Index: /branches/rel10_ifa/psModules/src/astrom/pmConcepts.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmConcepts.c	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmConcepts.c	(revision 6804)
@@ -398,5 +398,5 @@
         {
             psMetadataItem *cellReaddir = psMetadataItemAllocS32("CELL.READDIR",
-                                          "Read direction, rows=1, cols=2", 1);
+                                          "Read direction, rows=1, cols=2", 0);
             pmConceptRegister(cellReaddir, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
             psFree(cellReaddir);
Index: /branches/rel10_ifa/psModules/src/astrom/pmConceptsRead.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmConceptsRead.c	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmConceptsRead.c	(revision 6804)
@@ -6,5 +6,5 @@
 #include "pmFPA.h"
 #include "pmHDU.h"
-#include "pmHDUGetLowest.h"
+#include "pmHDUUtils.h"
 #include "pmConcepts.h"
 #include "pmConceptsRead.h"
Index: /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmConceptsWrite.c	(revision 6804)
@@ -5,5 +5,5 @@
 #include "pmFPA.h"
 #include "pmHDU.h"
-#include "pmHDUGetLowest.h"
+#include "pmHDUUtils.h"
 #include "pmConcepts.h"
 #include "pmConceptsRead.h"
@@ -31,8 +31,11 @@
         switch (item2->type) {
         case PS_TYPE_S32:
+            psTrace(__func__, 10, "Comparing %d and %d...\n", item1->data.S32, item2->data.S32);
             return (item1->data.S32 == item2->data.S32) ? true : false;
         case PS_TYPE_F32:
+            psTrace(__func__, 10, "Comparing %d and %d...\n", item1->data.S32, (int)item2->data.F32);
             return (item1->data.S32 == (int)item2->data.F32) ? true : false;
         case PS_TYPE_F64:
+            psTrace(__func__, 10, "Comparing %d and %d...\n", item1->data.S32, (int)item2->data.F64);
             return (item1->data.S32 == (int)item2->data.F64) ? true : false;
         default:
@@ -42,8 +45,11 @@
         switch (item2->type) {
         case PS_TYPE_S32:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, (float)item2->data.S32);
             return (item1->data.F32 == (float)item2->data.S32) ? true : false;
         case PS_TYPE_F32:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, item2->data.F32);
             return (item1->data.F32 == item2->data.F32) ? true : false;
         case PS_TYPE_F64:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, (float)item2->data.F64);
             return (item1->data.F32 == (float)item2->data.F64) ? true : false;
         default:
@@ -53,8 +59,11 @@
         switch (item2->type) {
         case PS_TYPE_S32:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, (double)item2->data.S32);
             return (item1->data.F64 == (double)item2->data.S32) ? true : false;
         case PS_TYPE_F32:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, (double)item2->data.F32);
             return (item1->data.F64 == (double)item2->data.F32) ? true : false;
         case PS_TYPE_F64:
+            psTrace(__func__, 10, "Comparing %f and %f...\n", item1->data.F32, item2->data.F64);
             return (item1->data.F64 == item2->data.F64) ? true : false;
         default:
@@ -66,4 +75,5 @@
             return false;
         }
+        psTrace(__func__, 10, "Comparing '%s' and '%s'\n", item1->data.V, item2->data.V);
         return (strcasecmp(item1->data.V, item2->data.V) == 0) ? true : false;
     default:
@@ -230,5 +240,4 @@
 }
 
-// XXX: Needs the .DEPEND stuff
 bool pmConceptsWriteToDefaults(psMetadata *specs, // The concept specifications
                                pmFPA *fpa, // The FPA
@@ -283,5 +292,5 @@
                 if (! compareConcepts(defaultItem, formatted)) {
                     psLogMsg(__func__, PS_LOG_WARN, "Concept %s is specified by the DEFAULTS in the camera "
-                             "format, but the values don't match.\n");
+                             "format, but the values don't match.\n", name);
                 }
                 psFree(formatted);
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPA.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPA.h	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPA.h	(revision 6804)
@@ -7,6 +7,6 @@
 *  @author GLG, MHPCC
 *
-*  @version $Revision: 1.1.4.5 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2006-03-28 02:16:26 $
+*  @version $Revision: 1.1.4.6 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-04-06 00:28:28 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -222,11 +222,13 @@
 bool pmCellSetDataStatus (pmCell *cell, bool status);
 
-/** FUNC DESC
- *
- *
- *
- *
- */
-
+/** Specify the level for an operation.
+ */
+typedef enum {
+    PM_FPA_LEVEL_NONE,                  ///< No particular level specified
+    PM_FPA_LEVEL_FPA,                   ///< Level corresponds to an FPA
+    PM_FPA_LEVEL_CHIP,                  ///< Level corresponds to a Chip
+    PM_FPA_LEVEL_CELL,                  ///< Level corresponds to a Cell
+    PM_FPA_LEVEL_READOUT                ///< Level corresponds to a Readout
+} pmFPALevel;
 
 
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAConstruct.c	(revision 6804)
@@ -35,33 +35,53 @@
 }
 
