Index: trunk/ppSub/src/ppSubDefineOutput.c
===================================================================
--- trunk/ppSub/src/ppSubDefineOutput.c	(revision 31435)
+++ trunk/ppSub/src/ppSubDefineOutput.c	(revision 37966)
@@ -22,8 +22,12 @@
 #include "ppSub.h"
 
+bool ppSubCopyWarpToChip (psMetadata *tgtHeader, psMetadata *srcHeader);
+
 bool ppSubDefineOutput(const char *name, pmConfig *config)
 {
     psAssert(name, "Require name");
     psAssert(config, "Require configuration");
+
+    bool status = false;
 
     pmFPAview *view = ppSubViewReadout(); // View to readout
@@ -44,12 +48,15 @@
 
     // Convolved input images
-    psMetadata *recipe = psMetadataLookupPtr(NULL, config->recipes, PPSUB_RECIPE);
-    bool noConvolve = psMetadataLookupBool(NULL, recipe, "NOCONVOLVE"); // Do not use convolved images.
+    psMetadata *recipe = psMetadataLookupPtr(&status, config->recipes, PPSUB_RECIPE);
+    bool noConvolve = psMetadataLookupBool(&status, recipe, "NOCONVOLVE"); // Do not use convolved images.
+    bool reverse = psMetadataLookupBool(&status, config->arguments, "REVERSE"); // Reverse sense of subtraction?
+    bool mapFromPositive = psMetadataLookupBool(&status, config->arguments, "CHIP.MAP.FROM.POSITIVE"); 
+    // mapFromPositive = true means "always grab the warp->chip map from the positive image (eg, A for A - B, B for B - A)
+    // mapFromPositive = false means "always grab the warp->chip map from the first image (eg, PPSUB.INPUT if not 'reverse')
 
     pmReadout *inConv;
     if (noConvolve) {
       inConv = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT"); // Input readout
-    }
-    else {
+    } else {
       inConv = pmFPAfileThisReadout(config->files, view, "PPSUB.INPUT.CONV"); // Input readout
     }
@@ -57,9 +64,7 @@
     if (noConvolve) {
       refConv = pmFPAfileThisReadout(config->files, view, "PPSUB.REF"); // Reference readout
-    }
-    else {
+    } else {
       refConv = pmFPAfileThisReadout(config->files, view, "PPSUB.REF.CONV"); // Reference readout
     }
-    psFree(view);
 
     // Add kernel descrption to header.
@@ -78,4 +83,5 @@
         psError(PPSUB_ERR_UNKNOWN, true, "Unable to find SUBTRACTION.KERNEL");
         psFree(outRO);
+	psFree(view);
         return false;
     }
@@ -85,4 +91,38 @@
     }
     outHDU->header = psMetadataCopy(outHDU->header, hdu->header);
+
+    // in warp-stack mode, we should always use the warp 
+    // in warp-warp mode, we should use the positive warp for the positive subtraction
+
+    bool normalDiff = true;
+    if (!strcmp (name, "PPSUB.INVERSE"))  {
+      normalDiff = false;
+    }
+
+    if (reverse) {
+      // normal  = PPSUB.REF - PPSUB.INPUT
+      // inverse = PPSUB.INPUT - PPSUB.REF
+      if (mapFromPositive) {
+	pmCell *cell_Pos = normalDiff ? pmFPAfileThisCell(config->files, view, "PPSUB.REF") : pmFPAfileThisCell(config->files, view, "PPSUB.INPUT");
+	pmHDU *hdu_Pos = pmHDUFromCell(cell_Pos);
+	ppSubCopyWarpToChip (outHDU->header, hdu_Pos->header);
+      } else {
+	pmCell *cell_Pos = pmFPAfileThisCell(config->files, view, "PPSUB.REF");
+	pmHDU *hdu_Pos = pmHDUFromCell(cell_Pos);
+	ppSubCopyWarpToChip (outHDU->header, hdu_Pos->header);
+      }
+    } else {
+      // normal  = PPSUB.INPUT - PPSUB.REF
+      // inverse = PPSUB.REF - PPSUB.INPUT
+      if (mapFromPositive) {
+	pmCell *cell_Pos = normalDiff ? pmFPAfileThisCell(config->files, view, "PPSUB.INPUT") : pmFPAfileThisCell(config->files, view, "PPSUB.REF");
+	pmHDU *hdu_Pos = pmHDUFromCell(cell_Pos);
+	ppSubCopyWarpToChip (outHDU->header, hdu_Pos->header);
+      } else {
+	pmCell *cell_Pos = pmFPAfileThisCell(config->files, view, "PPSUB.INPUT");
+	pmHDU *hdu_Pos = pmHDUFromCell(cell_Pos);
+	ppSubCopyWarpToChip (outHDU->header, hdu_Pos->header);
+      }
+    }
 
     // Add additional data to the header
