Index: /branches/eam_branches/ipp-20101103/ppSub/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/Makefile.am	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/Makefile.am	(revision 29915)
@@ -38,4 +38,5 @@
 	ppSubLoop.c			\
 	ppSubDefineOutput.c		\
+	ppSubInputDetections.c		\
 	ppSubExtras.c			\
 	ppSubFlagNeighbors.c		\
@@ -46,4 +47,5 @@
 	ppSubReadoutJpeg.c		\
 	ppSubReadoutPhotometry.c	\
+	ppSubReadoutForcedPhot.c	\
 	ppSubReadoutStats.c		\
 	ppSubReadoutSubtract.c		\
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSub.h
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSub.h	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSub.h	(revision 29915)
@@ -45,4 +45,6 @@
     bool photometry;                    // Perform photometry?
     bool inverse;                       // Output inverse subtraction as well?
+    bool forcedPhot1;                   // perform forced photometry?
+    bool forcedPhot2;                   // perform forced photometry?
     bool saveInConv;                    // Save convolved input?
     bool saveRefConv;                   // Save convolved reference?
@@ -105,4 +107,8 @@
                             ppSubData *data ///< Processing data
     );
+
+bool ppSubInputDetections (bool *foundDetections, const char *sourcesName, const char *imageName, ppSubData *data);
+bool ppSubReadoutForcedPhot(const char *outputName, const char *targetName, const char *sourceName, ppSubData *data);
+bool psphotCopyResults (bool *foundDetections, pmFPAfile *target, pmFPAfile *source, pmFPAview *view);
 
 /// Higher-order background subtraction
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubArguments.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubArguments.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubArguments.c	(revision 29915)
@@ -86,4 +86,7 @@
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-convolve", 0, "Image to convolve [1 or 2]", 0);
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-photometry", 0, "Perform photometry?", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-forced-phot", 0, "Perform forced photometry?", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-forced-input1", 0, "Perform forced photometry?", NULL);
+    psMetadataAddBool(arguments, PS_LIST_TAIL, "-forced-input2", 0, "Perform forced photometry?", NULL);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-zp", 0, "Zero point for photometry", NAN);
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-inverse", 0, "Generate inverse subtractions?", false);
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubBackground.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubBackground.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubBackground.c	(revision 29915)
@@ -37,26 +37,22 @@
     pmFPAview *view = ppSubViewReadout(); // View to readout
     pmReadout *outRO = pmFPAfileThisReadout(config->files, view, "PPSUB.OUTPUT"); // Output image
-    pmReadout *modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL"); // Background model
 
-    // Generate the background model, if required
+    // Generate the background model
+    if (!psphotModelBackground(config, view, "PPSUB.OUTPUT")) {
+      psError(psErrorCodeLast(), false, "Unable to model background");
+      psFree(view);
+      return false;
+    }
+
+    // select the model readout (should now exist)
+    pmReadout *modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL");
     if (!modelRO) {
-        // Create the background model
-        if (!psphotModelBackgroundReadoutFileIndex(config, view, "PPSUB.OUTPUT", 0)) {
-            psError(psErrorCodeLast(), false, "Unable to model background");
-            psFree(view);
-            return false;
-        }
-        // select the model readout (should now exist)
-        modelRO = pmFPAfileThisReadout(config->files, view, "PSPHOT.BACKMDL");
-        if (!modelRO) {
-            psError(psErrorCodeLast(), false, "Unable to find background model");
-            psFree(view);
-            return false;
-        }
+      psError(psErrorCodeLast(), false, "Unable to find background model");
+      psFree(view);
+      return false;
     }
     psFree(view);
 
-    psImageBinning *binning = psMetadataLookupPtr(&mdok, modelRO->analysis,
-                                                  "PSPHOT.BACKGROUND.BINNING"); // Binning for model
+    psImageBinning *binning = psMetadataLookupPtr(&mdok, modelRO->analysis, "PSPHOT.BACKGROUND.BINNING"); // Binning for model
     psImage *modelImage = modelRO->image; // Background model
     psImage *image = outRO->image; // Image of interest
@@ -83,7 +79,4 @@
     }
 
-    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
-    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
-
     return true;
 }
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubCamera.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubCamera.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubCamera.c	(revision 29915)
@@ -221,7 +221,18 @@
                           "Generate inverse subtractions?", true);
     }