-// Parse a list of first:second pairs in a string
-static bool parsePairs(psArray **first, // Array of the first values
-                       psArray **second, // Array of the second values
-                       const char *string // The string to parse
-                      )
+// Parse a list of first:second:third pairs in a string
+static bool parseContent(psArray **first, // Array of the first values
+                         psArray **second, // Array of the second values
+                         psArray **third, // Array of the third values
+                         const char *string // The string to parse
+                        )
 {
     bool allOK = true;                  // Everything was OK?
-    psList *pairs = psStringSplit(string, " ,;"); // List of the pairs
-    *first = psArrayAlloc(pairs->n);
-    *second = psArrayAlloc(pairs->n);
+    psList *values = psStringSplit(string, " ,;"); // List of the parts
+    *first = psArrayAlloc(values->n);
+    *second = psArrayAlloc(values->n);
+    *third = psArrayAlloc(values->n);
     int num = 0;
-    psListIterator *pairsIter = psListIteratorAlloc(pairs, PS_LIST_HEAD, false); // Iterator for pairs
-    psString pair = NULL;               // "first:second" pair string
-    while ((pair = psListGetAndIncrement(pairsIter))) {
-        psList *firstSecond = psStringSplit(pair, ":"); // List containing the first and second
-        if (firstSecond->n != 2) {
-            psLogMsg(__func__, PS_LOG_WARN, "Badly formated first:second pair: %s --- ignored.\n", pair);
+    psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); // Iterator for values
+    psString value = NULL;               // "first:second:third" string
+    while ((value = psListGetAndIncrement(valuesIter))) {
+        psList *firstSecondThird = psStringSplit(value, ":"); // List containing the first, second, third
+        psArray *fst = psListToArray(firstSecondThird); // An array representation
+        psFree(firstSecondThird);
+        psString firstPart = NULL;      // The first part
+        psString secondPart = NULL;     // The second part
+        psString thirdPart = NULL;      // The third part
+        switch (firstSecondThird->n) {
+        case 1:
+            thirdPart = fst->data[0];
+            break;
+        case 2:
+            secondPart = fst->data[0];
+            thirdPart = fst->data[1];
+            break;
+        case 3:
+            firstPart = fst->data[0];
+            secondPart = fst->data[1];
+            thirdPart = fst->data[2];
+            break;
+        default:
+            psLogMsg(__func__, PS_LOG_WARN, "Badly formated specifier: %s --- ignored.\n", value);
             allOK = false;
+            psFree(fst);
             continue;
         }
-        psString firstBit = psListGet(firstSecond, PS_LIST_HEAD); // The first bit
-        psString secondBit = psListGet(firstSecond, PS_LIST_TAIL); // The second bit
-        psArraySet(*first, num, firstBit);
-        psArraySet(*second, num, secondBit);
+        psArraySet(*first, num, firstPart);
+        psArraySet(*second, num, secondPart);
+        psArraySet(*third, num, thirdPart);
         num++;
-        psFree(firstSecond);
-    }
-    psFree(pairsIter);
-    psFree(pairs);
+        psFree(fst);
+    }
+    psFree(valuesIter);
+    psFree(values);
 
     return allOK;
@@ -77,5 +97,4 @@
     psString keyword = psMetadataLookupStr(&mdok, format, name);
     if (!mdok || strlen(keyword) == 0) {
-        psError(PS_ERR_IO, false, "Unable to find %s in the FILE.\n", name);
         return false;
     }
@@ -86,4 +105,219 @@
     }
     return psMetadataItemParseString(resultItem);
