Index: trunk/psphot/src/psphotReadout.c
===================================================================
--- trunk/psphot/src/psphotReadout.c	(revision 16250)
+++ trunk/psphot/src/psphotReadout.c	(revision 16820)
@@ -9,6 +9,4 @@
     psTimerStart ("psphotReadout");
 
-    bool dump = (psTraceGetLevel("psphot") >= 6);
-
     // select the current recipe
     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
@@ -18,40 +16,4 @@
     }
 
-    // Interpret the mask values
-    const char *maskValStr = psMetadataLookupStr(NULL, recipe, "MASKVAL"); // String with mask names
-    if (!maskValStr) {
-        psError(PSPHOT_ERR_CONFIG, false, "Missing recipe item: MASKVAL(STR)");
-        return false;
-    }
-    psMaskType maskVal = pmConfigMask(maskValStr, config); // Mask values to mask against
-    psMaskType maskMark = pmConfigMask("MARK", config); // Mask value for marking
-    psMaskType maskSat = pmConfigMask("SAT", config); // Mask value for saturated pixels
-    psMaskType maskBad = pmConfigMask("BAD", config); // Mask value for bad pixels
-
-    // find the currently selected readout
-    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
-    PS_ASSERT_PTR_NON_NULL (readout, false);
-
-    // optional break-point for processing
-    char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");
-    PS_ASSERT_PTR_NON_NULL (breakPt, false);
-
-    // Use the new pmFootprints approach?
-    const bool useFootprints = psMetadataLookupBool(NULL, recipe, "USE_FOOTPRINTS");
-
-    // generate mask & weight images if they don't already exit
-    if (!readout->mask) {
-        if (!pmReadoutGenerateMask(readout, maskSat, maskBad)) {
-            psError (PSPHOT_ERR_CONFIG, false, "trouble creating mask");
-            return false;
-        }
-    }
-    if (!readout->weight) {
-        if (!pmReadoutGenerateWeight(readout, true)) {
-            psError (PSPHOT_ERR_CONFIG, false, "trouble creating weight");
-            return false;
-        }
-    }
-
     // set the photcode for this image
     if (!psphotAddPhotcode (recipe, config, view)) {
@@ -60,31 +22,31 @@
     }
 
-    // I have a valid mask, now mask in the analysis region of interest
-    psphotMaskReadout (readout, recipe, maskBad);
-
-    if (psTraceGetLevel("psphot") >= 5) {
-        psphotSaveImage (NULL, readout->image,  "image.fits");
-        psphotSaveImage (NULL, readout->mask,   "mask.fits");
-        psphotSaveImage (NULL, readout->weight, "weight.fits");
-    }
-
+    // find the currently selected readout
+    pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
+    PS_ASSERT_PTR_NON_NULL (readout, false);
+
+    // optional break-point for processing
+    char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");
+    PS_ASSERT_PTR_NON_NULL (breakPt, 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);
+        return psphotReadoutCleanup(config, readout, recipe, NULL, NULL, NULL);
     }
 
     // generate a background model (median, smoothed image)
-    if (!psphotModelBackground (config, view, "PSPHOT.INPUT", maskVal)) {
-        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL);
-    }
-    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT", maskVal)) {
-        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL);
-    }
-
+    if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
+    if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
     if (!strcasecmp (breakPt, "BACKMDL")) {
-        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL);
-    }
-
-    // run a single-model test if desired
-    psphotModelTest (config, view, recipe, maskVal, maskMark);
+        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
+    }
+
+    // run a single-model test if desired (exits from here if test is run)
+    psphotModelTest (config, view, recipe);
 
     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
@@ -94,39 +56,20 @@
     bool havePSF = (psf != NULL);
 
