Index: /branches/eam_branches/ipp-20150112/ppSub/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20150112/ppSub/src/Makefile.am	(revision 38055)
+++ /branches/eam_branches/ipp-20150112/ppSub/src/Makefile.am	(revision 38056)
@@ -1,23 +1,8 @@
 bin_PROGRAMS = ppSub ppSubKernel ppSubConvolve
-
-if HAVE_SVNVERSION
-PPSUB_VERSION=`$(SVNVERSION) ..`
-else
-PPSUB_VERSION="UNKNOWN"
-endif
-
-if HAVE_SVN
-PPSUB_BRANCH=`$(SVN) info .. | $(SED) -n -e '/URL:/ h' -e '/Repository Root:/ { x; H; x; s|Repository Root: \(.*\)\nURL: \1\(.*\)|\2| ; s|^/|| ; s|/[a-zA-Z]*/src.*|| ; p }'`
-PPSUB_SOURCE=`$(SVN) info | $(SED) -n -e 's/Repository UUID: // p'`
-else
-PPSUB_BRANCH="UNKNOWN"
-PPSUB_SOURCE="UNKNOWN"
-endif
 
 # Force recompilation of ppSubVersion.c, since it gets the version information
 ppSubVersion.c: ppSubVersionDefinitions.h
 ppSubVersionDefinitions.h: ppSubVersionDefinitions.h.in FORCE
-	-$(RM) ppSubVersionDefinitions.h
-	$(SED) -e "s|@PPSUB_VERSION@|\"$(PPSUB_VERSION)\"|" -e "s|@PPSUB_BRANCH@|\"$(PPSUB_BRANCH)\"|" -e "s|@PPSUB_SOURCE@|\"$(PPSUB_SOURCE)\"|" ppSubVersionDefinitions.h.in > ppSubVersionDefinitions.h
+	pslib-setsvnversion.pl PPSUB ppSubVersionDefinitions.h.in ppSubVersionDefinitions.h
 FORCE: ;
 
Index: /branches/eam_branches/ipp-20150112/ppSub/src/ppSubCamera.c
===================================================================
--- /branches/eam_branches/ipp-20150112/ppSub/src/ppSubCamera.c	(revision 38055)
+++ /branches/eam_branches/ipp-20150112/ppSub/src/ppSubCamera.c	(revision 38056)
@@ -22,4 +22,27 @@
 #include "ppSub.h"
 
+bool checkFileruleFileSave (pmFPAfile *file, pmConfig *config) {
+
+  bool status;
+
+  psMetadata *filerule = pmConfigFileRule(config, file->camera, file->name); // File rule
+  if (!filerule) return false;
+
+  char *myString = psMetadataLookupStr(&status, filerule, "FILE.SAVE");
+  if (!myString) return false;
+
+  // do not change the value from the default unless TRUE or FALSE are found
+  if (!strcasecmp(myString, "TRUE")) {
+    file->save = true;
+    return true;
+  } 
+  if (!strcasecmp(myString, "FALSE")) {
+    file->save = false;
+    return true;
+  } 
+ 
+  return false;
+}
+
 // Define an input file
 static pmFPAfile *defineInputFile(bool *success,
@@ -131,6 +154,6 @@
         }
         if (file) {
-            // It's an output
-            file->save = true;
+            // It's an output (respect filerules)
+	  checkFileruleFileSave(file, config); 
         }
     }
@@ -244,4 +267,5 @@
         return false;
     }
+    // these ->save values below are set by command-line arguments (in ppSubArguments.c) : -save-inconv, -save-refconv
     inConvImage->save = data->saveInConv;
     inConvMask->save = data->saveInConv;
@@ -283,6 +307,6 @@
         return false;
     }
-    output->save = true;
-    outMask->save = true;
+    checkFileruleFileSave (output, config);
+    checkFileruleFileSave (outMask, config);
     if (inVar && refVar) {
         pmFPAfile *outVar = defineOutputFile(config, output, false, "PPSUB.OUTPUT.VARIANCE",
@@ -292,5 +316,5 @@
             return false;
         }
-        outVar->save = true;
+	checkFileruleFileSave (outVar, config);
     }
 