-
-    data->inverse = psMetadataLookupBool(NULL, recipe, "INVERSE");
-    data->photometry = psMetadataLookupBool(NULL, recipe, "PHOTOMETRY");
+    if (psMetadataLookupBool(NULL, config->arguments, "-forced-phot")) {
+        psMetadataAddBool(recipe, PS_LIST_TAIL, "FORCED.PHOTOMETRY.BOTH", PS_META_REPLACE, "Perform forced photometry?", true);
+    }
+    if (psMetadataLookupBool(NULL, config->arguments, "-forced-input1")) {
+        psMetadataAddBool(recipe, PS_LIST_TAIL, "FORCED.PHOTOMETRY.INPUT1", PS_META_REPLACE, "Perform forced photometry?", true);
+    }
+    if (psMetadataLookupBool(NULL, config->arguments, "-forced-input2")) {
+        psMetadataAddBool(recipe, PS_LIST_TAIL, "FORCED.PHOTOMETRY.INPUT2", PS_META_REPLACE, "Perform forced photometry?", true);
+    }
+
+    data->inverse     = psMetadataLookupBool(NULL, recipe, "INVERSE");
+    data->photometry  = psMetadataLookupBool(NULL, recipe, "PHOTOMETRY");
+    data->forcedPhot1 = psMetadataLookupBool(NULL, recipe, "FORCED.PHOTOMETRY.BOTH") || psMetadataLookupBool(NULL, recipe, "FORCED.PHOTOMETRY.INPUT1");
+    data->forcedPhot2 = psMetadataLookupBool(NULL, recipe, "FORCED.PHOTOMETRY.BOTH") || psMetadataLookupBool(NULL, recipe, "FORCED.PHOTOMETRY.INPUT2");
 
     // Convolved input image
@@ -363,6 +374,4 @@
             return false;
         }
-        // specify the number of psphot input images
-        psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
         pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");
 
@@ -405,4 +414,41 @@
             invSources->save = true;
         }
+
+	// files need to do the forced photometry on the positions of sources in the positive images
+        if (data->forcedPhot1) {
+	    // this pmFPAfile is used to carry sources detected in the positive image #1
+            pmFPAfile *posSources1 = defineOutputFile(config, output, true, "PPSUB.POS1.SOURCES", PM_FPA_FILE_CMF);
+            if (!posSources1) {
+                psError(psErrorCodeLast(), false, "Unable to set up forced source file.");
+                return false;
+            }
+            posSources1->save = true;
+
+	    // this pmFPAfile is used to carry sources detected in the diff image @ the positions from positive image #1
+            pmFPAfile *frcSources1 = defineOutputFile(config, output, true, "PPSUB.FORCED1.SOURCES", PM_FPA_FILE_CMF);
+            if (!frcSources1) {
+                psError(psErrorCodeLast(), false, "Unable to set up forced source file.");
+                return false;
+            }
+            frcSources1->save = true;
+	}
+
+        if (data->forcedPhot2) {
+	    // this pmFPAfile is used to carry sources detected in the positive image #2
+            pmFPAfile *posSources2 = defineOutputFile(config, inverse, true, "PPSUB.POS2.SOURCES", PM_FPA_FILE_CMF);
+            if (!posSources2) {
+                psError(psErrorCodeLast(), false, "Unable to set up forced source file.");
+                return false;
+            }
+            posSources2->save = true;
+
+	    // this pmFPAfile is used to carry sources detected in the diff image @ the positions from positive image #2
+            pmFPAfile *frcSources2 = defineOutputFile(config, inverse, true, "PPSUB.FORCED2.SOURCES", PM_FPA_FILE_CMF);
+            if (!frcSources2) {
+                psError(psErrorCodeLast(), false, "Unable to set up forced source file.");
+                return false;
+            }
+            frcSources2->save = true;
+        }
     }
 
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubFlagNeighbors.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubFlagNeighbors.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubFlagNeighbors.c	(revision 29915)
@@ -235,5 +235,5 @@
 	src = sources->data[Imin]; 
 