+}
+
+// Add an HDU to the FPA
+static bool addHDUtoFPA(pmFPA *fpa,     // FPA to which to add
+                        pmHDU *hdu      // HDU to be added
+                       )
+{
+    assert(fpa);
+    assert(hdu);
+
+    if (fpa->hdu) {
+        // Something's already here
+        if (fpa->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since FPA already has one.\n");
+        }
+        return false;
+    }
+    fpa->hdu = psMemIncrRefCounter(hdu);
+    if (hdu->header) {
+        pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL);
+    }
+    pmFPASetFileStatus(fpa, true);
+
+    return true;
+}
+
+// Add an HDU to the chip
+static bool addHDUtoChip(pmChip *chip,  // Chip to which to add
+                         pmHDU *hdu     // HDU to be added
+                        )
+{
+    assert(chip);
+    assert(hdu);
+
+    if (chip->hdu) {
+        // Something's already here
+        if (chip->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since chip already has one.\n");
+        }
+        return false;
+    }
+    chip->hdu = psMemIncrRefCounter(hdu);
+    if (hdu->header) {
+        pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER, true, NULL);
+    }
+    pmChipSetFileStatus(chip, true);
+
+    return true;
+}
+
+// Add an HDU to the cell
+static bool addHDUtoCell(pmCell *cell,  // Cell to which to add
+                         pmHDU *hdu     // HDU to be added
+                        )
+{
+    assert(cell);
+    assert(hdu);
+
+    if (cell->hdu) {
+        // Something's already here
+        if (cell->hdu != hdu) {
+            psError(PS_ERR_IO, true, "Unable to add HDU since cell already has one.\n");
+        }
+        return false;
+    }
+    cell->hdu = psMemIncrRefCounter(hdu);
+    if (hdu->header) {
+        pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, true, NULL);
+    }
+    pmCellSetFileStatus(cell, true);
+
+    return true;
+}
+
+
+// Looks up the particular content based on the header
+static const char *getContent(psMetadata *format, // The FORMAT from the camera format configuration
+                              psMetadata *contents, // The CONTENTS from the camera format configuration
+                              psMetadata *header // The (primary) header
+                             )
+{
+    bool mdok = true;                   // Status of MD lookup
+    const char *contentHeaders = psMetadataLookupStr(&mdok, format, "CONTENT"); // Headers for content
+    if (!mdok || !contentHeaders || strlen(contentHeaders) == 0) {
+        psError(PS_ERR_IO, true, "Unable to find CONTENT in FORMAT.\n");
+        return NULL;
+    }
+
+    psList *keywords = psStringSplit(contentHeaders, " ,;"); // List of keywords
+    psListIterator *keywordsIter = psListIteratorAlloc(keywords, PS_LIST_HEAD, false); // Iterator
+    psString keyword = NULL;        // Keyword, from iteration
+    psString contentsKey = NULL;    // Key to the CONTENTS menu
+    bool first = true;              // Is it the first value?
+    while ((keyword = psListGetAndIncrement(keywordsIter))) {
+        const char *value = psMetadataLookupStr(&mdok, header, keyword);
+        if (first) {
+            psStringAppend(&contentsKey, "%s", value);
+            first = false;
+        } else {
+            psStringAppend(&contentsKey, "_%s", value);
+        }
+    }
+    psTrace(__func__, 5, "Looking up %s in the CONTENTS.\n", contentsKey);
+    const char *content = psMetadataLookupStr(&mdok, contents, contentsKey);
+    if (!mdok || !content || strlen(content) == 0) {
+        psError(PS_ERR_IO, true, "Unable to find %s in the CONTENTS.\n", contentsKey);
+        return NULL;
+    }
+    psFree(contentsKey);
+
+    return content;
+}
+
+
+// Given a (string) list of contents "chip:cell:type chip:cell:type", put the HDU in the correct place and
+// plug in the cell configuration information
+static int processContents(pmFPA *fpa,  // The FPA
+                           pmChip *chip, // The chip, or NULL
+                           pmCell *cell, // The cell, or NULL
+                           pmHDU *hdu,  // The HDU to be added
+                           pmFPALevel level, // The level at which to add the HDU
+                           const char *contents, // The contents line, consisting of a list of chip:cell
+                           psMetadata *format // Camera format configuration
+                          )
+{
+    assert(fpa);
+    assert(contents && strlen(contents) > 0);
+    assert(!cell || (cell && chip));    // Need both chip and cell if given a cell
+
+    if (hdu && level == PM_FPA_LEVEL_FPA) {
+        addHDUtoFPA(fpa, hdu);
+    }
+
+    // Parse the list of chip:cell:type
+    psArray *chips = NULL;              // The chips (first bits)
+    psArray *cells = NULL;              // The cells (second bits)
+    psArray *types = NULL;              // The cell types (third bits)
+    int numCells = 0;                   // Number of cells processed
+    parseContent(&chips, &cells, &types, contents);
+    for (int i = 0; i < types->n; i++) {
+        psString chipName = chips->data[i]; // The name of the chip
+        psString cellName = cells->data[i]; // The name of the cell
+        psString cellType = types->data[i]; // The type of the cell
+
+        // Get the chip
+        pmChip *newChip = NULL;         // The chip specified
+        if (chip) {
+            newChip = chip;
+        } else if (chipName) {
+            // Find the chip
+            int chipNum = pmFPAFindChip(fpa, chipName); // The chip we're looking for
+            if (chipNum == -1) {
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to find chip %s in fpa --- ignored.\n", chipName);
+                continue;
+            }
+            newChip = fpa->chips->data[chipNum];
+        }
+
+        if (!newChip) {
+            psLogMsg(__func__, PS_LOG_WARN, "Unable to determine chip for entry %d of content (follows) --- "
+                     "ignored.\n\t%s", i, contents);
+            continue;
+        }
+
+        // Get the cell
+        pmCell *newCell = NULL;         // The cell specified
+        if (cell) {
+            newCell = cell;
+        } else if (cellName) {
+            // Find the cell
+            int cellNum = pmChipFindCell(newChip, cellName); // The cell we're looking for
+            if (cellNum == -1) {
+                psLogMsg(__func__, PS_LOG_WARN, "Unable to find cell %s in chip %s --- ignored.\n",
+                         cellName, chipName);
+                continue;
+            }
+            newCell = newChip->cells->data[cellNum];
+        }
+        if (!newCell) {
+            psLogMsg(__func__, PS_LOG_WARN, "Unable to determine cell for entry %d of content (follows) --- "
+                     "ignored.\n\t%s", i, contents);
+            continue;
+        }
+
+        // Get the type
+        if (!cellType) {
+            psLogMsg(__func__, PS_LOG_WARN, "Unable to determine cell type for entry %d of content (follows) "
+                     "--- ignored.\n\t%s", i, contents);
+            continue;
+        }
+        psMetadata *cellData = getCellData(format, cellType); // Data for this cell
+
+        // Put in the HDU
+        if (hdu && level == PM_FPA_LEVEL_CHIP) {
+            addHDUtoChip(newChip, hdu);
+        }
+        if (hdu && level == PM_FPA_LEVEL_CELL) {
+            addHDUtoCell(newCell, hdu);
+        }
+
+        // Put in the cell data
+        if (newCell->config) {
+            psLogMsg(__func__, PS_LOG_WARN, "Overwriting cell data in chip %s, cell %s\n", chipName,
+                     cellName);
+            psFree(newCell->config); // Make way!
+        }
+        newCell->config = psMemIncrRefCounter(cellData);
+        pmConceptsReadCell(newCell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
+        numCells++;
+    }
+    psFree(chips);
+    psFree(cells);
+    psFree(types);
+
+    return numCells;
 }
 
@@ -137,8 +371,4 @@
     assert(format);
 
-    pmChip *chip = NULL;                // The chip, if any one in particular
-    pmCell *cell = NULL;                // The cell, if any one in particular
-    psString phuChipName = NULL;        // Name of the chip from the PHU
-
     bool mdok = true;                   // Status from metadata lookups
     psMetadata *formatSpec = psMetadataLookupMD(&mdok, format, "FILE"); // The format specification
@@ -149,22 +379,9 @@
 
     // Check the name of the FPA
-    const char *nameKeyword = psMetadataLookupStr(&mdok, formatSpec, "FPA.NAME"); // Keyword that gives name
-    if (!mdok || strlen(nameKeyword) == 0) {
-        psError(PS_ERR_IO, false, "Unable to find FPA.NAME in the format specification.\n");
-        return NULL;
-    }
-    psMetadataItem *fpaNameItem = psMetadataLookup(phu, nameKeyword); // Name of the FPA
-    if (!fpaNameItem) {
-        psError(PS_ERR_IO, false, "Unable to find keyword %s with the name of the FPA.\n", nameKeyword);
-        return NULL;
-    }
-    const char *newFPAname = psMetadataItemParseString(fpaNameItem); // FPA.NAME for new source
-    fpaNameItem = psMetadataLookup(fpa->concepts, "FPA.NAME"); // Current name of FPA
-    if (fpaNameItem && fpaNameItem->type == PS_DATA_STRING) {
-        const char *currentFPAname = fpaNameItem->data.V; // Name of the current FPA
-        if (currentFPAname && strlen(currentFPAname) > 0 && strcmp(currentFPAname, newFPAname) != 0) {
-            psLogMsg(__func__, PS_LOG_WARN, "FPA.NAME for new source (%s) doesn't match FPA.NAME for current "
-                     "fpa (%s).\n", newFPAname, currentFPAname);
-        }
+    psString newFPAname = phuNameFromHeader("FPA.NAME", formatSpec, phu); // New name for the FPA
+    const char *currentFPAname = psMetadataLookupStr(&mdok, fpa->concepts, "FPA.NAME"); // Current name
+    if (mdok && currentFPAname && strlen(currentFPAname) > 0 && strcmp(currentFPAname, newFPAname) != 0) {
+        psLogMsg(__func__, PS_LOG_WARN, "FPA.NAME for new source (%s) doesn't match FPA.NAME for current "
+                 "fpa (%s).\n", newFPAname, currentFPAname);
     }
     psMetadataAddStr(fpa->concepts, PS_LIST_HEAD, "FPA.NAME", PS_META_REPLACE, "Name of FPA", newFPAname);
@@ -180,5 +397,4 @@
     phdu->header = psMemIncrRefCounter(phu);
     phdu->format = psMemIncrRefCounter(format);
-
     // Generate the view
     pmFPAview *view = pmFPAviewAlloc(0); // The FPA view corresponding to the PHU, to be returned
@@ -186,63 +402,119 @@
     view->cell = -1;
     view->readout = -1;
-    if (strcasecmp(phuType, "FPA") == 0) {
-        if (fpa->hdu) {
-            // Something's already here
-            psError(PS_ERR_IO, true, "Unable to add source since FPA already has a PHU.\n");
+
+    // And what are the individual extensions?
+    const char *extType = psMetadataLookupStr(&mdok, formatSpec, "EXTENSIONS"); // What's in the extns?
+    if (!mdok || strlen(extType) == 0) {
+        psError(PS_ERR_IO, false, "Unable to find EXTENSIONS in the format specification.\n");
+        psFree(view);
+        return NULL;
+    }
+
+
+    // This is a special case: PHU=FPA and EXTENSIONS=NONE.  The only reason to do this is in the case of
+    // single CCD imagers, where the entire FPA is in the PHU image.  In this case, the CONTENTS is of type
+    // STR (rather than METADATA), and has the usual chip:cell.
+    if (strcasecmp(phuType, "FPA") == 0 && strcasecmp(extType, "NONE") == 0) {
+        const char *contents = psMetadataLookupStr(&mdok, format, "CONTENTS"); // The contents of the file
+        if (!mdok || !contents || strlen(contents) == 0) {
+            psError(PS_ERR_IO, true, "Unable to find CONTENTS in the camera format configuration.\n");
             psFree(view);
             return NULL;
         }
-        fpa->hdu = phdu;
-        pmConceptsReadFPA(fpa, PM_CONCEPT_SOURCE_HEADER, NULL);
-        pmFPASetFileStatus (fpa, true);
+
+        processContents(fpa, NULL, NULL, phdu, PM_FPA_LEVEL_FPA, contents, format);
+        psFree(phdu);
+        return view;
+    }
+
+    // In all other cases, the CONTENTS is of type METADATA, and is either a menu if EXTENSIONS=NONE, or
+    // a list of extensions otherwise.
+    psMetadata *contents = psMetadataLookupMD(&mdok, format, "CONTENTS"); // The contents of the FITS file
+    if (!mdok || !contents) {
+        psError(PS_ERR_IO, false, "Unable to find CONTENTS in the camera format configuration.\n");
+        psFree(view);
+        return NULL;
+    }
+
+    // No extensions --- only have the PHU.  In this case, the CONTENTS is a menu, with CONTENT indicating
+    // header keywords that provides a key to the CONTENTS menu.
+    if (strcasecmp(extType, "NONE") == 0) {
+        // We have already dealt with the case PHU=FPA, in a special case, above.
+        const char *content = getContent(formatSpec, contents, phu); // The content: string of chip:cell pairs
+
+        // Need to look up what chip we have.
+        const char *chipName = phuNameFromHeader("CHIP.NAME", formatSpec, phu);
+        psTrace(__func__, 5, "This is chip %s\n", chipName);
+        int chipNum = pmFPAFindChip(fpa, chipName); // Chip number
+        if (chipNum == -1) {
+            psError(PS_ERR_IO, true, "Unable to find chip %s in FPA.\n", chipName);
+            psFree(view);
+            return NULL;
+        }
+        pmChip *chip = fpa->chips->data[chipNum]; // Chip of interest
+        view->chip = chipNum;
+
+        pmCell *cell = NULL;            // Cell of interest
+
+        pmFPALevel level = PM_FPA_LEVEL_NONE; // Level for HDU to be added
+        if (strcasecmp(phuType, "CHIP") == 0) {
+            level = PM_FPA_LEVEL_CHIP;
+        } else if (strcasecmp(phuType, "CELL") == 0) {
+            level = PM_FPA_LEVEL_CELL;
+            // Need to look up what cell we have.
+            const char *cellName = phuNameFromHeader("CELL.NAME", formatSpec, phu);
+            int cellNum = pmChipFindCell(chip, cellName); // Cell number
+            if (cellNum == -1) {
+                psError(PS_ERR_IO, true, "Unable to find cell %s in chip %s.\n", cellName, chipName);
+                psFree(view);
+                return NULL;
+            }
+            cell = chip->cells->data[cellNum];
+            view->cell = cellNum;
+        } else {
+            psError(PS_ERR_IO, true, "PHU is not FPA, CHIP or CELL.\n");
+            psFree(view);
+            return NULL;
+        }
+
+        processContents(fpa, chip, cell, phdu, level, content, format);
+        psFree(phdu);
+        return view;
+    }
+
+
+    // From here on, we have extensions that we iterate through.  The CONTENTS is a list of extensions.
+    pmChip *chip = NULL;                // The chip of interest
+    pmCell *cell = NULL;                // The cell of interest
+
+    // First, put in the PHU
+    if (strcasecmp(phuType, "FPA") == 0) {
+        addHDUtoFPA(fpa, phdu);
     } else {
         // Get the chip
-        phuChipName = phuNameFromHeader("CHIP.NAME", formatSpec, phu); // Name of the chip
-        int chipNum = pmFPAFindChip(fpa, phuChipName); // Chip number
+        const char *chipName = phuNameFromHeader("CHIP.NAME", formatSpec, phu); // Name of the chip
+        int chipNum = pmFPAFindChip(fpa, chipName); // Chip number
         if (chipNum == -1) {
-            psError(PS_ERR_IO, true, "Unable to find chip %s in FPA.\n", phuChipName);
+            psError(PS_ERR_IO, true, "Unable to find chip %s in FPA.\n", chipName);
             psFree(view);
             return NULL;
         }
-        chip = fpa->chips->data[chipNum];
+        chip = fpa->chips->data[chipNum]; // The specified chip
         view->chip = chipNum;
 
         if (strcasecmp(phuType, "CHIP") == 0) {
-            if (chip->hdu) {
-                // Something's already here
-                psError(PS_ERR_IO, true, "Unable to add source since chip already has a PHU.\n");
-                psFree (view);
-                return NULL;
-            }
-            chip->hdu = phdu;
-            pmConceptsReadChip(chip, PM_CONCEPT_SOURCE_HEADER, true, NULL);
-            pmChipSetFileStatus (chip, true);
+            addHDUtoChip(chip, phdu);
         } else if (strcasecmp(phuType, "CELL") == 0) {
-            psError(PS_ERR_IO, true, "Not yet sure how to handle PHU=CELL.\n");
-            psFree(view);
-            return NULL;
-            #if 0
-            // Added this for possible future plans which might allow PHU=CELL
-            phuCellName = phuNameFromHeader("CELL.NAME", formatSpec, phu); // Name of the cell
-            int cellNum = pmChipFindCell(chip, phuCellName); // Cell number
+            const char *cellName = phuNameFromHeader("CELL.NAME", formatSpec, phu); // Name of the cell
+            int cellNum = pmChipFindCell(chip, cellName); // Cell number
             if (cellNum == -1) {
-                psError(PS_ERR_IO, true, "Unable to find cell %s in chip %s.\n", phuCellName, phuChipName);
+                psError(PS_ERR_IO, true, "Unable to find cell %s in chip %s.\n", cellName, chipName);
                 psFree(view);
                 return NULL;
             }
-            cell = chip->cells->data[cellNum];
+            cell = chip->cells->data[cellNum]; // The specified cell
             view->cell = cellNum;
 
-            if (cell->hdu) {
-                // Something's already here
-                psError(PS_ERR_IO, true, "Unable to add source since cell already has a PHU.\n");
-                psFree(view);
-                return NULL;
-            }
-            cell->hdu = phdu;
-            pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, true, NULL);
-            pmCellSetFileStatus (cell, true);
-            #endif
-
+            addHDUtoCell(cell, phdu);
         } else {
             psError(PS_ERR_IO, true, "The format of the PHU (%s) is not FPA, CHIP or CELL.\n", phuType);
@@ -251,87 +523,19 @@
         }
     }
-
-    // And the individual extensions?
-    const char *extType = psMetadataLookupStr(&mdok, formatSpec, "EXTENSIONS"); // What's in the extns?
-    if (!mdok || strlen(extType) == 0) {
-        psError(PS_ERR_IO, false, "Unable to find EXTENSIONS in the format specification.\n");
+    psFree(phdu);
+
+    // Where do we stick in the HDUs?
+    pmFPALevel hduLevel = PM_FPA_LEVEL_NONE; // Level for HDU insertion
+    if (strcasecmp(extType, "CHIP") == 0) {
+        hduLevel = PM_FPA_LEVEL_CHIP;
+    } else if (strcasecmp(extType, "CELL") == 0) {
+        hduLevel = PM_FPA_LEVEL_CELL;
+    } else {
+        psError(PS_ERR_IO, true, "EXTENSIONS is not CHIP or CELL or NONE.\n");
         psFree(view);
         return NULL;
     }
-    psMetadata *contents = psMetadataLookupMD(&mdok, format, "CONTENTS"); // The contents of the FITS file
-    if (!mdok || !contents) {
-        psError(PS_ERR_IO, false, "Unable to find CONTENTS in the camera format configuration.\n");
-        psFree(view);
-        return NULL;
-    }
-
-
-    // Now, different actions, according to what's in the file:
-
-    // No extensions --- it's all in the PHU
-    if (strcasecmp(extType, "NONE") == 0) {
-        if (strcasecmp(phuType, "FPA") == 0) {
-            psError(PS_ERR_IO, true, "Not sure how to handle the case PHU=FPA, EXTENSIONS=NONE.\n");
-            psFree(view);
-            return NULL;
-        }
-        if (strcasecmp(phuType, "CELL") == 0) {
-            psError(PS_ERR_IO, true, "Not sure how to handle the case PHU=CELL, EXTENSIONS=NONE.\n");
-            psFree(view);
-            return NULL;
-        }
-
-        psString content = psMetadataLookupStr(&mdok, contents, phuChipName); // The content line
-        if (!mdok || strlen(content) == 0) {
-            psError(PS_ERR_IO, true, "Cannot find chip %s in the list of CONTENTS.\n", phuChipName);
-            psFree(view);
-            return NULL;
-        }
-
-        // Parse the list of first:second
-        psArray *names = NULL;          // The first bits
-        psArray *values = NULL;         // The second bits
-        parsePairs(&names, &values, content);
-        for (int i = 0; i < names->n; i++) {
-            psString chipName = names->data[i]; // The name of the chip specified
-            if (phuChipName && strcmp(phuChipName, chipName) != 0) {
-                psLogMsg(__func__, PS_LOG_WARN, "Chip name in CONTENT (%s) does not match chip name from PHU "
-                         "(%s) --- there may be problems when reading!\n", chipName, phuChipName);
-                // Find the other chip
-                int chipNum = pmFPAFindChip(fpa, chipName); // The chip we're looking for
-                if (chipNum == -1) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to find chip %s in fpa --- ignored.\n", chipName);
-                    continue;
-                }
-                chip = fpa->chips->data[chipNum];
-            }
-            psString cellName = values->data[i]; // The name of the cell specified
-            int cellNum = pmChipFindCell(chip, cellName); // The cell we're looking for
-            if (cellNum == -1) {
-                psLogMsg(__func__, PS_LOG_WARN, "Unable to find cell %s in chip %s --- ignored.\n",
-                         cellName, chipName);
-                continue;
-            }
-            cell = chip->cells->data[cellNum];
-
-            psMetadata *cellData = getCellData(format, cellName); // Data for this cell
-
-            // Have already plugged in the PHU, which is all we have
-
-            // Put in the cell data
-            if (cell->config) {
-                psLogMsg(__func__, PS_LOG_WARN, "Overwriting cell data in chip %s, cell %s\n", chipName,
-                         cellName);
-                psFree(cell->config); // Make way!
-            }
-            cell->config = psMemIncrRefCounter(cellData);
-            pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
-        }
-
-        return view;
-    }
-
-
-    // Otherwise, go through the contents
+
+    // Now go through the contents
     psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL);
     psMetadataItem *contentsItem = NULL; // Item from contents
@@ -346,119 +550,6 @@
         hdu->format = psMemIncrRefCounter(format);
 
-        // Parse the list of first:second
-        psArray *names = NULL;          // The first bits
-        psArray *values = NULL;         // The second bits
-        parsePairs(&names, &values, contentsItem->data.V);
-
-        // XXX Memory problems in here --> leaks and/or double frees???
-        if (strcasecmp(extType, "CHIP") == 0) {
-            // Extensions are chips
-            for (int i = 0; i < names->n; i++) {
-                psString chipName = names->data[i]; // The name of the chip
-                psString cellName = values->data[i]; // The name of the cell
-                int chipNum = pmFPAFindChip(fpa, chipName); // The chip we're looking for
-                if (chipNum == -1) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to find chip %s in FPA --- ignored.\n", chipName);
-                    continue;
-                }
-                chip = fpa->chips->data[chipNum];
-                int cellNum = pmChipFindCell(chip, cellName); // The cell we're looking for
-                if (cellNum == -1) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to find cell %s in chip %s --- ignored\n",
-                             cellName, chipName);
-                    continue;
-                }
-                pmCell *cell = chip->cells->data[cellNum];
-                psMetadata *cellData = getCellData(format, cellName); // Data for this cell
-
-                // Put in the extension
-                if (chip->hdu && chip->hdu != hdu) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Overwriting HDU in chip %s\n", chipName);
-                    psFree(chip->hdu);  // Make way!
-                    chip->hdu = NULL;
-                }
-                if (!chip->hdu) {
-                    chip->hdu = psMemIncrRefCounter(hdu);
-                }
-
-                // Put in the cell data
-                if (cell->config) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Overwriting cell data in chip %s, cell %s\n", chipName,
-                             cellName);
-                    psFree(cell->config); // Make way!
-                }
-                cell->config = psMemIncrRefCounter(cellData);
-                pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
-            }
-
-        } else if (strcasecmp(extType, "CELL") == 0) {
-            // Extensions are cells
-            psString chipName = NULL;   // Name of chip under consideration
-            pmChip *chip = NULL;        // The chip we're looking for
-            #if 1
-            // Think I'm doing this at the start now
-            if (!fpa->hdu || !fpa->hdu->phu) {
-                // Need to look up the name of the chip
-                chipName = phuNameFromHeader("CHIP.NAME", formatSpec, phu);
-                int chipNum = pmFPAFindChip(fpa, chipName);
-                if (chipNum == -1) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to find chip %s in FPA --- ignored.\n", chipName);
-                    continue;
-                }
-                chip = fpa->chips->data[chipNum];
-            }
-            #endif
-            for (int i = 0; i < names->n; i++) {
-                psString cellType = values->data[i]; // The type of the cell
-                psString cellName = NULL; // The name of the cell
-                if (fpa->hdu && fpa->hdu->phu) {
-                    // We've got chipName:cellType with cellType == cellName
-                    chipName = names->data[i];
-                    cellName = cellType;
-                    int chipNum = pmFPAFindChip(fpa, chipName); // The chip we're looking for
-                    if (chipNum == -1) {
-                        psLogMsg(__func__, PS_LOG_WARN, "Unable to find chip %s in FPA --- ignored.\n",
-                                 chipName);
-                        continue;
-                    }
-                    chip = fpa->chips->data[chipNum];
-                } else {
-                    // We've got cellName:cellType and the chipName comes from before
-                    cellName = names->data[i];
-                }
-                int cellNum = pmChipFindCell(chip, cellName); // The cell we're looking for
-                if (cellNum == -1) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to find cell %s in chip %s --- ignored.\n",
-                             cellName, chipName);
-                    continue;
-                }
-                pmCell *cell = chip->cells->data[cellNum];
-                psMetadata *cellData = getCellData(format, cellType); // Data for this cell
-
-                // Put in the extension
-                if (cell->hdu && cell->hdu != hdu) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Overwriting HDU in chip %s, cell %s\n", chipName,
-                             cellName);
-                    psFree(cell->hdu);
-                    cell->hdu = NULL;
-                }
-                if (! cell->hdu) {
-                    cell->hdu = psMemIncrRefCounter(hdu);
-                }
-
-                // Put in the cell data
-                if (cell->config) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Overwriting cell data in chip %s, cell %s\n", chipName,
-                             cellName);
-                    psFree(cell->config);
-                }
-                cell->config = psMemIncrRefCounter(cellData);
-                pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
-            }
-
-        }
+        processContents(fpa, chip, cell, hdu, hduLevel, contentsItem->data.V, format);
         psFree(hdu);