@@ -104,5 +144,132 @@
 
     psFree(outRO);
+    psFree(view);
 
     return true;
 }
+
+// we have 4 sets of header keywords to copy:
+// SRC_nnnn, SEC_nnnn, MPX_nnnn, MPY_nnnn
+
+bool ppSubCopyWarpToChip (psMetadata *tgtHeader, psMetadata *srcHeader) {
+
+  char keyword[80];
+
+  bool status = false;
+
+  int Nchip = 0;
+  while (true) {
+    snprintf (keyword, 80, "SRC_%04d", Nchip);
+    char *string = psMetadataLookupStr (&status, srcHeader, keyword);
+    if (!status) {
+      break;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, keyword, PS_META_REPLACE, "input image", string);
+    Nchip ++;
+  }
+    
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (keyword, 80, "SEC_%04d", i);
+    char *string = psMetadataLookupStr (&status, srcHeader, keyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", keyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, keyword, PS_META_REPLACE, "input image", string);
+  }
+
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (keyword, 80, "MPX_%04d", i);
+    char *string = psMetadataLookupStr (&status, srcHeader, keyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", keyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, keyword, PS_META_REPLACE, "input image", string);
+  }
+
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (keyword, 80, "MPY_%04d", i);
+    char *string = psMetadataLookupStr (&status, srcHeader, keyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", keyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, keyword, PS_META_REPLACE, "input image", string);
+  }
+  return true;
+}
+
+bool ppSubCopyWarpToChip_Alt (psMetadata *tgtHeader, psMetadata *srcHeader, bool isPositive) {
+
+  char srcKeyword[80], tgtKeyword[80];
+
+  bool status = false;
+
+  int Nchip = 0;
+  while (true) {
+    snprintf (srcKeyword, 80, "SRC_%04d", Nchip);
+    if (isPositive) {
+      snprintf (tgtKeyword, 80, "SRCP_%03d", Nchip);
+    } else {
+      snprintf (tgtKeyword, 80, "SRCM_%03d", Nchip);
+    }
+
+    char *string = psMetadataLookupStr (&status, srcHeader, srcKeyword);
+    if (!status) {
+      break;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, srcKeyword, PS_META_REPLACE, "input image", string);
+    Nchip ++;
+  }
+    
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (srcKeyword, 80, "SEC_%04d", i);
+    if (isPositive) {
+      snprintf (tgtKeyword, 80, "SECP_%03d", Nchip);
+    } else {
+      snprintf (tgtKeyword, 80, "SECM_%03d", Nchip);
+    }
+
+    char *string = psMetadataLookupStr (&status, srcHeader, srcKeyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", srcKeyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, srcKeyword, PS_META_REPLACE, "input image", string);
+  }
+
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (srcKeyword, 80, "MPX_%04d", i);
+    if (isPositive) {
+      snprintf (tgtKeyword, 80, "MPXP_%03d", Nchip);
+    } else {
+      snprintf (tgtKeyword, 80, "MPXM_%03d", Nchip);
+    }
+
+    char *string = psMetadataLookupStr (&status, srcHeader, srcKeyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", srcKeyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, srcKeyword, PS_META_REPLACE, "input image", string);
+  }
+
+  for (int i = 0; i < Nchip; i++) {
+    snprintf (srcKeyword, 80, "MPY_%04d", i);
+    if (isPositive) {
+      snprintf (tgtKeyword, 80, "MPYP_%03d", Nchip);
+    } else {
+      snprintf (tgtKeyword, 80, "MPYM_%03d", Nchip);
+    }
+
+    char *string = psMetadataLookupStr (&status, srcHeader, srcKeyword);
+    if (!status) {
+      psWarning ("cannot find keyword %s\n", srcKeyword);
+      continue;
+    }
+    psMetadataAddStr(tgtHeader, PS_LIST_TAIL, srcKeyword, PS_META_REPLACE, "input image", string);
+  }
+  return true;
+}
+