@@ -305,6 +329,6 @@
             return false;
         }
-        inverse->save = true;
-        invMask->save = true;
+        checkFileruleFileSave (inverse, config);
+        checkFileruleFileSave (invMask, config);
         if (inVar && refVar) {
             pmFPAfile *invVar = defineOutputFile(config, inverse, false, "PPSUB.INVERSE.VARIANCE",
@@ -314,5 +338,5 @@
                 return false;
             }
-            invVar->save = true;
+            checkFileruleFileSave(invVar, config);
         }
     }
@@ -329,5 +353,5 @@
         return false;
     }
-    jpeg1->save = true;
+    checkFileruleFileSave(jpeg1, config);
     pmFPAfile *jpeg2 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG2");
     if (!jpeg2) {
@@ -339,5 +363,5 @@
         return false;
     }
-    jpeg2->save = true;
+    checkFileruleFileSave(jpeg2, config);
 
     // Output residual JPEG
@@ -351,5 +375,5 @@
         return false;
     }
-    jpeg3->save = true;
+    checkFileruleFileSave(jpeg3, config);
 
     // Output subtraction kernel
@@ -395,5 +419,5 @@
         // Deactivate psphot output sources --- we want to define output source files of our own
         pmFPAfile *psphotOutput = pmFPAfileSelectSingle(config->files, "PSPHOT.OUTPUT", 0);
-        psphotOutput->save = false;
+        psphotOutput->save = false;  // this one should NOT be set
 
         pmFPAfile *outSources = defineOutputFile(config, output, false, "PPSUB.OUTPUT.SOURCES",
@@ -403,5 +427,5 @@
             return false;
         }
-        outSources->save = true;
+        checkFileruleFileSave(outSources, config);
 
         if (data->inverse) {
@@ -412,5 +436,5 @@
                 return false;
             }
-            invSources->save = true;
+            checkFileruleFileSave(invSources, config);
         }
 
@@ -423,5 +447,5 @@
                 return false;
             }
-            posSources1->save = true;
+            checkFileruleFileSave(posSources1, config);
 
 	    // this pmFPAfile is used to carry sources detected in the diff image @ the positions from positive image #1
@@ -431,5 +455,5 @@
                 return false;
             }
-            frcSources1->save = true;
+            checkFileruleFileSave(frcSources1, config);
 	}
 
@@ -441,5 +465,5 @@
                 return false;
             }
-            posSources2->save = true;
+            checkFileruleFileSave(posSources2, config);
 
 	    // this pmFPAfile is used to carry sources detected in the diff image @ the positions from positive image #2
@@ -449,5 +473,5 @@
                 return false;
             }
-            frcSources2->save = true;
+	    checkFileruleFileSave(frcSources2, config);
         }
     }
Index: /branches/eam_branches/ipp-20150112/ppSub/src/ppSubDefineOutput.c
===================================================================
--- /branches/eam_branches/ipp-20150112/ppSub/src/ppSubDefineOutput.c	(revision 38055)
+++ /branches/eam_branches/ipp-20150112/ppSub/src/ppSubDefineOutput.c	(revision 38056)
@@ -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;
+}
+
Index: /branches/eam_branches/ipp-20150112/ppSub/src/ppSubReadoutPhotometry.c
===================================================================
--- /branches/eam_branches/ipp-20150112/ppSub/src/ppSubReadoutPhotometry.c	(revision 38055)
+++ /branches/eam_branches/ipp-20150112/ppSub/src/ppSubReadoutPhotometry.c	(revision 38056)
@@ -46,4 +46,9 @@
         psFree(view);
         return false;
+    }
+
+    // psphot may need the PHU header
+    if (!photFile->fpa->hdu) {
+      photFile->fpa->hdu = psMemIncrRefCounter (inFile->fpa->hdu);
     }
 
