Index: /branches/eam_branches/ipp-20101103/psphot/src/Makefile.am
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/Makefile.am	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/Makefile.am	(revision 29904)
@@ -102,16 +102,4 @@
 	psphotStackPSF.c	      \
 	psphotCleanup.c
-
-
-
-# # psphot analysis of the detectability of specified positions
-# psphotDetect_SOURCES =            \
-#         psphotDetect.c            \
-# 	psphotDetectArguments.c	  \
-# 	psphotDetectParseCamera.c \
-# 	psphotDetectImageLoop.c	  \
-# 	psphotDetectReadout.c	  \
-# 	psphotMosaicChip.c	  \
-# 	psphotCleanup.c
 
 # psphotTest_SOURCES = \
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphot.h
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphot.h	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphot.h	(revision 29904)
@@ -24,8 +24,8 @@
 bool            psphotModelTest (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
 bool            psphotInit (void);
-bool            psphotReadout (pmConfig *config, const pmFPAview *view);
-bool            psphotReadoutFindPSF(pmConfig *config, const pmFPAview *view, psArray *inSources);
-bool            psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources);
-bool            psphotReadoutMinimal(pmConfig *config, const pmFPAview *view);
+bool            psphotReadout (pmConfig *config, const pmFPAview *view, const char *filerule);
+bool            psphotReadoutFindPSF(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *inSources);
+bool            psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *inSources);
+bool            psphotReadoutMinimal(pmConfig *config, const pmFPAview *view, const char *filerule);
 
 bool            psphotReadoutCleanup (pmConfig *config, const pmFPAview *view, const char *filerule);
@@ -219,5 +219,5 @@
 bool            psphotFitSummary (void);
 
-bool            psphotLoadPSF (pmConfig *config, const pmFPAview *view);
+bool            psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule);
 bool            psphotLoadPSFReadout (pmConfig *config, const pmFPAview *view, const char *outFilename, const char *inFilename, int index);
 
@@ -304,9 +304,11 @@
 pmConfig *psphotForcedArguments(int argc, char **argv);
 bool psphotForcedImageLoop (pmConfig *config);
-bool psphotForcedReadout(pmConfig *config, const pmFPAview *view);
+bool psphotForcedReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
 
 pmConfig *psphotMakePSFArguments(int argc, char **argv);
 bool psphotMakePSFImageLoop (pmConfig *config);
-bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view);
+bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
+
+int psphotFileruleCount(const pmConfig *config, const char *filerule);
 
 /**** psphotStack prototypes ****/
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotAddNoise.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotAddNoise.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotAddNoise.c	(revision 29904)
@@ -18,6 +18,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotApResid.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotApResid.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotApResid.c	(revision 29904)
@@ -13,6 +13,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
@@ -72,8 +71,8 @@
     if (!measureAptrend) {
         // save nan values since these were not calculated
-        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
-        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
-        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
-        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
+        psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_META_REPLACE, "aperture residual",   NAN);
+        psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_META_REPLACE, "ap residual scatter", NAN);
+        psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_META_REPLACE, "number of apresid stars", 0);
+        psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_META_REPLACE, "aperture loss (mag)", NAN);
         return true;
     }
@@ -325,8 +324,8 @@
 
     // save results for later output
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   psf->ApResid);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth ? psf->growth->apLoss : NAN);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_META_REPLACE, "aperture residual",   psf->ApResid);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_META_REPLACE, "ap residual scatter", psf->dApResid);
+    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_META_REPLACE, "number of apresid stars", psf->nApResid);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_META_REPLACE, "aperture loss (mag)", psf->growth ? psf->growth->apLoss : NAN);
 
     psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);
@@ -345,8 +344,8 @@
 escape:
     // save nan values since these were not calculated
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
-    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_META_REPLACE, "aperture residual",   NAN);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_META_REPLACE, "ap residual scatter", NAN);
+    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_META_REPLACE, "number of apresid stars", 0);
+    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_META_REPLACE, "aperture loss (mag)", NAN);
 
     psFree (xPos);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotBasicDeblend.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotBasicDeblend.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotBasicDeblend.c	(revision 29904)