-    // find the peaks in the image.
-
-    // XXX clean this up into a single function.  if psf is defined, we should treat this as
-    // pass "2", not "1".  re-define this boolean to be "have PSF"
-    psArray *peaks;
-    psArray *footprints = NULL;
-    if (useFootprints) {
-       footprints = psphotFindPeaks (readout, recipe, useFootprints, 1, maskVal);
-       int growRadius = psMetadataLookupS32(NULL, recipe, "FOOTPRINT_GROW_RADIUS");
-       if (growRadius > 0) {
-           psArray *tmp = pmGrowFootprintArray(footprints, growRadius);
-           psFree(footprints);
-           footprints = tmp;
-       }
-       psphotCullPeaks(readout->image, readout->weight, recipe, footprints);
-
-       peaks = pmFootprintArrayToPeaks(footprints);
-    } else {
-       peaks = psphotFindPeaks (readout, recipe, useFootprints, 1, maskVal);
-    }
-
-    if (!peaks) {
-        psLogMsg ("psphot", 3, "unable to find peaks in this image");
-        return psphotReadoutCleanup (config, readout, recipe, NULL, NULL);
+    // find the detections (by peak and/or footprint) in the image.
+    pmDetections *detections = psphotFindDetections (NULL, readout, recipe);
+    if (!detections) {
+        psLogMsg ("psphot", 3, "unable to find detections in this image");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL);
     }
 
     // construct sources and measure basic stats
-    psArray *sources = psphotSourceStats (readout, recipe, peaks, maskVal, maskMark);
+    psArray *sources = psphotSourceStats (readout, recipe, detections);
     if (!sources) return false;
-    psFree (peaks);
-
     if (!strcasecmp (breakPt, "PEAKS")) {
-        return psphotReadoutCleanup(config, readout, recipe, NULL, sources);
-    }
-
+        return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
+    }
+
+    // find blended neighbors of very saturated stars
+    // XXX merge this with Basic Deblend?
     psphotDeblendSatstars (sources, recipe);
 
@@ -134,14 +77,14 @@
     if (!psphotBasicDeblend (sources, recipe)) {
         psLogMsg ("psphot", 3, "failed on deblend analysis");
-        return psphotReadoutCleanup (config, readout, recipe, NULL, sources);
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     }
 
     // classify sources based on moments, brightness
-    if (!psphotRoughClass (sources, recipe, havePSF, maskSat)) {
+    if (!psphotRoughClass (sources, recipe, havePSF)) {
         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
-        return psphotReadoutCleanup (config, readout, recipe, NULL, sources);
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     }
     if (!strcasecmp (breakPt, "MOMENTS")) {
-        return psphotReadoutCleanup(config, readout, recipe, NULL, sources);
+        return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
     }
 
@@ -151,16 +94,13 @@
         // XXX if we do not have enough stars to generate the PSF, build one
         // from the SEEING guess and model class
-        psf = psphotChoosePSF (readout, sources, recipe, maskVal, maskMark);
+        psf = psphotChoosePSF (readout, sources, recipe);
         if (psf == NULL) {
             psLogMsg ("psphot", 3, "failure to construct a psf model");
-            return psphotReadoutCleanup (config, readout, recipe, psf, sources);
+            return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
         }
         havePSF = true;
     }
-
-    // XXX Test dump of PSF parameters across image field.
-
     if (!strcasecmp (breakPt, "PSFMODEL")) {
-        return psphotReadoutCleanup (config, readout, recipe, psf, sources);
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     }
 
@@ -169,19 +109,15 @@
 
     // construct an initial model for each object
-    psphotGuessModels (readout, sources, recipe, psf, maskVal);
+    psphotGuessModels (readout, sources, recipe, psf);
 
     // XXX test output of models
     // psphotTestSourceOutput (readout, sources, recipe, psf);
 
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v0.fits");
-
-    // linear PSF fit to peaks
-    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v1.fits");
+    // linear PSF fit to source peaks
+    psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
 
     // XXX test the CR/EXT measurement
     // XXX we need to call this here and after the second pass: option for starting number?
