Index: /branches/ipp-magic-v0/psphot/src/psphotDetect.h
===================================================================
--- /branches/ipp-magic-v0/psphot/src/psphotDetect.h	(revision 21393)
+++ /branches/ipp-magic-v0/psphot/src/psphotDetect.h	(revision 21393)
@@ -0,0 +1,23 @@
+# 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 ();
+
+#endif
Index: /branches/ipp-magic-v0/psphot/src/psphotDetectReadout.c
===================================================================
--- /branches/ipp-magic-v0/psphot/src/psphotDetectReadout.c	(revision 21393)
+++ /branches/ipp-magic-v0/psphot/src/psphotDetectReadout.c	(revision 21393)
@@ -0,0 +1,64 @@
+# 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);
+    if (!strcasecmp (breakPt, "NOTHING")) {
+        return psphotReadoutCleanup(config, readout, recipe, NULL, NULL, NULL);
+    }
+
+    // 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)
+    pmDetections *detections = psphotDetectionsFromSources (config, inSources);
+    if (!detections || !detections->peaks) {
+        psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
+        return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);
+    }
+
+    // construct sources and measure basic stats
+    psArray *sources = psphotSourceStats (config, readout, detections);
+    if (!sources) return false;
+    if (!strcasecmp (breakPt, "PEAKS")) {
+        return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+    }
+
+    // classify sources based on moments, brightness
+    if (!psphotRoughClass (readout, sources, recipe, havePSF)) {
+        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
+    }
+
+    // calculate source magnitudes
+    psphotPSFWeights(config, readout, view, sources);
+
+    // create the exported-metadata and free local data
+    return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+}