-        psFree(names);
-        psFree(values);
     }
     psFree(contentsIter);
@@ -468,222 +559,4 @@
     return view;
 }
-
-
-
-
-#if 0
-pmFPA *pmFPAConstruct(const psMetadata *camera // The camera configuration
-                     )
-{
-    pmFPA *fpa = pmFPAAlloc(camera);    // The FPA to fill out
-
-    bool mdStatus = true;               // Status from metadata lookups
-    const char *phuType = psMetadataLookupStr(&mdStatus, camera, "PHU"); // What is the PHU?
-    const char *extType = psMetadataLookupStr(&mdStatus, camera, "EXTENSIONS"); // What's in the extns?
-
-    if (strcasecmp(phuType, "FPA") == 0) {
-        // The FITS file contains an entire FPA
-
-        psMetadata *contents = psMetadataLookupMD(&mdStatus, camera, "CONTENTS"); // The CONTENTS
-        if (! mdStatus) {
-            psError(PS_ERR_IO, false, "Unable to determine CONTENTS of camera.\n");
-            psFree(fpa);
-            return NULL;
-        }
-
-        // Set up iteration over the contents
-        psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL);
-        psMetadataItem *contentItem = NULL; // Item from the metadata
-
-        if (strcasecmp(extType, "CHIP") == 0) {
-            // Extensions are chips; Content contains a list of cells
-            while ((contentItem = psMetadataGetAndIncrement(contentsIter))) {
-                psString extName = contentItem->name; // The name of the extension
-                pmChip *chip = pmChipAlloc(fpa, extName); // The chip
-                chip->hdu = p_pmHDUAlloc(extName); // Prepare chip to receive FITS data
-                if (contentItem->type != PS_DATA_STRING) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Type of content item (%x) is not string: ignored\n",
-                             contentItem->type);
-                    continue;
-                }
-
-                const char *content = contentItem->data.V; // The content of the extension
-                psTrace(__func__, 7, "Content of %s is: %s\n", extName, content);
-                psList *cellNames = psStringSplit(content, " ,"); // A list of the component cells
-                psListIterator *cellNamesIter = psListIteratorAlloc(cellNames, PS_LIST_HEAD, NULL);
-                char *cellName = NULL; // The name of a cell
-                while ((cellName = psListGetAndIncrement(cellNamesIter))) {
-                    // Get the cell data
-                    psMetadata *cellData = getCellData(camera, cellName);
-                    pmCell *cell = pmCellAlloc(chip, cellData, cellName); // The cell
-                    psFree(cell);       // Drop reference
-                    //                    psFree(cellData);   // Drop reference
-                }
-                psFree(cellNamesIter);
-                psFree(cellNames);
-                psFree(chip);           // Drop reference
-            }
-
-        } else if (strcasecmp(extType, "CELL") == 0) {
-            // Extensions are cells; Content contains a chip name and cell type
-            psMetadata *chips = psMetadataAlloc(); // Given a chip name, holds the chip number
-            while ((contentItem = psMetadataGetAndIncrement(contentsIter))) {
-                psString extName = contentItem->name; // The name of the extension
-                psTrace(__func__, 1, "Getting %s....\n", extName);
-
-                if (contentItem->type != PS_DATA_STRING) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Type of content item (%x) is not string: ignored\n",
-                             contentItem->type);
-                    continue;
-                }
-                const char *content = contentItem->data.V; // The content of the extension
-                psList *contents = psStringSplit(content, ": "); // Split the name from the type
-                if (contents->n != 2) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Unable to read contents of %s: ignored.\n", extName);
-                } else {
-                    psString chipName = psListGet(contents, 0); // The name of the chip
-                    psString cellType = psListGet(contents, 1); // The type of cell
-                    psTrace(__func__, 7, "Extension is cell of type %s, from chip %s\n", cellType,
-                            chipName);
-
-                    psMetadataItem *chipItem = psMetadataLookup(chips, chipName); // Item containing the chip
-                    pmChip *chip = NULL; // The chip
-                    if (! chipItem) {
-                        chip = pmChipAlloc(fpa, chipName);
-                        psMetadataAdd(chips, PS_LIST_TAIL, chipName, PS_DATA_UNKNOWN, "", chip);
-                    } else {
-                        chip = psMemIncrRefCounter(chipItem->data.V);
-                    }
-                    // The cell
-                    psMetadata *cellData = getCellData(camera, cellType);
-                    pmCell *cell = pmCellAlloc(chip, cellData, extName); // The cell
-                    //                  psFree(cellData); // Drop reference
-                    cell->hdu = p_pmHDUAlloc(extName); // Prepare cell to receive FITS data
-
-                    psFree(cell);       // Drop reference
-                    psFree(chip);       // Drop reference
-                }
-                psFree(contents);
-            }
-            psFree(chips);
-
-        } else if (strcasecmp(extType, "NONE") == 0) {
-            // No extensions; Content contains metadata, each entry is a chip with its component cells
-            fpa->hdu = p_pmHDUAlloc("PHU"); // Prepare FPA to receive FITS data
-            while ((contentItem = psMetadataGetAndIncrement(contentsIter))) {
-                psString chipName = contentItem->name; // The name of the chip
-
-                if (contentItem->type != PS_DATA_STRING) {
-                    psLogMsg(__func__, PS_LOG_WARN, "Type of content item (%x) is not string: ignored\n",
-                             contentItem->type);
-                    continue;
-                }
-                psString content = contentItem->data.V; // The content of the extension
-                psTrace(__func__, 5, "Component cells are: %s\n", content);
-                pmChip *chip = pmChipAlloc(fpa, chipName); // The chip
-                psList *cellNames = psStringSplit(content, ", "); // Split the list of cells
-                psListIterator *cellNamesIter = psListIteratorAlloc(cellNames, PS_LIST_HEAD, false);
-                char *cellName = NULL; // Name of the cell
-                while ((cellName = psListGetAndIncrement(cellNamesIter))) {
-                    psTrace(__func__, 7, "Processing cell %s....\n", cellName);
-                    psMetadata *cellData = getCellData(camera, cellName);
-                    pmCell *cell = pmCellAlloc(chip, cellData, cellName); // The cell
-                    psFree(cell);       // Drop reference
-                    //                  psFree(cellData);   // Drop reference
-                }
-                psFree(cellNamesIter);
-                psFree(chip);           // Drop reference
-            }
-
-        } else {
-            psError(PS_ERR_IO, false, "EXTENSIONS in camera definition is not CHIP, CELL or NONE.\n");
-            psFree(fpa);
-            return NULL;
-        } // Type of extension
-
-        psFree(contentsIter);
-
-    } else if (strcasecmp(phuType, "CHIP") == 0) {
-        // The FITS file contains a single chip only
-        psString chipName = psStringCopy("CHIP"); // Name for chip
-        pmChip *chip = pmChipAlloc(fpa, chipName); // The chip
-
-        if (strcasecmp(extType, "NONE") == 0) {
-            // There are no extensions --- only the PHU
-            chip->hdu = p_pmHDUAlloc("PHU");
-
-            const char *contents = psMetadataLookupStr(&mdStatus, camera, "CONTENTS");
-            if (! mdStatus) {
-                psError(PS_ERR_IO, false, "Unable to determine CONTENTS of camera.\n");
-                psFree(fpa);
-                return NULL;
-            }
-            psList *cellNames = psStringSplit(contents, " ,"); // Names of cells
-            psListIterator *cellIter = psListIteratorAlloc(cellNames, PS_LIST_HEAD, false); // Iterator
-            psString cellName = NULL;
-            while ((cellName = psListGetAndIncrement(cellIter))) {
-                psMetadata *cellData = getCellData(camera, cellName);
-                pmCell *cell = pmCellAlloc(chip, cellData, cellName); // The cell
-                psFree(cell);
-            }
-            psFree(cellIter);
-            psFree(cellNames);
-
-        } else if (strcasecmp(extType, "CELL") == 0) {
-            // Extensions are cells
-            psMetadata *contents = psMetadataLookupMD(&mdStatus, camera, "CONTENTS"); // The CONTENTS
-            if (! mdStatus) {
-                psError(PS_ERR_IO, false, "Unable to determine CONTENTS of camera.\n");
-                psFree(fpa);
-                return NULL;
-            }
-
-            if (strcasecmp(extType, "CELL") != 0) {
-                psLogMsg(__func__, PS_LOG_WARN, "EXTENSIONS in camera definition is %s, but PHU is CHIP.\n"
-                         "EXTENSIONS assumed to be CELL.\n", extType);
-            }
-
-            // Iterate through the contents
-            psMetadataIterator *contentsIter = psMetadataIteratorAlloc(contents, PS_LIST_HEAD, NULL);
-            psMetadataItem *contentItem = NULL; // Item from metadata
-            while ((contentItem = psMetadataGetAndIncrement(contentsIter))) {
-                psString extName = contentItem->name; // The name of the extension
-                // Content is a cell type
-                if (contentItem->type != PS_DATA_STRING) {
-                    psLogMsg(__func__, PS_LOG_WARN,
-                             "CONTENT metadata for extension %s is not of type string, but %x --- ignored\n",
-                             extName, contentItem->type);
-                    continue;
-                }
-                const char *cellType = contentItem->data.V; // The type of cell
-                psTrace(__func__, 5, "Cell type is %s\n", cellType);
-                psMetadata *cellData = getCellData(camera, cellType);
-                pmCell *cell = pmCellAlloc(chip, cellData, extName); // The cell
-                //              psFree(cellData);
-                cell->hdu = p_pmHDUAlloc(extName); // Prepare cell to receive FITS data
-
-                psFree(cell);
-            } // Iterating through contents
-            psFree(contentsIter);
-
-        } else {
-            psError(PS_ERR_IO, false, "EXTENSIONS in camera definition is neither CELL or NONE.\n");
-            psFree(fpa);
-            return NULL;
-        }
-        psFree(chipName);
-        psFree(chip);                   // Drop reference
-
-    } else {
-        psError(PS_ERR_IO, true,
-                "The PHU type specified in the camera configuration (%s) is not FPA or CHIP.\n",
-                phuType);
-        psFree(fpa);
-        return NULL;
-    }
-
-    return fpa;
-}
-#endif
 
 
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c	(revision 6803)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPACopy.c	(revision 6804)
@@ -470,4 +470,5 @@
     bool yFlip = (psMetadataLookupS32(NULL, target->concepts, "CELL.YPARITY") !=
                   psMetadataLookupS32(NULL, source->concepts, "CELL.YPARITY")); // Switch parity in y?