-    psphotSourceSize (readout, sources, recipe);
-
+    psphotSourceSize (readout, sources, recipe, 0);
     if (!strcasecmp (breakPt, "ENSEMBLE")) {
         goto finish;
@@ -189,14 +125,11 @@
 
     // non-linear PSF and EXT fit to brighter sources
-    psphotBlendFit (readout, sources, recipe, psf, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v2.fits");
-
-    // replace all sources
-    psphotReplaceAll (sources, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v3.fits");
-
-    // linear PSF fit to remaining peaks
-    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v4.fits");
+    psphotBlendFit (readout, sources, recipe, psf);
+
+    // replace all sources (make this part of psphotFitSourcesLinear?)
+    psphotReplaceAll (sources, recipe);
+
+    // linear fit to include all sources
+    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
     if (!strcasecmp (breakPt, "PASS1")) {
         goto finish;
@@ -210,62 +143,37 @@
 
     // add noise for subtracted objects
-    psphotAddNoise (readout, sources, recipe, true, maskVal);
-
-    // find the peaks in the image
-    psArray *newPeaks;
-    if (useFootprints) {
-       psArray *newFootprints = psphotFindPeaks (readout, recipe, useFootprints, 2, maskVal);
-
-       int growRadius = psMetadataLookupS32(NULL, recipe, "FOOTPRINT_GROW_RADIUS_2");
-       if (growRadius > 0) {
-           psArray *tmp = pmGrowFootprintArray(newFootprints, growRadius);
-           psFree(newFootprints);
-           newFootprints = tmp;
-       }
-
-       // merge in old peaks
-       const int includePeaks = 0x0 | 0x2; // i.e. just from newFootprints
-       psArray *mergedFootprints = pmMergeFootprintArrays(footprints, newFootprints, includePeaks);
-       psFree(footprints);
-       psFree(newFootprints);
-
-       psphotCullPeaks(readout->image, readout->weight, recipe, mergedFootprints);
-
-       newPeaks = pmFootprintArrayToPeaks(mergedFootprints);
-
-       psFree(mergedFootprints);
-    } else {
-       newPeaks = psphotFindPeaks(readout, recipe, useFootprints, 2, maskVal);
-    }
+    psphotAddNoise (readout, sources, recipe);
+
+    detections = psphotFindDetections (detections, readout, recipe);
 
     // remove noise for subtracted objects
-    psphotAddNoise (readout, sources, recipe, false, maskVal);
-
-    // define new sources based on the new peaks
-    psArray *newSources = psphotSourceStats (readout, recipe, newPeaks, maskVal, maskMark);
-    psFree (newPeaks);
+    psphotSubNoise (readout, sources, recipe);
+
+    // define new sources based on only the new peaks
+    psArray *newSources = psphotSourceStats (readout, recipe, detections);
 
     // set source type
-    if (!psphotRoughClass (newSources, recipe, havePSF, maskSat)) {
+    if (!psphotRoughClass (newSources, recipe, havePSF)) {
         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
-        return psphotReadoutCleanup (config, readout, recipe, psf, sources);
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     }
 
     // create full input models
-    psphotGuessModels (readout, newSources, recipe, psf, maskVal);
-
-    // replace all sources
-    psphotReplaceAll (sources, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v5.fits");
-
-    // merge the newly selected peaks into the existing list
+    psphotGuessModels (readout, newSources, recipe, psf);
+
+    // replace all sources so fit below applies to all at once
+    psphotReplaceAll (sources, recipe);
+
+    // merge the newly selected sources into the existing list
     psphotMergeSources (sources, newSources);
     psFree (newSources);
 
-    // linear PSF fit to remaining peaks
-    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE, maskVal);
-    if (dump) psphotSaveImage (NULL, readout->image,  "image.v6.fits");
-
-    psphotExtendedSources (readout, sources, recipe, maskVal);
+    // linear fit to all sources
+    psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
+
+    // measure source size for the remaining sources
+    psphotSourceSize (readout, sources, recipe, 0);
+
+    psphotExtendedSources (readout, sources, recipe);
 
 finish:
@@ -273,17 +181,16 @@
     // plot positive sources
     if (!havePSF) {
-        // psphotSourcePlots (readout, sources, recipe, maskVal);
+        // psphotSourcePlots (readout, sources, recipe);
     }
 
     // measure aperture photometry corrections
-    if (!havePSF && !psphotApResid (readout, sources, recipe, psf, maskVal, maskMark)) {
-        psTrace ("psphot", 4, "failure on psphotApResid");
-        psError(PSPHOT_ERR_PHOTOM, false, "Measure aperture photometry corrections");
-        return false;
+    if (!havePSF && !psphotApResid (readout, sources, recipe, psf)) {
+        psLogMsg ("psphot", 3, "failed on psphotApResid");
+        return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     }
 
     // calculate source magnitudes
     pmReadout *background = psphotSelectBackground (config, view, false);
-    psphotMagnitudes(sources, recipe, psf, background, maskVal, maskMark);
+    psphotMagnitudes(sources, recipe, psf, background);
 
     // replace failed sources?
@@ -297,4 +204,4 @@
 
     // create the exported-metadata and free local data
-    return psphotReadoutCleanup(config, readout, recipe, psf, sources);
+    return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
 }