@@ -4,8 +4,5 @@
 bool psphotBasicDeblend (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
-    bool status = true;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotBlendFit.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotBlendFit.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotBlendFit.c	(revision 29904)
@@ -10,6 +10,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotChoosePSF.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotChoosePSF.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotChoosePSF.c	(revision 29904)
@@ -10,6 +10,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotDeblendSatstars.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDeblendSatstars.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotDeblendSatstars.c	(revision 29904)
@@ -4,8 +4,5 @@
 bool psphotDeblendSatstars (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
-    bool status = true;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetect.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetect.c	(revision 29903)
+++ 	(revision )
@@ -1,41 +1,0 @@
-# include "psphotDetect.h"
-
-static void usage (void) {
-    fprintf (stderr, "USAGE: psphotDetect [-mask image(s)] [-masklist masklist] [-psf psfmodel] [-points pointlist] (output)\n");
-    exit (PS_EXIT_CONFIG_ERROR);
-}
-
-int main (int argc, char **argv) {
-
-    psTimerStart ("complete");
-    pmErrorRegister();			// register psModule's error codes/messages
-    psphotInit();
-
-    // load command-line arguments, options, and system config data
-    pmConfig *config = psphotDetectArguments (argc, argv);
-    if (!config) {
-	psErrorStackPrint(stderr, "Error reading arguments\n");
-	usage ();
-    }
-
-    // load input data (config and images (signal, noise, mask)
-    if (!psphotDetectParseCamera (config)) {
-        psErrorStackPrint(stderr, "Error setting up the camera\n");
-        exit (psphotGetExitStatus());
-    }
-
-    // call psphot for each readout
-    if (!psphotDetectImageLoop (config)) {
-        psErrorStackPrint(stderr, "Error in the psphotDetect image loop\n");
-        exit (psphotGetExitStatus());
-    }
-
-    psLogMsg ("psphot", 3, "complete psphotDetect run: %f sec\n", psTimerMark ("complete"));
-
-    psErrorCode exit_status = psphotGetExitStatus();
-    psphotCleanup (config);
-    exit (exit_status);
-}
-
-// all functions which return to this level must raise one of the top-level error codes if they
-// exit with an error.  these error codes are used to specify the program exit status
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetect.h
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetect.h	(revision 29903)
+++ 	(revision )
@@ -1,23 +1,0 @@
-# ifdef HAVE_CONFIG_H
-# include <config.h>
-# endif
-
-#ifndef PSPHOT_DETECT_H
-#define PSPHOT_DETECT_H
-
-#include <stdio.h>
-#include <pslib.h>
-#include <psmodules.h>
-#include "psphot.h"
-
-// Top level functions
-pmConfig   *psphotDetectArguments(int argc, char **argv);
-bool        psphotDetectParseCamera (pmConfig *config);
-bool        psphotDetectImageLoop (pmConfig *config);
-bool        psphotDetectReadout(pmConfig *config, const pmFPAview *view);
-
-bool        psphotMosaicChip(pmConfig *config, const pmFPAview *view, char *outFile, char *inFile);
-void        psphotCleanup (pmConfig *config);
-psExit      psphotGetExitStatus (void);
-
-#endif
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetectArguments.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetectArguments.c	(revision 29903)
+++ 	(revision )
@@ -1,57 +1,0 @@
-# include "psphotDetect.h"
-
-pmConfig *psphotDetectArguments(int argc, char **argv) {
-
-    int N;
-
-    if (argc == 1) {
-        psError(PSPHOT_ERR_ARGUMENTS, true, "Too few arguments: %d", argc);
-        return NULL;
-    }
-
-    if ((N = psArgumentGet (argc, argv, "-version"))) {
-        psString version;
-        version = psphotVersionLong();    fprintf (stdout, "%s\n", version); psFree (version);
-        version = psModulesVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
-        version = psLibVersionLong();     fprintf (stdout, "%s\n", version); psFree (version);
-        exit (0);
-    }
-
-    // load config data from default locations
-    pmConfig *config = pmConfigRead(&argc, argv, PSPHOT_RECIPE);
-    if (config == NULL) {
-        psError(PSPHOT_ERR_CONFIG, false, "Can't read site configuration");
-        return NULL;
-    }
-
-    // save the following additional recipe values based on command-line options
-    // these options override the PSPHOT recipe values loaded from recipe files
-    psMetadata *options = pmConfigRecipeOptions (config, PSPHOT_RECIPE);
-
-    // XXX add psphot thread arguments?
-
-    // all three of these input files are required: if not found, we will exit
-    if (!pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",   "-mask",    "-masklist")) {
-        psError(PSPHOT_ERR_ARGUMENTS, false, "mask image not supplied");
-        return NULL;
-    }
-    if (!pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf", "-psflist")) {
-        psError(PSPHOT_ERR_ARGUMENTS, false, "mask image not supplied");
-        return NULL;
-    }
-    if (!pmConfigFileSetsMD (config->arguments, &argc, argv, "POINTS", "-points",  "-pointslist")) {
-        psError(PSPHOT_ERR_ARGUMENTS, false, "mask image not supplied");
-        return NULL;
-    }
-
-    if (argc != 2) {
-        psError(PSPHOT_ERR_ARGUMENTS, true, "Expected to see one more argument; saw %d", argc - 1);
-        return NULL;
-    }
-
-    // output position is fixed
-    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
-
-    psTrace("psphot", 1, "Done with psphotDetectArguments...\n");
-    return (config);
-}
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetectImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetectImageLoop.c	(revision 29903)
+++ 	(revision )
@@ -1,97 +1,0 @@
-# include "psphotDetect.h"
-
-# define ESCAPE(MESSAGE) { \
-  psError(PSPHOT_ERR_DATA, false, MESSAGE); \
-  psFree (view); \
-  return false; \
-}
-
-bool psphotDetectImageLoop (pmConfig *config) {
-
-    bool status;
-    pmChip *chip;
-    pmCell *cell;
-    pmReadout *readout;
-
-    pmFPAfile *mask = psMetadataLookupPtr (&status, config->files, "PSPHOT.MASK");
-    if (!status) {
-	psError(PSPHOT_ERR_PROG, false, "Can't find input mask data!");
-	return false;
-    }
-    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
-    if (!status) {
-	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
-	return false;
-    }
-
-    pmFPAview *view = pmFPAviewAlloc (0);
-    
-    // files associated with the science image
-    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa in psphot.");
-
-    // for psphot, we force data to be read at the chip level 
-    while ((chip = pmFPAviewNextChip (view, mask->fpa, 1)) != NULL) {
-        psLogMsg ("psphot", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
-        if (!chip->process || !chip->file_exists) { continue; }
-
-	// load just the input image data (image, mask, weight)
-	pmFPAfileActivate (config->files, false, NULL);
-	pmFPAfileActivate (config->files, true, "PSPHOT.MASK");
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");
-
-	// mosaic the cells of a chip into a single contiguous (trimmed) chip
-        if (!psphotMosaicChip(config, view, "PSPHOT.INPUT", "PSPHOT.MASK")) ESCAPE ("Unable to mosaic chip.");
-
-	// try to load other supporting data (PSF, SRC, etc).
-	// do not re-load the mask three files
-	pmFPAfileActivate (config->files, true, NULL);
-	pmFPAfileActivate (config->files, false, "PSPHOT.MASK");
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for Chip in psphot.");
-
-	// re-activate files so they will be closed and freed below
-	pmFPAfileActivate (config->files, true, NULL);
-
-	// there is now only a single chip (multiple readouts?). loop over it and process
-	while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
-            psLogMsg ("psphot", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
-
-	    // process each of the readouts
-	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
-		psLogMsg ("psphot", 6, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
-		if (!readout->data_exists) { continue; }
-
-		// run the actual photometry analysis on this chip/cell/readout
-		if (!psphotDetectReadout (config, view)) {
-		    psError(psErrorCodeLast(), false, "failure in psphotDetectReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-	    }
-	}
-
-	// save output which is saved at the chip level
-	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
-    }
-    // save output which is saved at the fpa level
-    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed ouput for FPA in psphot.");
-
-    // fail if we failed to handle an error
-    if (psErrorCodeLast() != PS_ERR_NONE) psAbort ("failed to handle an error!");
-
-    psFree (view);
-    return true;
-}
-
-// I/O files related to psphot:
-// PSPHOT.INPUT   : input image file(s)
-// PSPHOT.RESID   : residual image
-// PSPHOT.OUTPUT  : output object tables (object)
-
-// PSPHOT.BACKSUB : background subtracted image
-// PSPHOT.BACKGND : background model (full-scale image?)
-// PSPHOT.BACKMDL : background model (binned image?)
-// PSPHOT.PSF     : sample PSF images
-
-// PSPHOT.MASK
-// PSPHOT.WEIGHT
-// 
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetectParseCamera.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetectParseCamera.c	(revision 29903)
+++ 	(revision )
@@ -1,43 +1,0 @@
-# include "psphotDetect.h"
-
-// define the needed / desired I/O files
-bool psphotDetectParseCamera (pmConfig *config) {
-
-    bool status = false;
-
-    // if MASK or WEIGHT was supplied on command line, bind files to 'load'
-    // the mask and weight will be mosaicked with the image
-    pmFPAfile *mask = pmFPAfileDefineFromArgs (&status, config, "PSPHOT.MASK", "MASK");
-    if (!status) {
-        psError (PS_ERR_UNKNOWN, false, "failed to load find definition");
-        return NULL;
-    }
-    if (!psphotSetMaskBits (config)) {
-      // XXX shouldn't this come after the file has been read?
-        psError (PS_ERR_UNKNOWN, false, "failed to set mask bit values");
-        return NULL;
-    }
-    mask->dataLevel = PM_FPA_LEVEL_CHIP; // force load at the CHIP level
-
-    // the psphot analysis is performed on chips
-    pmFPAfile *input = pmFPAfileDefineChipMosaic(config, mask->fpa, "PSPHOT.INPUT");
-    if (!input) {
-        psError(PSPHOT_ERR_CONFIG, false, _("Unable to generate new file from PSPHOT.INPUT"));
-        return NULL;
-    }
-
-    // the PSF model is required
-    pmFPAfileBindFromArgs(&status, mask, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
-    if (!status) {
-      psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.PSF.LOAD");
-      return status;
-    }
-
-    if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.PTS", "POINTS")) {
-      psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.PTS");
-      return status;
-    }
-
-    psErrorClear();                     // some metadata lookup may have failed
-    return true;
-}
Index: anches/eam_branches/ipp-20101103/psphot/src/psphotDetectReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotDetectReadout.c	(revision 29903)
+++ 	(revision )
@@ -1,54 +1,0 @@
-# include "psphotInternal.h"
-
-bool psphotDetectReadout(pmConfig *config, const pmFPAview *view) {
-
-    // measure the total elapsed time in psphotReadout.  XXX the current threading plan
-    // for psphot envisions threading within psphotReadout, not multiple threads calling
-    // the same psphotReadout.  In the current plan, this dtime is the elapsed time used
-    // jointly by the multiple threads, not the total time used by all threads.
-    psTimerStart ("psphotReadout");
-
-    // select the current recipe
-    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
-    if (!recipe) {
-        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
-        return false;
-    }
-
-    // find the currently selected readout
-    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
-    PS_ASSERT_PTR_NON_NULL (readout, false);
-
-    // Generate the mask and weight images, including the user-defined analysis region of interest
-    psphotSetMaskAndWeight (config, readout, recipe);
-
-    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
-    pmPSF *psf = psphotLoadPSF (config, view, recipe);
-    psAssert (psf, "psf should be loaded");
-
-    // grab the sources of interest from the storage location (pmFPAfile PSPHOT.INPUT.CMF)
-    psArray *sources = psphotLoadPSFSources (config, view);
-    if (!sources) {
-      psError(PS_ERR_UNKNOWN, false, "No sources supplied to measure PSF");
-      return false;
-    }
-
-    // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
-    psphotSetSourceParams (config, sources, psf);
-
-    // calculate source magnitudes
-    psphotPSFWeights(config, readout, view, sources);
-
-    // create the exported-metadata and free local data
-    return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
-}
-
-// deep in pmSourcePixelWeight, we need the following items for each location of interest:
-// pmModel *model (should be a realized version of the PSF, can have unity normalization)
-// psImage *mask  (local subimage of mask for source)
-// psImageMaskType maskVal (from recipe & mask header)
-
-{ 
-    pmModel *model = pmModelFromPSFforXY (psf, x, y, 1.0);
-}
-
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotEfficiency.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotEfficiency.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotEfficiency.c	(revision 29904)
@@ -164,6 +164,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysis.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysis.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysis.c	(revision 29904)
@@ -22,6 +22,5 @@
     }
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysisByObject.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysisByObject.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceAnalysisByObject.c	(revision 29904)
@@ -41,6 +41,5 @@
 
     // number of images used to define sources
-    int nImages = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int nImages = psphotFileruleCount(config, filerule);
 
     // generate look-up arrays for readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceFits.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceFits.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotExtendedSourceFits.c	(revision 29904)
@@ -16,6 +16,5 @@
     }
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotFindDetections.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotFindDetections.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotFindDetections.c	(revision 29904)
@@ -12,6 +12,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotFitSourcesLinear.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotFitSourcesLinear.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotFitSourcesLinear.c	(revision 29904)
@@ -21,6 +21,5 @@
     assert (recipe);
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedImageLoop.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedImageLoop.c	(revision 29904)
@@ -84,5 +84,5 @@
 
                 // run the actual photometry analysis on this chip/cell/readout
-                if (!psphotForcedReadout (config, view)) {
+                if (!psphotForcedReadout (config, view, "PSPHOT.INPUT")) {
                     psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
                     psFree (view);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedReadout.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotForcedReadout.c	(revision 29904)
@@ -1,5 +1,5 @@
 # include "psphotInternal.h"
 
-bool psphotForcedReadout(pmConfig *config, const pmFPAview *view) {
+bool psphotForcedReadout(pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     // measure the total elapsed time in psphotReadout.  XXX the current threading plan
@@ -20,5 +20,5 @@
 
     // set the photcode for this image
-    if (!psphotAddPhotcode (config, view, "PSPHOT.INPUT")) {
+    if (!psphotAddPhotcode (config, view, filerule)) {
         psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -30,38 +30,38 @@
 
     // Generate the mask and weight images, including the user-defined analysis region of interest
-    psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT");
+    psphotSetMaskAndVariance (config, view, filerule);
     if (!strcasecmp (breakPt, "NOTHING")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // generate a background model (median, smoothed image)
-    if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    if (!psphotModelBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
     }
-    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    if (!psphotSubtractBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "BACKMDL")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
-    if (!psphotLoadPSF (config, view)) {
+    if (!psphotLoadPSF (config, view, filerule)) {
     	// this only happens if we had a programming error in psphotLoadPSF
         psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // include externally-supplied sources
-    psphotLoadExtSources (config, view, "PSPHOT.INPUT");
+    psphotLoadExtSources (config, view, filerule);
 
     // construct an initial model for each object, set the radius to fitRadius, set circular fit mask
-    psphotGuessModels (config, view, "PSPHOT.INPUT");
+    psphotGuessModels (config, view, filerule);
 
     // merge the newly selected sources into the existing list
     // NOTE: merge OLD and NEW
-    psphotMergeSources (config, view, "PSPHOT.INPUT");
+    psphotMergeSources (config, view, filerule);
 
     // linear PSF fit to source peaks, subtract the models from the image (in PSF mask)
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", false);
+    psphotFitSourcesLinear (config, view, filerule, false);
 
     // identify CRs and extended sources
@@ -71,5 +71,5 @@
 
     // calculate source magnitudes
-    psphotMagnitudes(config, view, "PSPHOT.INPUT");
+    psphotMagnitudes(config, view, filerule);
 
     // XXX do I want to do this?
@@ -80,10 +80,10 @@
 
     // replace background in residual image
-    psphotSkyReplace (config, view, "PSPHOT.INPUT");
+    psphotSkyReplace (config, view, filerule);
 
     // drop the references to the image pixels held by each source
-    psphotSourceFreePixels (config, view, "PSPHOT.INPUT");
+    psphotSourceFreePixels (config, view, filerule);
 
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup (config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotGuessModels.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotGuessModels.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotGuessModels.c	(revision 29904)
@@ -12,6 +12,5 @@
     bool status = true;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotImageLoop.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotImageLoop.c	(revision 29904)
@@ -109,5 +109,5 @@
 
                 // run the actual photometry analysis on this chip/cell/readout
-                if (!psphotReadout (config, view)) {
+                if (!psphotReadout (config, view, "PSPHOT.INPUT")) {
                     psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
                     psFree (view);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotImageQuality.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotImageQuality.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotImageQuality.c	(revision 29904)
@@ -13,6 +13,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotLoadPSF.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotLoadPSF.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotLoadPSF.c	(revision 29904)
@@ -6,5 +6,5 @@
 
 // XXX for now (2010.01.27), the supporting programs do not define multiple PSPHOT.PSF.LOAD
-// files to go with multiple PSPHOT.INPUT files.  as a result, the implementation below is
+// files to go with multiple input files.  as a result, the implementation below is
 // currently going to work for the case of a single input file, but will fail if we try with a
 // stack of images.
@@ -59,11 +59,8 @@
 }
 
-bool psphotLoadPSF (pmConfig *config, const pmFPAview *view) {
+// PSPHOT.PSF.LOAD vs input file -- see note at top
+bool psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule) {
 
-    bool status = false;
-
-    // XXX PSPHOT.PSF.LOAD vs PSPHOT.INPUT -- see note at top
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
@@ -71,5 +68,5 @@
 
         // Generate the mask and weight images, including the user-defined analysis region of interest
-        if (!psphotLoadPSFReadout (config, view, "PSPHOT.INPUT", "PSPHOT.PSF.LOAD", i)) {
+        if (!psphotLoadPSFReadout (config, view, filerule, "PSPHOT.PSF.LOAD", i)) {
             psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
             return false;
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotMagnitudes.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotMagnitudes.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotMagnitudes.c	(revision 29904)
@@ -9,6 +9,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFImageLoop.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFImageLoop.c	(revision 29904)
@@ -84,5 +84,5 @@
 
                 // run the actual photometry analysis on this chip/cell/readout
-                if (!psphotMakePSFReadout (config, view)) {
+                if (!psphotMakePSFReadout (config, view, "PSPHOT.INPUT")) {
                     psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
                     psFree (view);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFReadout.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotMakePSFReadout.c	(revision 29904)
@@ -1,5 +1,5 @@
 # include "psphotInternal.h"
 
-bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view) {
+bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     // measure the total elapsed time in psphotReadout.  XXX the current threading plan
@@ -19,5 +19,5 @@
 
     // set the photcode for this image
-    if (!psphotAddPhotcode (config, view, "PSPHOT.INPUT")) {
+    if (!psphotAddPhotcode (config, view, filerule)) {
         psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -29,21 +29,21 @@
 
     // Generate the mask and weight images, including the user-defined analysis region of interest
-    psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT");
+    psphotSetMaskAndVariance (config, view, filerule);
     if (!strcasecmp (breakPt, "NOTHING")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // generate a background model (median, smoothed image)
-    if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    if (!psphotModelBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
     }
-    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    if (!psphotSubtractBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "BACKMDL")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
-    psphotLoadExtSources (config, view, "PSPHOT.INPUT");
+    psphotLoadExtSources (config, view, filerule);
 
     // If sources have been supplied, then these should be used to measure the PSF include
@@ -53,24 +53,24 @@
     // a text file have no valid SN values, but psphotChoosePSF needs to select the top
     // PSF_MAX_NSTARS to generate the PSF.
-    if (!psphotCheckExtSources (config, view, "PSPHOT.INPUT")) {
+    if (!psphotCheckExtSources (config, view, filerule)) {
 	psLogMsg ("psphot", 3, "failure to select possible PSF sources (external or internal)");
-	return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+	return psphotReadoutCleanup (config, view, filerule);
     }
 
     // Use bright stellar objects to measure PSF. If we do not have enough stars to generate
     // the PSF, build one from the SEEING guess and model class
-    if (!psphotChoosePSF (config, view, "PSPHOT.INPUT")) {
+    if (!psphotChoosePSF (config, view, filerule)) {
 	psLogMsg ("psphot", 3, "failure to construct a psf model");
-	return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+	return psphotReadoutCleanup (config, view, filerule);
     }
 
     // measure aperture photometry corrections
 # if 0
-    if (!psphotApResid (config, view, "PSPHOT.INPUT")) {
+    if (!psphotApResid (config, view, filerule)) {
         psLogMsg ("psphot", 3, "failed on psphotApResid");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 # endif
 
-    return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup (config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotMaskReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotMaskReadout.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotMaskReadout.c	(revision 29904)
@@ -9,6 +9,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
@@ -17,5 +16,5 @@
 	// Generate the mask and weight images, including the user-defined analysis region of interest
 	if (!psphotSetMaskAndVarianceReadout (config, view, filerule, i, recipe)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to generate mask for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed to generate mask for %s entry %d", filerule, i);
 	    return false;
 	}
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotMergeSources.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotMergeSources.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotMergeSources.c	(revision 29904)
@@ -8,8 +8,5 @@
 bool psphotMergeSources (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
-    bool status = true;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
@@ -70,5 +67,5 @@
 // XXX This function needs to be updated to loop over set of input files.  At the moment, we
 // 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
+// associate input sources with a single entry for the filerule
 bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view, const char *filerule) {
 
@@ -405,6 +402,5 @@
     bool status = true;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, ruleSrc);
 
     // skip the chisq image because it is a duplicate of the detection version
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotModelBackground.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotModelBackground.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotModelBackground.c	(revision 29904)
@@ -383,16 +383,12 @@
 }
 
-// XXX supply filename or keep PSPHOT.INPUT fixed?
 bool psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
-    bool status = false;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
         if (!psphotModelBackgroundReadoutFileIndex(config, view, filerule, i)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to model background for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed to model background for %s entry %d", filerule, i);
             return false;
         }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotOutput.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotOutput.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotOutput.c	(revision 29904)
@@ -1,3 +1,16 @@
 # include "psphotInternal.h"
+
+// convert filerule to filerule.NUM and look up in the config->arguments metadata
+int psphotFileruleCount(const pmConfig *config, const char *filerule) {
+
+    bool status = false;
+
+    psString name = NULL;
+    psStringAppend(&name, "%s.NUM", filerule);
+    int num = psMetadataLookupS32 (&status, config->arguments, name);
+    psAssert (status, "programming error: must define %s", name);
+    psFree (name);
+    return num;
+}
 
 pmReadout *psphotSelectBackground (pmConfig *config,
@@ -117,13 +130,10 @@
 bool psphotAddPhotcode (pmConfig *config, const pmFPAview *view, const char *filerule) {
 
-    bool status = false;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
 	if (!psphotAddPhotcodeReadout (config, view, filerule, i)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to add photcode to PSPHOT.INPUT entry %d", i);
+	  psError (PSPHOT_ERR_CONFIG, false, "failed to add photcode to %s entry %d", filerule, i);
 	    return false;
 	}
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialApertures.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialApertures.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialApertures.c	(revision 29904)
@@ -18,6 +18,5 @@
     }
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialAperturesByObject.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialAperturesByObject.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotRadialAperturesByObject.c	(revision 29904)
@@ -21,6 +21,5 @@
 
     // number of images used to define sources
-    int nImages = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int nImages = psphotFileruleCount(config, filerule);
 
     // radMax stores the upper bounds of the annuli
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReadout.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReadout.c	(revision 29904)
@@ -9,5 +9,5 @@
 }
 
-bool psphotReadout(pmConfig *config, const pmFPAview *view) {
+bool psphotReadout(pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     // measure the total elapsed time in psphotReadout.  dtime is the elapsed time used jointly
@@ -28,5 +28,5 @@
 
     // set the photcode for this image
-    if (!psphotAddPhotcode (config, view, "PSPHOT.INPUT")) {
+    if (!psphotAddPhotcode (config, view, filerule)) {
         psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -34,102 +34,101 @@
 
     // Generate the mask and weight images, including the user-defined analysis region of interest
-    if (!psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup(config, view, "PSPHOT.INPUT");
+    if (!psphotSetMaskAndVariance (config, view, filerule)) {
+        return psphotReadoutCleanup(config, view, filerule);
     }
     if (!strcasecmp (breakPt, "NOTHING")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // generate a background model (median, smoothed image)
-    if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
-    }
-
-    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    if (!psphotModelBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
+    }
+
+    if (!psphotSubtractBackground (config, view, filerule)) {
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "BACKMDL")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // load the psf model, if suppled.  FWHM_MAJ,FWHM_MIN,etc are determined and saved on
-    // readout->analysis. XXX Note: this function currently only works with a single
-    // PSPHOT.INPUT
-    if (!psphotLoadPSF (config, view)) { // ??? need to supply 2 ?
+    // readout->analysis. NOTE: this function currently only loads from PSPHOT.PSF.LOAD
+    if (!psphotLoadPSF (config, view, filerule)) { // ??? need to supply 2 ?
         psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // find the detections (by peak and/or footprint) in the image.
-    if (!psphotFindDetections (config, view, "PSPHOT.INPUT", true)) { // pass 1
+    if (!psphotFindDetections (config, view, filerule, true)) { // pass 1
         // this only happens if we had an error in psphotFindDetections
         psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct sources and measure basic stats (saved on detections->newSources)
-    if (!psphotSourceStats (config, view, "PSPHOT.INPUT", true)) { // pass 1
+    if (!psphotSourceStats (config, view, filerule, true)) { // pass 1
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "PEAKS")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // find blended neighbors of very saturated stars (detections->newSources)
-    if (!psphotDeblendSatstars (config, view, "PSPHOT.INPUT")) {
+    if (!psphotDeblendSatstars (config, view, filerule)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // mark blended peaks PS_SOURCE_BLEND (detections->newSources)
-    if (!psphotBasicDeblend (config, view, "PSPHOT.INPUT")) {
+    if (!psphotBasicDeblend (config, view, filerule)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failed on deblend analysis");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // classify sources based on moments, brightness.  if a PSF model has been loaded, the PSF
     // clump defined for it is used not measured (detections->newSources)
-    if (!psphotRoughClass (config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotRoughClass (config, view, filerule)) { // pass 1
         psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // if we were not supplied a PSF model, determine the IQ stats here (detections->newSources)
-    if (!psphotImageQuality (config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotImageQuality (config, view, filerule)) { // pass 1
         psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "MOMENTS")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // use bright stellar objects to measure PSF if we were supplied a PSF for any input file,
     // this step is skipped
-    if (!psphotChoosePSF (config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotChoosePSF (config, view, filerule)) { // pass 1
         psLogMsg ("psphot", 3, "failure to construct a psf model");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
     if (!strcasecmp (breakPt, "PSFMODEL")) {
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // include externally-supplied sources
     // XXX fix this in the new multi-input context
-    // psphotLoadExtSources (config, view, "PSPHOT.INPUT"); // pass 1
+    // psphotLoadExtSources (config, view, filerule); // pass 1
 
     // construct an initial model for each object, set the radius to fitRadius, set circular
     // fit mask (detections->newSources)
-    psphotGuessModels (config, view, "PSPHOT.INPUT"); // pass 1
+    psphotGuessModels (config, view, filerule); // pass 1
 
     // merge the newly selected sources into the existing list
     // NOTE: merge OLD and NEW
-    psphotMergeSources (config, view, "PSPHOT.INPUT");
+    psphotMergeSources (config, view, filerule);
 
     // linear PSF fit to source peaks, subtract the models from the image (in PSF mask)
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", false); // pass 1 (detections->allSources)
+    psphotFitSourcesLinear (config, view, filerule, false); // pass 1 (detections->allSources)
 
     // identify CRs and extended sources (only unmeasured sources are measured)
-    psphotSourceSize (config, view, "PSPHOT.INPUT", true); // pass 1 (detections->allSources)
+    psphotSourceSize (config, view, filerule, true); // pass 1 (detections->allSources)
     if (!strcasecmp (breakPt, "ENSEMBLE")) {
         goto finish;
@@ -138,12 +137,12 @@
     // non-linear PSF and EXT fit to brighter sources
     // replace model flux, adjust mask as needed, fit, subtract the models (full stamp)
-    psphotBlendFit (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
+    psphotBlendFit (config, view, filerule); // pass 1 (detections->allSources)
 
     // replace all sources
-    psphotReplaceAllSources (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
+    psphotReplaceAllSources (config, view, filerule); // pass 1 (detections->allSources)
 
     // linear fit to include all sources (subtract again)
     // NOTE : apply to ALL sources (extended + psf)
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", true); // pass 2 (detections->allSources)
+    psphotFitSourcesLinear (config, view, filerule, true); // pass 2 (detections->allSources)
 
     // if we only do one pass, skip to extended source analysis
@@ -153,40 +152,40 @@
 
     // add noise for subtracted objects
-    psphotAddNoise (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
+    psphotAddNoise (config, view, filerule); // pass 1 (detections->allSources)
 
     // find fainter sources
     // NOTE: finds new peaks and new footprints, OLD and FULL set are saved on detections
-    psphotFindDetections (config, view, "PSPHOT.INPUT", false); // pass 2 (detections->peaks, detections->footprints)
+    psphotFindDetections (config, view, filerule, false); // pass 2 (detections->peaks, detections->footprints)
 
     // remove noise for subtracted objects (ie, return to normal noise level)
     // NOTE: this needs to operate only on the OLD sources
-    psphotSubNoise (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
+    psphotSubNoise (config, view, filerule); // pass 1 (detections->allSources)
 
     // define new sources based on only the new peaks
     // NOTE: new sources are saved on detections->newSources
-    psphotSourceStats (config, view, "PSPHOT.INPUT", false); // pass 2 (detections->newSources)
+    psphotSourceStats (config, view, filerule, false); // pass 2 (detections->newSources)
 
     // set source type
     // NOTE: apply only to detections->newSources
-    if (!psphotRoughClass (config, view, "PSPHOT.INPUT")) { // pass 2 (detections->newSources)
+    if (!psphotRoughClass (config, view, filerule)) { // pass 2 (detections->newSources)
         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // create full input models, set the radius to fitRadius, set circular fit mask
     // NOTE: apply only to detections->newSources
-    psphotGuessModels (config, view, "PSPHOT.INPUT"); // pass 2 (detections->newSources)
+    psphotGuessModels (config, view, filerule); // pass 2 (detections->newSources)
 
     // replace all sources so fit below applies to all at once
     // NOTE: apply only to OLD sources (which have been subtracted)
-    psphotReplaceAllSources (config, view, "PSPHOT.INPUT"); // pass 2
+    psphotReplaceAllSources (config, view, filerule); // pass 2
 
     // merge the newly selected sources into the existing list
     // NOTE: merge OLD and NEW
     // XXX check on free of sources...
-    psphotMergeSources (config, view, "PSPHOT.INPUT"); // (detections->newSources + detections->allSources -> detections->allSources)
+    psphotMergeSources (config, view, filerule); // (detections->newSources + detections->allSources -> detections->allSources)
 
     // NOTE: apply to ALL sources
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", true); // pass 3 (detections->allSources)
+    psphotFitSourcesLinear (config, view, filerule, true); // pass 3 (detections->allSources)
 
 pass1finish:
@@ -194,8 +193,8 @@
     // measure source size for the remaining sources
     // NOTE: applies only to NEW (unmeasured) sources
-    psphotSourceSize (config, view, "PSPHOT.INPUT", false); // pass 2 (detections->allSources)
-
-    psphotExtendedSourceAnalysis (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
-    psphotExtendedSourceFits (config, view, "PSPHOT.INPUT"); // pass 1 (detections->allSources)
+    psphotSourceSize (config, view, filerule, false); // pass 2 (detections->allSources)
+
+    psphotExtendedSourceAnalysis (config, view, filerule); // pass 1 (detections->allSources)
+    psphotExtendedSourceFits (config, view, filerule); // pass 1 (detections->allSources)
 
 finish:
@@ -205,15 +204,15 @@
 
     // measure aperture photometry corrections
-    if (!psphotApResid (config, view, "PSPHOT.INPUT")) { // pass 1 (detections->allSources)
+    if (!psphotApResid (config, view, filerule)) { // pass 1 (detections->allSources)
         psLogMsg ("psphot", 3, "failed on psphotApResid");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // calculate source magnitudes
-    if (!psphotMagnitudes(config, view, "PSPHOT.INPUT")) { // pass 1 (detections->allSources)
+    if (!psphotMagnitudes(config, view, filerule)) { // pass 1 (detections->allSources)
       psErrorStackPrint(stderr, "Unable to do magnitudes.");
         psErrorClear();
     }
-    if (!psphotEfficiency(config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotEfficiency(config, view, filerule)) { // pass 1
         psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
         psErrorClear();
@@ -224,20 +223,20 @@
 
     // replace background in residual image
-    if (!psphotSkyReplace (config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotSkyReplace (config, view, filerule)) { // pass 1
       psErrorStackPrint(stderr, "Unable to replace sky");
       psErrorClear();
 
 /*       psLogMsg("psphot", 3, "failed on psphotSkyReplace"); */
-/*       return(psphotReadoutCleanup(config, view, "PSPHOT.INPUT")); */
+/*       return(psphotReadoutCleanup(config, view, filerule)); */
     }
     // drop the references to the image pixels held by each source
-    if (!psphotSourceFreePixels (config, view, "PSPHOT.INPUT")) { // pass 1
+    if (!psphotSourceFreePixels (config, view, filerule)) { // pass 1
       psErrorStackPrint(stderr, "Unable to free source pixels");
       psErrorClear();
 
 /*       psLogMsg ("psphot", 3, "failed on psphotSourceFreePixels"); */
-/*       return(psphotReadoutCleanup(config, view, "PSPHOT.INPUT")); */
+/*       return(psphotReadoutCleanup(config, view, filerule)); */
     }
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup(config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup(config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutCleanup.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutCleanup.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutCleanup.c	(revision 29904)
@@ -19,6 +19,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutFindPSF.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutFindPSF.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutFindPSF.c	(revision 29904)
@@ -3,10 +3,10 @@
 // in this psphotReadout-variant, we are only trying to determine the PSF given an existing set
 // of input source positions to use as initial PSF stars.
-bool psphotReadoutFindPSF(pmConfig *config, const pmFPAview *view, psArray *inSources) {
+bool psphotReadoutFindPSF(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *inSources) {
 
     psTimerStart ("psphotReadout");
 
-    // set the photcode for the PSPHOT.INPUT
-    if (!psphotAddPhotcode(config, view, "PSPHOT.INPUT")) {
+    // set the photcode for the input
+    if (!psphotAddPhotcode(config, view, filerule)) {
         psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -14,18 +14,18 @@
 
     // Generate the mask and variance images, including the user-defined analysis region of interest
-    psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT");
+    psphotSetMaskAndVariance (config, view, filerule);
 
     // Note that in this implementation, we do NOT model the background and we do not
     // attempt to detect the sources in the image
 
-    // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
-    // XXX we assume a single set of input sources is supplied
-    if (!psphotDetectionsFromSources (config, view, "PSPHOT.INPUT", inSources)) {
+    // include the externally-supplied sources (inSources)
+    // (we assume a single set of input sources is supplied)
+    if (!psphotDetectionsFromSources (config, view, filerule, inSources)) {
         psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct detections->newSources and measure basic stats (moments, local sky)
-    if (!psphotSourceStats(config, view, "PSPHOT.INPUT", true)) {
+    if (!psphotSourceStats(config, view, filerule, true)) {
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
 	return false;
@@ -33,5 +33,5 @@
 
     // peak flux is wrong : use the peak measured in the moments analysis:
-    if (!psphotRepairLoadedSources(config, view, "PSPHOT.INPUT")) {
+    if (!psphotRepairLoadedSources(config, view, filerule)) {
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to repair sources");
 	return false;
@@ -39,17 +39,17 @@
 
     // classify sources based on moments, brightness (psf is not known)
-    if (!psphotRoughClass (config, view, "PSPHOT.INPUT")) {
+    if (!psphotRoughClass (config, view, filerule)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough source class");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
-    if (!psphotImageQuality (config, view, "PSPHOT.INPUT")) {
+    if (!psphotImageQuality (config, view, filerule)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
-    if (!psphotChoosePSF(config, view, "PSPHOT.INPUT")) {
+    if (!psphotChoosePSF(config, view, filerule)) {
         psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
@@ -59,23 +59,23 @@
     // fits from that analysis, or run the linear PSF fit for all objects currently in hand
     // construct an initial model for each object, set the radius to fitRadius, set circular fit mask
-    psphotGuessModels (config, view, "PSPHOT.INPUT");
+    psphotGuessModels (config, view, filerule);
 # endif
 
     // merge the newly selected sources into the existing list
     // NOTE: merge OLD and NEW
-    psphotMergeSources (config, view, "PSPHOT.INPUT"); 
+    psphotMergeSources (config, view, filerule); 
 
 # if 0
     // measure aperture photometry corrections
-    if (!psphotApResid (config, view, "PSPHOT.INPUT")) {
+    if (!psphotApResid (config, view, filerule)) {
         psLogMsg ("psphot", 3, "failed on psphotApResid");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 # endif
 
     // drop the references to the image pixels held by each source
-    psphotSourceFreePixels(config, view, "PSPHOT.INPUT");
+    psphotSourceFreePixels(config, view, filerule);
 
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup (config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutKnownSources.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutKnownSources.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutKnownSources.c	(revision 29904)
@@ -3,10 +3,10 @@
 // in this psphotReadout-variant, we are only measuring the photometry for known sources, using
 // a PSF generated for this observation from those sources
-bool psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources) {
+bool psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *inSources) {
 
     psTimerStart ("psphotReadout");
 
     // set the photcode for this image
-    if (!psphotAddPhotcode(config, view, "PSPHOT.INPUT")) {
+    if (!psphotAddPhotcode(config, view, filerule)) {
         psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -14,5 +14,5 @@
 
     // Generate the mask and weight images, including the user-defined analysis region of interest
-    psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT");
+    psphotSetMaskAndVariance (config, view, filerule);
 
     // Note that in this implementation, we do NOT model the background and we do not
@@ -20,11 +20,11 @@
 
     // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
-    if (!psphotDetectionsFromSources (config, view, "PSPHOT.INPUT", inSources)) {
+    if (!psphotDetectionsFromSources (config, view, filerule, inSources)) {
         psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct sources and measure basic stats
-    if (!psphotSourceStats (config, view, "PSPHOT.INPUT", true)) {
+    if (!psphotSourceStats (config, view, filerule, true)) {
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
 	return false;
@@ -32,5 +32,5 @@
 
     // peak flux is wrong : use the peak measured in the moments analysis:
-    if (!psphotRepairLoadedSources(config, view, "PSPHOT.INPUT")) {
+    if (!psphotRepairLoadedSources(config, view, filerule)) {
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to repair sources");
 	return false;
@@ -38,37 +38,37 @@
 
     // classify sources based on moments, brightness (psf is not known)
-    if (!psphotRoughClass (config, view, "PSPHOT.INPUT")) {
+    if (!psphotRoughClass (config, view, filerule)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough source class");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
-    if (!psphotChoosePSF (config, view, "PSPHOT.INPUT")) {
+    if (!psphotChoosePSF (config, view, filerule)) {
         psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct an initial model for each object
-    psphotGuessModels (config, view, "PSPHOT.INPUT");
+    psphotGuessModels (config, view, filerule);
 
     // merge the newly selected sources into the existing list
     // NOTE: merge OLD and NEW
-    psphotMergeSources (config, view, "PSPHOT.INPUT"); 
+    psphotMergeSources (config, view, filerule); 
 
     // linear PSF fit to source peaks
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", false);
+    psphotFitSourcesLinear (config, view, filerule, false);
 
     // measure aperture photometry corrections
-    if (!psphotApResid (config, view, "PSPHOT.INPUT")) {
+    if (!psphotApResid (config, view, filerule)) {
         psLogMsg ("psphot", 3, "failed on psphotApResid");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // calculate source magnitudes
-    psphotMagnitudes(config, view, "PSPHOT.INPUT");
+    psphotMagnitudes(config, view, filerule);
 
     // drop the references to the image pixels held by each source
-    psphotSourceFreePixels (config, view, "PSPHOT.INPUT");
+    psphotSourceFreePixels (config, view, filerule);
 
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup (config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutMinimal.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutMinimal.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReadoutMinimal.c	(revision 29904)
@@ -7,5 +7,5 @@
 // NOTE: ppSub needs to perform extended source analysis for comets and trails.
 
-bool psphotReadoutMinimal(pmConfig *config, const pmFPAview *view) {
+bool psphotReadoutMinimal(pmConfig *config, const pmFPAview *view, const char *filerule) {
 
     // measure the total elapsed time in psphotReadout.  XXX the current threading plan
@@ -18,5 +18,5 @@
 
     // set the photcode for this image
-    if (!psphotAddPhotcode(config, view, "PSPHOT.INPUT")) {
+    if (!psphotAddPhotcode(config, view, filerule)) {
         psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
         return false;
@@ -24,63 +24,63 @@
 
     // Generate the mask and weight images, including the user-defined analysis region of interest
-    psphotSetMaskAndVariance (config, view, "PSPHOT.INPUT");
+    psphotSetMaskAndVariance (config, view, filerule);
 
     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved on readout->analysis
-    if (!psphotLoadPSF (config, view)) {
+    if (!psphotLoadPSF (config, view, filerule)) {
       psError (PSPHOT_ERR_CONFIG, false, "missing psf model");
-      return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+      return psphotReadoutCleanup (config, view, filerule);
     }
 
     // find the detections (by peak and/or footprint) in the image. (final pass)
-    if (!psphotFindDetections(config, view, "PSPHOT.INPUT", false)) {
+    if (!psphotFindDetections(config, view, filerule, false)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct sources and measure basic stats (saved on detections->newSources)
-    if (!psphotSourceStats (config, view, "PSPHOT.INPUT", false)) { // pass 1
+    if (!psphotSourceStats (config, view, filerule, false)) { // pass 1
         psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // find blended neighbors of very saturated stars
-    psphotDeblendSatstars (config, view, "PSPHOT.INPUT");
+    psphotDeblendSatstars (config, view, filerule);
 
     // mark blended peaks PS_SOURCE_BLEND
-    if (!psphotBasicDeblend (config, view, "PSPHOT.INPUT")) {
+    if (!psphotBasicDeblend (config, view, filerule)) {
         psLogMsg ("psphot", 3, "failed on deblend analysis");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // classify sources based on moments, brightness (use supplied psf shape parameters)
-    if (!psphotRoughClass (config, view, "PSPHOT.INPUT")) {
+    if (!psphotRoughClass (config, view, filerule)) {
         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
-        return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+        return psphotReadoutCleanup (config, view, filerule);
     }
 
     // construct an initial model for each object
-    psphotGuessModels (config, view, "PSPHOT.INPUT");
+    psphotGuessModels (config, view, filerule);
 
     // merge the newly selected sources into the existing list
-    psphotMergeSources (config, view, "PSPHOT.INPUT");
+    psphotMergeSources (config, view, filerule);
 
     // linear PSF fit to source peaks
-    psphotFitSourcesLinear (config, view, "PSPHOT.INPUT", false);
+    psphotFitSourcesLinear (config, view, filerule, false);
 
 // XXX eventually, add the extended source fits here
 # if (0)
     // measure source size for the remaining sources
-    psphotSourceSize (config, view, "PSPHOT.INPUT");
+    psphotSourceSize (config, view, filerule);
 
-    psphotExtendedSourceAnalysis (config, view, "PSPHOT.INPUT");
+    psphotExtendedSourceAnalysis (config, view, filerule);
 
-    psphotExtendedSourceFits (config, view, "PSPHOT.INPUT");
+    psphotExtendedSourceFits (config, view, filerule);
 # endif
 
     // calculate source magnitudes
-    psphotMagnitudes(config, view, "PSPHOT.INPUT");
+    psphotMagnitudes(config, view, filerule);
 
     // XXX ensure this is measured if the analysis succeeds (even if quality is low)
-    if (!psphotEfficiency(config, view, "PSPHOT.INPUT")) {
+    if (!psphotEfficiency(config, view, filerule)) {
         psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
         psErrorClear();
@@ -88,7 +88,7 @@
 
     // drop the references to the image pixels held by each source
-    psphotSourceFreePixels (config, view, "PSPHOT.INPUT");
+    psphotSourceFreePixels (config, view, filerule);
 
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup (config, view, "PSPHOT.INPUT");
+    return psphotReadoutCleanup (config, view, filerule);
 }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotReplaceUnfit.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotReplaceUnfit.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotReplaceUnfit.c	(revision 29904)
@@ -31,11 +31,10 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
 	if (!psphotReplaceAllSourcesReadout (config, view, filerule, i, recipe)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for %s entry %d", filerule, i);
 	    return false;
 	}
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotRoughClass.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotRoughClass.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotRoughClass.c	(revision 29904)
@@ -16,6 +16,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSkyReplace.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSkyReplace.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSkyReplace.c	(revision 29904)
@@ -5,6 +5,5 @@
     bool status = true;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceFreePixels.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceFreePixels.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceFreePixels.c	(revision 29904)
@@ -3,8 +3,5 @@
 bool psphotSourceFreePixels (pmConfig *config, const pmFPAview *view, const char *filerule)
 {
-    bool status = true;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceMatch.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceMatch.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceMatch.c	(revision 29904)
@@ -6,15 +6,12 @@
 psArray *psphotMatchSources (pmConfig *config, const pmFPAview *view, const char *filerule) 
 {
-    bool status = true;
-
     psArray *objects = psArrayAllocEmpty(100);
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
         if (!psphotMatchSourcesReadout (objects, config, view, filerule, i)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to merge sources for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed to merge sources for %s entry %d", filerule, i);
 	    psFree (objects);
             return NULL;
@@ -162,6 +159,5 @@
     psAssert (status, "missing SKY_OUTER_RADIUS in recipe?");
 
-    int nImages = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int nImages = psphotFileruleCount(config, filerule);
 
     // generate look-up arrays for detections and readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceSize.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceSize.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceSize.c	(revision 29904)
@@ -49,6 +49,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
@@ -60,5 +59,5 @@
         if (i == chisqNum) continue; // skip chisq image
         if (!psphotSourceSizeReadout (config, view, filerule, i, recipe, getPSFsize)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed on source size analysis for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed on source size analysis for %s entry %d", filerule, i);
             return false;
         }
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceStats.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceStats.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSourceStats.c	(revision 29904)
@@ -14,6 +14,5 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // skip the chisq image (optionally?)
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotStackChisqImage.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotStackChisqImage.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotStackChisqImage.c	(revision 29904)
@@ -8,6 +8,4 @@
 bool psphotStackChisqImage (pmConfig *config, const pmFPAview *view, const char *ruleDet, const char *ruleCnv)
 {
-    bool status = false;
-
     psTimerStart ("psphot.chisq.image");
 
@@ -17,6 +15,5 @@
     pmReadout *chiReadout = NULL;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     // loop over the available readouts
@@ -28,7 +25,4 @@
         }
     }
-
-    num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
 
     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "PSPHOT.CHISQ.NUM", PS_META_REPLACE, "", num);
@@ -125,6 +119,5 @@
     psAssert (status, "programming error: must define PSPHOT.CHISQ.NUM");
 
-    int inputNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int inputNum = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     pmFPAfileRemoveSingle (config->files, filerule, chisqNum);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotStackImageLoop.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotStackImageLoop.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotStackImageLoop.c	(revision 29904)
@@ -105,11 +105,8 @@
 bool GetAstrometryFPA (pmConfig *config, pmFPAview *view) {
 
-    bool status = false;
-
     bool foundAstrometry = false;
     bool bilevelAstrometry = false;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     // loop over the available readouts
@@ -158,8 +155,5 @@
 bool GetAstrometryChip (pmConfig *config, pmFPAview *view, bool bilevelAstrometry) {
 
-    bool status = false;
-
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     // loop over the available readouts
@@ -220,10 +214,7 @@
 bool SetAstrometryFPA (pmConfig *config, pmFPAview *view, bool bilevelAstrometry) {
 
-    bool status = false;
-
     if (!bilevelAstrometry) return true;
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     // loop over the available readouts
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotStackMatchPSFs.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotStackMatchPSFs.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotStackMatchPSFs.c	(revision 29904)
@@ -8,6 +8,5 @@
     psAssert(recipe, "We've thrown an error on this before.");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
 
     // 'options' carries info needed to perform the stack matching
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotStackReadout.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotStackReadout.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotStackReadout.c	(revision 29904)
@@ -52,5 +52,5 @@
     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are determined and saved on
     // readout->analysis XXX this function currently only works with a single PSPHOT.INPUT
-    if (!psphotLoadPSF (config, view)) {
+    if (!psphotLoadPSF (config, view, STACK_RAW)) {
         psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
         return psphotReadoutCleanup (config, view, STACK_OUT);
Index: /branches/eam_branches/ipp-20101103/psphot/src/psphotSubtractBackground.c
===================================================================
--- /branches/eam_branches/ipp-20101103/psphot/src/psphotSubtractBackground.c	(revision 29903)
+++ /branches/eam_branches/ipp-20101103/psphot/src/psphotSubtractBackground.c	(revision 29904)
@@ -132,11 +132,10 @@
     psAssert (recipe, "missing recipe?");
 
-    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
-    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+    int num = psphotFileruleCount(config, filerule);
 
     // loop over the available readouts
     for (int i = 0; i < num; i++) {
 	if (!psphotSubtractBackgroundReadout (config, view, filerule, i, recipe)) {
-            psError (PSPHOT_ERR_CONFIG, false, "failed to subtract background for PSPHOT.INPUT entry %d", i);
+	    psError (PSPHOT_ERR_CONFIG, false, "failed to subtract background for %s entry %d", filerule, i);
 	    return false;
 	}