+    psTrace(__func__, 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip);
 
     bool mdok = true;                   // Status of MD lookup
@@ -535,5 +536,6 @@
         psString name = conceptItem->name; // Name of concept
         if (strcmp(name, "CELL.TRIMSEC") != 0 && strcmp(name, "CELL.BIASSEC") != 0 &&
-                strcmp(name, "CELL.XPARITY") != 0 && strcmp(name, "CELL.YPARITY") != 0) {
+                strcmp(name, "CELL.XPARITY") != 0 && strcmp(name, "CELL.YPARITY") != 0 &&
+                strcmp(name, "CELL.X0") != 0 && strcmp(name, "CELL.Y0") != 0) {
             psMetadataAddItem(target->concepts, conceptItem, PS_LIST_TAIL, PS_META_REPLACE);
         }
@@ -543,12 +545,22 @@
     // Need to update CELL.X0 and CELL.Y0 if we flipped
     if (xFlip) {
-        psMetadataItem *xZero = psMetadataLookup(target->concepts, "CELL.X0"); // CELL.X0
+        int xZero = psMetadataLookupS32(NULL, source->concepts, "CELL.X0"); // CELL.X0 from source
+        int xParity = psMetadataLookupS32(NULL, target->concepts, "CELL.XPARITY"); // Parity in x
         pmReadout *readout = target->readouts->data[0]; // A representative readout
-        xZero->data.S32 -= readout->image->numCols - 1;
+        psTrace(__func__, 3, "CELL.X0: Before: %d After: %d\n", xZero,
+                xZero - (readout->image->numCols - 1) * xParity);
+        xZero -= (readout->image->numCols - 1) * xParity; // Change the parity on the X0 position
+        psMetadataItem *newItem = psMetadataLookup(target->concepts, "CELL.X0"); // CELL.X0 from target
+        newItem->data.S32 = xZero;
     }
     if (yFlip) {
-        psMetadataItem *yZero = psMetadataLookup(target->concepts, "CELL.Y0"); // CELL.Y0
+        int yZero = psMetadataLookupS32(NULL, source->concepts, "CELL.Y0"); // CELL.Y0 from source
+        int yParity = psMetadataLookupS32(NULL, target->concepts, "CELL.YPARITY"); // Parity in y
         pmReadout *readout = target->readouts->data[0]; // A representative readout
-        yZero->data.S32 -= readout->image->numRows - 1;
+        psTrace(__func__, 3, "CELL.Y0: Before: %d After: %d\n", yZero,
+                yZero - (readout->image->numCols - 1) * yParity);
+        yZero -= (readout->image->numCols - 1) * yParity; // Change the parity on the Y0 position
+        psMetadataItem *newItem = psMetadataLookup(target->concepts, "CELL.Y0"); // CELL.Y0 from target
+        newItem->data.S32 = yZero;
     }
 