-	fprintf (stderr, "j: %d, Imin: %d, obj x,y: %f, %f  src x,y: %f, %f, SN: %f, ID: %d\n", j, Imin, obj->x, obj->y, src->peak->xf, src->peak->yf, src->peak->SN, src->id);
+	// fprintf (stderr, "j: %d, Imin: %d, obj x,y: %f, %f  src x,y: %f, %f, SN: %f, ID: %d\n", j, Imin, obj->x, obj->y, src->peak->xf, src->peak->yf, src->peak->SN, src->id);
 
 	// add source to object
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubInputDetections.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubInputDetections.c	(revision 29915)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubInputDetections.c	(revision 29915)
@@ -0,0 +1,190 @@
+/** @file ppSubInputDetections.c
+ *
+ *  @ingroup ppSub
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-18 00:31:20 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <psphot.h>
+
+#include "ppSub.h"
+
+pmHDU *getHDUandLevel (pmFPALevel *level, pmFPA *fpa, pmFPAview *view) {
+
+    pmHDU *hdu = NULL;
+    *level = PM_FPA_LEVEL_NONE;
+
+    pmCell *cell = pmFPAviewThisCell(view, fpa);
+    if (cell) {
+	hdu = cell->hdu; // cell
+	if (hdu) {
+	    *level = PM_FPA_LEVEL_CELL;
+	    return hdu;
+	}
+    }
+
+    pmChip *chip = pmFPAviewThisChip(view, fpa);
+    if (chip) {
+	hdu = chip->hdu; // chip
+	if (hdu) {
+	    *level = PM_FPA_LEVEL_CHIP;
+	    return hdu;
+	}
+    }
+
+    hdu = fpa->hdu; // fpa
+    if (hdu) {
+	*level = PM_FPA_LEVEL_FPA;
+	return hdu;
+    }
+    return NULL;
+}      
+
+pmHDU *setHDUatLevel (pmFPALevel level, pmFPA *fpa, pmFPAview *view, char *extname) {
+
+    switch (level) {
+      case (PM_FPA_LEVEL_FPA): {
+	  if (!fpa->hdu) {
+	      fpa->hdu = pmHDUAlloc(extname);
+	  }
+	  return fpa->hdu;
+      }
+      case (PM_FPA_LEVEL_CHIP): {
+	  pmChip *chip = pmFPAviewThisChip(view, fpa);
+	  if (!chip->hdu) {
+	      chip->hdu = pmHDUAlloc(extname);
+	  }
+	  return chip->hdu;
+      }
+      case (PM_FPA_LEVEL_CELL): {
+	  pmCell *cell = pmFPAviewThisCell(view, fpa);
+	  if (!cell->hdu) {
+	      cell->hdu = pmHDUAlloc(extname);
+	  }
+	  return cell->hdu;
+      }
+      default:
+	return NULL;
+    }
+    return NULL;
+}      
+
+bool ppSubInputDetections (bool *foundDetections, const char *sourcesName, const char *imageName, ppSubData *data) {
+
+    bool mdok = false;
+
+    psAssert(data, "Require processing data");
+    pmConfig *config = data->config;    // Configuration
+    psAssert(config, "Require configuration");
+
+    // select the view of interest
+    pmFPAview *view = ppSubViewReadout(); // View to readout
+
+    // point PSPHOT.INPUT at the positive image
+    pmFPAfile *imageFile   = psMetadataLookupPtr(&mdok, config->files, imageName); // Image to photometer
+    pmFPAfile *sourcesFile = psMetadataLookupPtr(&mdok, config->files, sourcesName); // Place results her
+    pmFPAfile *photFile    = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // holder for the working image
+
+    // create a psphot working file, so we don't damage the image or affect existing sources
+    if (!pmFPACopy(photFile->fpa, imageFile->fpa)) {
+	psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
+	psFree(view);
+	return false;
+    }
+
+    pmFPALevel hduLevel = PM_FPA_LEVEL_NONE;
+    pmHDU *imageHDU = getHDUandLevel (&hduLevel, imageFile->fpa, view);
+
+    if (imageHDU) {
+	pmFPALevel outLevel = PM_FPA_LEVEL_NONE;
+	pmHDU *sourcesHDU = getHDUandLevel (&outLevel, sourcesFile->fpa, view);
+	if (!sourcesHDU) {
+	    sourcesHDU = setHDUatLevel (hduLevel, sourcesFile->fpa, view, imageHDU->extname);
+	}
+	
+	if (!sourcesHDU->header) {
+	    sourcesHDU->header = psMetadataAlloc();
+	}
+	if (!psMetadataCopy(sourcesHDU->header, imageHDU->header)) {
+	    psError(PPSUB_ERR_PROG, false, "Unable to copy header");
+	    return false;
+	}
+    }
+
+    if (!psphotReadout(config, view, "PSPHOT.INPUT")) {
+	psErrorStackPrint(stderr, "Unable to perform photometry on image");
+	psWarning("Unable to perform photometry on image --- suspect bad data quality.");
+	ppSubDataQuality(data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
+    }
+    // save the outputs on PPSUB.POS1.SOURCES
+    if (!psphotCopyResults (foundDetections, sourcesFile, photFile, view)) {
+	psError(PPSUB_ERR_PROG, false, "Unable to copy psphot outputs");
+	return false;
+    }
+    // if no sources were found here, we report that back and let them handle it
+
+    return true;
+}
+
+bool psphotCopyResults (bool *foundDetections, pmFPAfile *target, pmFPAfile *source, pmFPAview *view) {
+
+    pmReadout *sourceRO = pmFPAviewThisReadout(view, source->fpa);
+    psAssert(sourceRO, "programming error: source readout not defined");
+
+    pmReadout *targetRO = pmFPAviewThisReadout(view, target->fpa);
+    if (!targetRO) {
+	pmCell *targetCell = pmFPAviewThisCell(view, target->fpa);
+	targetRO = pmReadoutAlloc(targetCell);
+	psAssert(targetRO, "programming error: could not make target readout");
+    }
+
+    // If no sources were found, there's no error, but we need to inform the calling function
+    pmDetections *detections = psMetadataLookupPtr(NULL, sourceRO->analysis, "PSPHOT.DETECTIONS"); // Sources
+    if (!detections) {
+	*foundDetections = false;
+	return true;
+    } else {
+	*foundDetections = true;
+    }
+
+    psArray *sources = detections->allSources; 
+    psAssert (sources, "missing sources?");
+
+    if (!psMetadataCopySingle(targetRO->analysis, sourceRO->analysis, "PSPHOT.DETECTIONS")) {
+	psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.DETECTIONS");
+	return false;
+    }
+    if (!psMetadataCopySingle(targetRO->analysis, sourceRO->analysis, "PSPHOT.HEADER")) {
+	psError(PPSUB_ERR_PROG, false, "Unable to copy PSPHOT.HEADER");
+	return false;
+    }
+    if (!psMetadataCopySingle(targetRO->analysis, sourceRO->analysis, PM_DETEFF_ANALYSIS)) {
+	psError(PPSUB_ERR_PROG, false, "Unable to copy Detection Efficiency");
+	return false;
+    }
+
+    // Ensure photometry information is put in the header
+    // XXX create one if it does not exist?
+    pmHDU *hdu = pmHDUFromReadout(targetRO); // HDU for readout
+    if (hdu) {
+	psMetadata *header = psMetadataLookupMetadata(NULL, targetRO->analysis, "PSPHOT.HEADER"); // Header
+	hdu->header = psMetadataCopy(hdu->header, header);
+    }
+
+    targetRO->data_exists = true;
+    targetRO->parent->data_exists = true;
+    targetRO->parent->parent->data_exists = true;
+
+    return true;
+}
+
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubLoop.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubLoop.c	(revision 29915)
@@ -57,4 +57,30 @@
     }
 
+    if (data->forcedPhot1) {
+	bool foundDetections = false;
+	if (!ppSubInputDetections(&foundDetections, "PPSUB.POS1.SOURCES", "PPSUB.INPUT", data)) {
+	    psError(psErrorCodeLast(), false, "Unable to measure positive detections (1)");
+	    return false;
+	}
+	// if nothing was found, don't bother doing the forced photometry below
+	if (!foundDetections) {
+	    psWarning ("no sources found in positive image 1, skipping forced photometry");
+	    data->forcedPhot1 = false;
+	}
+    }
+    if (data->forcedPhot2) {
+	bool foundDetections = false;
+	if (!ppSubInputDetections(&foundDetections, "PPSUB.POS2.SOURCES", "PPSUB.REF", data)) {
+	    psError(psErrorCodeLast(), false, "Unable to measure positive detections (2)");
+	    return false;
+	}
+	// if nothing was found, don't bother doing the forced photometry below
+	if (!foundDetections) {
+	    psWarning ("no sources found in positive image 1, skipping forced photometry");
+	    data->forcedPhot1 = false;
+	}
+    }
+
+    // XXX if it exists, use the POS1, POS2 results for the FWHMs
     if (!ppSubMatchPSFs(data)) {
         psError(psErrorCodeLast(), false, "Unable to match PSFs.");
@@ -156,4 +182,20 @@
     }
     // dumpout(config, "diff.3.fits");
+
+    // forced photometry for positive image 1
+    if (data->forcedPhot1 && !data->quality) {
+	if (!ppSubReadoutForcedPhot("PPSUB.FORCED1.SOURCES", "PPSUB.OUTPUT", "PPSUB.POS1.SOURCES", data)) {
+	    psError(psErrorCodeLast(), false, "Unable to perform photometry.");
+	    return false;
+	}
+    }
+
+    // forced photometry for positive image 2
+    if (data->forcedPhot2 && !data->quality) {
+	if (!ppSubReadoutForcedPhot("PPSUB.FORCED2.SOURCES", "PPSUB.OUTPUT", "PPSUB.POS2.SOURCES", data)) {
+	    psError(psErrorCodeLast(), false, "Unable to perform photometry.");
+	    return false;
+	}
+    }
 
     if (!ppSubFilesIterateUp(config, PPSUB_FILES_PHOT_SUB)) {
@@ -230,4 +272,8 @@
     }
 
+    pmFPAfileDropInternal(config->files, "PSPHOT.BACKGND");
+    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
+    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
+
     return true;
 }
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMakePSF.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMakePSF.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMakePSF.c	(revision 29915)
@@ -35,11 +35,4 @@
 
     psTimerStart("PPSUB_PHOT");
-
-    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSub
-    psAssert(recipe, "We checked this earlier, so it should be here.");
-
-    if (!psMetadataLookupBool(NULL, recipe, "PHOTOMETRY")) {
-        return true;
-    }
 
     bool reverse = psMetadataLookupBool(NULL, config->arguments, "REVERSE"); // Reverse sense of subtraction?
@@ -93,5 +86,5 @@
     // use flags to toss totally bogus entries?
     psArray *goodSources = ppSubSelectPSFSources (sources);
-    if (!psphotReadoutFindPSF(config, view, goodSources)) {
+    if (!psphotReadoutFindPSF(config, view, "PSPHOT.INPUT", goodSources)) {
         // This is likely a data quality issue
         // XXX Split into multiple cases using error codes?
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMatchPSFs.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMatchPSFs.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubMatchPSFs.c	(revision 29915)
@@ -72,5 +72,5 @@
     // Extract the loaded sources from the associated readout, and generate PSF
     // Here, we assume the image is background-subtracted
-    if (!psphotReadoutFindPSF(config, view, sources)) {
+    if (!psphotReadoutFindPSF(config, view, "PSPHOT.INPUT", sources)) {
         psErrorStackPrint(stderr, "Unable to determine PSF");
         psWarning("Unable to determine PSF.");
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutForcedPhot.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutForcedPhot.c	(revision 29915)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutForcedPhot.c	(revision 29915)
@@ -0,0 +1,100 @@
+/** @file ppSubReadoutForcedphot.c
+ *
+ *  @brief
+ *
+ *  @ingroup ppSub
+ *
+ *  @author IfA
+ *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-18 00:31:20 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <psphot.h>
+
+#include "ppSub.h"
+
+// run forced photometry on the image in 'targetName' at the positions of the sources in 'sourceName'
+// this function is only called if (data->forcedPhot1 || data->forcedPhot2) (ppSubLoop.c:186,194)
+bool ppSubReadoutForcedPhot(const char *outputName, const char *targetName, const char *sourceName, ppSubData *data)
+{
+    bool foundDetections = false;
+    bool mdok = false;
+
+    psAssert(data, "Require processing data");
+    pmConfig *config = data->config;    // Configuration
+    psAssert(config, "Require configuration");
+
+    // select the view of interest
+    pmFPAview *view = ppSubViewReadout(); // View to readout
+
+    pmFPAfile *sourceFile = psMetadataLookupPtr(&mdok, config->files, sourceName); // positive image sources
+    pmFPAfile *targetFile = psMetadataLookupPtr(&mdok, config->files, targetName); // diff image pixels
+    pmFPAfile *outputFile = psMetadataLookupPtr(&mdok, config->files, outputName); // result file
+
+    psAssert (sourceFile, "failed to construct sourceName %s", sourceName);
+    psAssert (targetFile, "failed to construct targetName %s", targetName);
+    psAssert (outputFile, "failed to construct outputName %s", outputName);
+
+    // copy the image data to PSPHOT.INPUT so that psphotReadoutForcedKnownSources does
+    // not affect the prior results on targetName (ie, diff detections)
+    pmFPAfile *photFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.INPUT"); // Photometry file
+    if (!pmFPACopy(photFile->fpa, targetFile->fpa)) {
+        psError(PPSUB_ERR_CONFIG, false, "Unable to copy FPA for photometry");
+        psFree(view);
+        return false;
+    }
+
+    // select the reference position sources from sourceName
+    pmReadout *sourceRO = pmFPAviewThisReadout(view, sourceFile->fpa);
+    psAssert(sourceRO, "programming error: source readout not defined");
+
+    pmDetections *sourceDet = psMetadataLookupPtr(NULL, sourceRO->analysis, "PSPHOT.DETECTIONS"); // Sources
+    if (!sourceDet) {
+	// XXX remove the pixels from photFile?
+	// XXX other cleanup operations?
+	return true;
+    }
+    psArray *sources = sourceDet->allSources;
+    psAssert (sources, "missing sources?");
+
+    // grab the PSF information from the pmFPAfile PSPHOT.PSF.LOAD
+    pmFPAfile *psfFile = psMetadataLookupPtr(&mdok, config->files, "PSPHOT.PSF.LOAD"); // PSF file
+    ppSubCopyPSF (photFile, psfFile, view);
+
+    // psphotSaveImage (photFile->fpa->hdu->header, photRO->image, "findsrc.im.fits");
+    // psphotSaveImage (photFile->fpa->hdu->header, photRO->variance, "findsrc.wt.fits");
+    // psphotSaveImage (photFile->fpa->hdu->header, photRO->mask, "findsrc.mk.fits");
+
+    // erase the overlays from a previous psphot-related step
+    if (pmVisualIsVisual()) {
+        //      psphotVisualEraseOverlays (1, "all");
+    }
+
+    if (!psphotReadoutForcedKnownSources(config, view, "PSPHOT.INPUT", sources)) {
+        // This is likely a data quality issue
+        // XXX Split into multiple cases using error codes?
+        psErrorStackPrint(stderr, "Unable to perform photometry on image");
+        psWarning("Unable to perform photometry on image --- suspect bad data quality.");
+        ppSubDataQuality(data, psErrorCodeLast(), PPSUB_FILES_PHOT_SUB | PPSUB_FILES_PHOT_INV);
+    }
+    // save the outputs on PPSUB.POS1.SOURCES
+    if (!psphotCopyResults (&foundDetections, outputFile, photFile, view)) {
+	psError(PPSUB_ERR_PROG, false, "Unable to copy psphot outputs");
+	return false;
+    }
+
+    float newTime = psTimerClear("PPSUB_PHOT"); // Time for photometry
+    float oldTime = psMetadataLookupF32(&mdok, data->stats, "TIME_PHOT"); // Previous time for photometry
+    float elapsed = isfinite(oldTime) ? oldTime + newTime : newTime;
+    psMetadataAddF32(data->stats, PS_LIST_TAIL, "TIME_PHOT", PS_META_REPLACE, "Time to do photometry", elapsed);
+
+    return true;
+}
Index: /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutPhotometry.c
===================================================================
--- /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutPhotometry.c	(revision 29914)
+++ /branches/eam_branches/ipp-20101103/ppSub/src/ppSubReadoutPhotometry.c	(revision 29915)
@@ -31,14 +31,4 @@
 
     if (!data->photometry) {
-        return true;
-    }
-
-    // Look up recipe values
-    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
-    psAssert(recipe, "We checked this earlier, so it should be here.");
-
-    if (!psMetadataLookupBool(NULL, recipe, "PHOTOMETRY")) {
-        pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
-        pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
         return true;
     }
@@ -81,5 +71,5 @@
     }
 
-    if (!psphotReadoutMinimal(config, view)) {
+    if (!psphotReadoutMinimal(config, view, "PSPHOT.INPUT")) {
         // This is likely a data quality issue
         // XXX Split into multiple cases using error codes?
@@ -90,4 +80,5 @@
 
     // If no sources were found, there's no error,  but we want to trigger 'bad quality'
+    psWarning("no sources found: why is this being set to bad quality??");
     pmDetections *detections = psMetadataLookupPtr(NULL, photRO->analysis, "PSPHOT.DETECTIONS"); // Sources
     if (!detections) {
@@ -136,7 +127,4 @@
         }
     }
-
-    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL");
-    pmFPAfileDropInternal(config->files, "PSPHOT.BACKMDL.STDEV");
 
     return true;
