Index: /trunk/psModules/src/camera/pmFPACopy.c
===================================================================
--- /trunk/psModules/src/camera/pmFPACopy.c	(revision 12809)
+++ /trunk/psModules/src/camera/pmFPACopy.c	(revision 12810)
@@ -350,4 +350,46 @@
 }
 
+// create a new pmChip with the data derived from the supplied chip
+pmChip *pmChipDuplicate(pmFPA *fpa, const pmChip *sourceChip)
+{
+    assert(sourceChip);
+
+    bool status;
+    char *chipName = psMetadataLookupStr(&status, sourceChip->concepts, "CHIP.NAME");
+    pmChip *targetChip = pmChipAlloc (NULL, chipName);
+    targetChip->parent = fpa;
+
+    psArray *sourceCells = sourceChip->cells; // The source cells
+
+    for (int i = 0; i < sourceCells->n; i++) {
+        pmCell *sourceCell = sourceCells->data[i]; // The sources cell
+        const char *cellName = psMetadataLookupStr(NULL, sourceCell->concepts, "CELL.NAME"); // Name of cell
+	// XXX are there other concepts I need to copy first?
+	pmCell *targetCell = pmCellAlloc (targetChip, cellName);
+	int xParityTarget = psMetadataLookupS32(&status, sourceCell->concepts, "CELL.XPARITY"); // Target x parity
+	psMetadataAddS32 (targetCell->concepts, PS_LIST_TAIL, "CELL.XPARITY", PS_META_REPLACE, "", xParityTarget);
+	int yParityTarget = psMetadataLookupS32(&status, sourceCell->concepts, "CELL.YPARITY"); // Target y parity
+	psMetadataAddS32 (targetCell->concepts, PS_LIST_TAIL, "CELL.YPARITY", PS_META_REPLACE, "", yParityTarget);
+	if (!cellCopy(targetCell, sourceCell, true, 1, 1)) {
+	    psError(PS_ERR_BAD_PARAMETER_VALUE, false, "failed to duplicate chip\n");
+	    return NULL;
+	}
+	// update the attributes
+	targetCell->file_exists = sourceCell->file_exists;
+	targetCell->data_exists = sourceCell->data_exists;
+	targetCell->process     = sourceCell->process;
+    }
+
+    // Update the concepts
+    psMetadataCopy(targetChip->concepts, sourceChip->concepts);
+
+    // update the attributes
+    targetChip->file_exists = sourceChip->file_exists;
+    targetChip->data_exists = sourceChip->data_exists;
+    targetChip->process     = sourceChip->process;
+
+    return targetChip;
+}
+
 // Common engine for pmFPACopy and pmFPACopyStructure.
 // Iterate on the components
Index: /trunk/psModules/src/camera/pmFPACopy.h
===================================================================
--- /trunk/psModules/src/camera/pmFPACopy.h	(revision 12809)
+++ /trunk/psModules/src/camera/pmFPACopy.h	(revision 12810)
@@ -4,6 +4,6 @@
  * @author Paul Price, IfA
  *
- * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-01-24 02:54:14 $
+ * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-04-12 02:51:44 $
  * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -72,4 +72,7 @@
                          int xBin, int yBin ///< Binning factors in x and y
                         );
+
+pmChip *pmChipDuplicate(pmFPA *fpa, const pmChip *source);
+
 /// @}
 #endif
Index: /trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 12809)
+++ /trunk/psModules/src/camera/pmFPAfileIO.c	(revision 12810)
@@ -416,6 +416,6 @@
     pmFPALevel level = pmFPAviewLevel (view);
     if (file->fileLevel != level) {
-        psTrace("psModules.camera", 6, "skip closing of %s at this level %s: dataLevel is %s",
-                file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
+        psTrace("psModules.camera", 6, "skip closing of %s at this level %s: fileLevel is %s",
+                file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
         return true;
     }
