Index: branches/simmosaic_branches/psphot/src/psphotRoughClass.c
===================================================================
--- branches/simmosaic_branches/psphot/src/psphotRoughClass.c	(revision 24860)
+++ branches/simmosaic_branches/psphot/src/psphotRoughClass.c	(revision 27839)
@@ -1,18 +1,66 @@
 # include "psphotInternal.h"
 
-# define CHECK_STATUS(S,MSG) {						\
-	if (!status) {							\
-	    psError(PSPHOT_ERR_CONFIG, false, "missing PSF Clump entry: %s\n", MSG); \
-	    return false;						\
-	} }
+# define CHECK_STATUS(S,MSG) {                                          \
+        if (!status) {                                                  \
+            psError(PSPHOT_ERR_CONFIG, false, "missing PSF Clump entry: %s\n", MSG); \
+            return false;                                               \
+        } }
 
-bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *recipe, const bool havePSF);
+// for now, let's store the detections on the readout->analysis for each readout
+bool psphotRoughClass (pmConfig *config, const pmFPAview *view)
+{
+    bool status = true;
 
-// 2006.02.02 : no leaks
-bool psphotRoughClass (pmReadout *readout, psArray *sources, psMetadata *recipe, const bool havePSF) {
+    // select the appropriate recipe information
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+    psAssert (recipe, "missing recipe?");
+
+    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
+    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
+
+    // skip the chisq image (optionally?)
+    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
+    if (!status) chisqNum = -1;
+
+    // loop over the available readouts
+    for (int i = 0; i < num; i++) {
+	if (i == chisqNum) continue; // skip chisq image
+	if (!psphotRoughClassReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
+            psError (PSPHOT_ERR_CONFIG, false, "failed on rough classification for PSPHOT.INPUT entry %d", i);
+	    return false;
+	}
+    }
+    return true;
+}
+
+bool psphotRoughClassReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
 
     bool status;
 
     psTimerStart ("psphot.rough");
+
+    // find the currently selected readout
+    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
+    psAssert (file, "missing file?");
+
+    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
+    psAssert (readout, "missing readout?");
+
+    // if we have a PSF, use the existing PSF clump region below
+    bool havePSF = false;
+    if (psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF")) {
+	havePSF = true;
+    }
+
+    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
+    psAssert (detections, "missing detections?");
+
+    psArray *sources = detections->newSources;
+    psAssert (sources, "missing sources?");
+
+    if (!sources->n) {
+	psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping rough classification");
+	return true;
+    }
 
     // we make this measurement on a NxM grid of regions across the readout
@@ -24,17 +72,18 @@
     int nRegion = 0;
     for (int ix = 0; ix < NX; ix ++) {
-	for (int iy = 0; iy < NY; iy ++) {
+        for (int iy = 0; iy < NY; iy ++) {
 
-	    psRegion region = psRegionSet (ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY);
-	    if (!psphotRoughClassRegion (nRegion, &region, sources, recipe, havePSF)) {
-		psLogMsg ("psphot", 4, "Failed to determine rough classification for region %f,%f - %f,%f\n", 
-			 region.x0, region.y0, region.x1, region.y1);
-		continue;
-	    }
-	    
-	    nRegion ++;
-	}
+            psRegion *region = psRegionAlloc (ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY);
+            if (!psphotRoughClassRegion (nRegion, region, sources, readout->analysis, recipe, havePSF)) {
+                psLogMsg ("psphot", 4, "Failed to determine rough classification for region %f,%f - %f,%f\n",
+                         region->x0, region->y0, region->x1, region->y1);
+                psFree (region);
+                continue;
+            }
+            psFree (region);
+            nRegion ++;
+        }
     }
-    psMetadataAddS32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegion);
+    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegion);
 
     // optional printout of source moments only
@@ -43,12 +92,12 @@
     psLogMsg ("psphot.roughclass", PS_LOG_INFO, "rough classification: %f sec\n", psTimerMark ("psphot.rough"));
 
-    psphotVisualPlotMoments (recipe, sources);
+    psphotVisualPlotMoments (recipe, readout->analysis, sources);
     psphotVisualShowRoughClass (sources);
-    psphotVisualShowFlags (sources);
+    // XXX better visualization: psphotVisualShowFlags (sources);
 
     return true;
 }
 
-bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *recipe, const bool havePSF) {
+bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *analysis, psMetadata *recipe, const bool havePSF) {
 
     bool status;
@@ -60,46 +109,75 @@
     assert (maskSat);
 
+    // the regions are saved on the readout->analysis metadata folder (passed to us as analysis)
     snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", nRegion);
-    psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName);
+    psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     if (!regionMD) {
-	regionMD = psMetadataAlloc();
-	psMetadataAddMetadata (recipe, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
-	psFree (regionMD);
+        // allocate the region metadata folder and add this region to it.
+        regionMD = psMetadataAlloc();
+        psMetadataAddMetadata (analysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
+        psFree (regionMD);
     }
+    psMetadataAddPtr (regionMD, PS_LIST_TAIL, "REGION", PS_DATA_REGION | PS_META_REPLACE, "psf clump region", region);
 
     if (!havePSF) {
-	// determine the PSF parameters from the source moment values
-	psfClump = pmSourcePSFClump (region, sources, recipe);
-	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
-	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
-	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
-	psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+        // determine the PSF parameters from the source moment values
+        // XXX why not save the psfClump as a PTR?
+
+	float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
+	float MOMENTS_AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX"); psAssert (status, "missing MOMENTS_AR_MAX");
+
+	float PSF_CLUMP_GRID_SCALE = psMetadataLookupF32(&status, analysis, "PSF_CLUMP_GRID_SCALE");
+	if (!status) {
+	    PSF_CLUMP_GRID_SCALE = psMetadataLookupF32(&status, recipe, "PSF_CLUMP_GRID_SCALE");
+	    psAssert (status, "missing PSF_CLUMP_GRID_SCALE");
+	}
+	float MOMENTS_SX_MAX = psMetadataLookupF32(&status, analysis, "MOMENTS_SX_MAX");
+	if (!status) {
+	    MOMENTS_SX_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SX_MAX");
+	    psAssert (status, "missing MOMENTS_SX_MAX");
+	}
+	float MOMENTS_SY_MAX = psMetadataLookupF32(&status, analysis, "MOMENTS_SY_MAX");
+	if (!status) {
+	    MOMENTS_SY_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SY_MAX");
+	    psAssert (status, "missing MOMENTS_SY_MAX");
+	}
+
+        psfClump = pmSourcePSFClump (NULL, region, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX);
+
+        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
+        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
+        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
+        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
     } else {
-	// pull FWHM_X,Y from the recipe, use to define psfClump.X,Y
-	psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 
-	if (!status) {
-	    psLogMsg ("psphot", 4, "No PSF clump defined for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
-	    return false;
-	}	    
-	psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   psAssert (status, "missing PSF.CLUMP.Y");
-	psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  psAssert (status, "missing PSF.CLUMP.DX");
-	psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  psAssert (status, "missing PSF.CLUMP.DY");
+        // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y
+        psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
+        if (!status) {
+            psLogMsg ("psphot", 4, "No PSF clump defined for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
+            return false;
+        }
+        psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   psAssert (status, "missing PSF.CLUMP.Y");
+        psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  psAssert (status, "missing PSF.CLUMP.DX");
+        psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  psAssert (status, "missing PSF.CLUMP.DY");
     }
 
     if (psfClump.X < 0) {
-	psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourcePSFClump");
-	return false;
+        psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourcePSFClump");
+        return false;
     }
     if (!psfClump.X || !psfClump.Y || isnan(psfClump.X) || isnan(psfClump.Y)) {
-	psLogMsg ("psphot", 4, "Failed to find a valid PSF clump for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
-	return false;
+        psLogMsg ("psphot", 4, "Failed to find a valid PSF clump for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
+        return false;
     }
     psLogMsg ("psphot", 3, "psf clump  X,  Y: %f, %f\n", psfClump.X, psfClump.Y);
     psLogMsg ("psphot", 3, "psf clump DX, DY: %f, %f\n", psfClump.dX, psfClump.dY);
 
+    // get basic parameters, or set defaults
+    float PSF_SN_LIM = psMetadataLookupF32 (&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
+    float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA"); psAssert (status, "missing PSF_CLUMP_NSIGMA");
+
     // group into STAR, COSMIC, EXTENDED, SATURATED, etc.
-    if (!pmSourceRoughClass (region, sources, recipe, psfClump, maskSat)) {
-	psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass");
-	return false;
+    if (!pmSourceRoughClass (region, sources, PSF_SN_LIM, PSF_CLUMP_NSIGMA, psfClump, maskSat)) {
+        psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass");
+        return false;
     }
 
