Index: trunk/psphot/src/psphotMergeSources.c
===================================================================
--- trunk/psphot/src/psphotMergeSources.c	(revision 27657)
+++ trunk/psphot/src/psphotMergeSources.c	(revision 28013)
@@ -6,5 +6,5 @@
 
 // for now, let's store the detections on the readout->analysis for each readout
-bool psphotMergeSources (pmConfig *config, const pmFPAview *view)
+bool psphotMergeSources (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
     bool status = true;
@@ -15,6 +15,6 @@
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
-        if (!psphotMergeSourcesReadout (config, view, "PSPHOT.INPUT", i)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to merge sources for PSPHOT.INPUT entry %d", i);
+        if (!psphotMergeSourcesReadout (config, view, filerule, i)) {
+            psError (PSPHOT_ERR_CONFIG, false, "failed to merge sources for %s entry %d", filerule, i);
             return false;
         }
@@ -24,10 +24,10 @@
 
 // add newly selected sources to the existing list of sources
-bool psphotMergeSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) {
+bool psphotMergeSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index) {
 
     bool status;
 
     // find the currently selected readout
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     psAssert (file, "missing file?");
 
@@ -71,5 +71,5 @@
 // only expect a single entry for PSPHOT.INPUT.CMF and PSPHOT.SOURCES.TEXT, so we can only
 // associate input sources with a single entry for PSPHOT.INPUT
-bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view) {
+bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     bool status;
@@ -79,5 +79,5 @@
 
     // find the currently selected readout
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", index); // File of interest
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     psAssert (file, "missing file?");
 
@@ -130,5 +130,5 @@
     // load data from input TXT file:
     {
-        pmChip *chipTXT = pmFPAfileThisChip (config->files, view, "PSPHOT.INPUT");
+        pmChip *chipTXT = pmFPAfileThisChip (config->files, view, filerule);
         if (!chipTXT) goto finish;
 
@@ -167,5 +167,5 @@
 
 // extract the input sources corresponding to this readout
-// XXX this function needs to be updated to work with the new context of pshot inputs
+// XXX this function needs to be updated to work with the new context of psphot inputs
 psArray *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view) {
 
@@ -197,8 +197,8 @@
 // psphotDetectionsFromSources to psphotSourceStats and are now stored on
 // detections->newSources.
-bool psphotRepairLoadedSources (pmConfig *config, const pmFPAview *view) {
-
-    // find the currently selected readout
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
+bool psphotRepairLoadedSources (pmConfig *config, const pmFPAview *view, const char *filerule) {
+
+    // find the currently selected readout
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, 0); // File of interest
     psAssert (file, "missing file?");
 
@@ -227,8 +227,8 @@
 // generate the detection structure for the supplied array of sources
 // XXX this currently assumes there is a single input file
-bool psphotDetectionsFromSources (pmConfig *config, const pmFPAview *view, psArray *sources) {
-
-    // find the currently selected readout
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
+bool psphotDetectionsFromSources (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *sources) {
+
+    // find the currently selected readout
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, 0); // File of interest
     psAssert (file, "missing file?");
 
@@ -335,5 +335,5 @@
 }
 
-bool psphotCheckExtSources (pmConfig *config, const pmFPAview *view) {
+bool psphotCheckExtSources (pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     bool status;
@@ -343,5 +343,5 @@
 
     // find the currently selected readout
-    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, 0); // File of interest
     psAssert (file, "missing file?");
 
@@ -373,28 +373,84 @@
 
         // find the detections (by peak and/or footprint) in the image.
-        if (!psphotFindDetections (config, view, true)) {
+        if (!psphotFindDetections (config, view, filerule, true)) {
             psError(PSPHOT_ERR_CONFIG, false, "unable to find detections in this image");
-            return psphotReadoutCleanup (config, view);
+            return psphotReadoutCleanup (config, view, filerule);
         }
 
         // construct sources and measure basic stats
-        psphotSourceStats (config, view, true);
+        psphotSourceStats (config, view, filerule, true);
 
         // find blended neighbors of very saturated stars
-        psphotDeblendSatstars (config, view);
+        psphotDeblendSatstars (config, view, filerule);
 
         // mark blended peaks PS_SOURCE_BLEND
-        if (!psphotBasicDeblend (config, view)) {
+        if (!psphotBasicDeblend (config, view, filerule)) {
             psLogMsg ("psphot", 3, "failed on deblend analysis");
-            return psphotReadoutCleanup (config, view);
+            return psphotReadoutCleanup (config, view, filerule);
         }
 
         // classify sources based on moments, brightness
-        if (!psphotRoughClass (config, view)) {
+        if (!psphotRoughClass (config, view, filerule)) {
             psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
-            return psphotReadoutCleanup (config, view);
-        }
-    }
-
-    return true;
-}
+            return psphotReadoutCleanup (config, view, filerule);
+        }
+    }
+
+    return true;
+}
+
+// copy the detections from one pmFPAfile to another
+bool psphotCopySources (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc)
+{
+    bool status = true;
+
+    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
+    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+
+    // skip the chisq image because it is a duplicate of the detection version
+    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
+    if (!status) chisqNum = -1;
+
+    // loop over the available readouts
+    for (int i = 0; i < num; i++) {
+	if (i == chisqNum) continue; // skip chisq image
+        if (!psphotCopySourcesReadout (config, view, ruleOut, ruleSrc, i)) {
+            psError (PSPHOT_ERR_CONFIG, false, "failed to copy sources from %s to %s entry %d", ruleSrc, ruleOut, i);
+            return false;
+        }
+    }
+    return true;
+}
+
+// add newly selected sources to the existing list of sources
+bool psphotCopySourcesReadout (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc, int index) {
+
+    bool status;
+
+    // find the currently selected readout
+    pmFPAfile *fileSrc = pmFPAfileSelectSingle(config->files, ruleSrc, index); // File of interest
+    psAssert (fileSrc, "missing file?");
+
+    pmReadout *readoutSrc = pmFPAviewThisReadout(view, fileSrc->fpa);
+    psAssert (readoutSrc, "missing readout?");
+
+    pmDetections *detections = psMetadataLookupPtr (&status, readoutSrc->analysis, "PSPHOT.DETECTIONS");
+    psAssert (detections, "missing detections?");
+
+    // find the currently selected readout
+    pmFPAfile *fileOut = pmFPAfileSelectSingle(config->files, ruleOut, index); // File of interest
+    psAssert (fileOut, "missing file?");
+
+    pmReadout *readoutOut = pmFPAviewThisReadout(view, fileOut->fpa);
+    psAssert (readoutOut, "missing readout?");
+
+    // save detections on the readout->analysis
+    // XXX this replaced any existing entry; allow this operation to merge?
+    if (!psMetadataAddPtr (readoutOut->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detections)) {
+	psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
+	return false;
+    }
+
+    return true;
+}
+
