Index: /trunk/psphot/src/Makefile.am
===================================================================
--- /trunk/psphot/src/Makefile.am	(revision 12626)
+++ /trunk/psphot/src/Makefile.am	(revision 12627)
@@ -49,4 +49,7 @@
 	psphotMergeSources.c	 \
 	psphotReadoutCleanup.c	 \
+	psphotAddNoise.c	 \
+	psphotSourcePlots.c	 \
+	psphotRadialPlot.c	 \
 	psphotCleanup.c	   	
 
Index: /trunk/psphot/src/psphot.h
===================================================================
--- /trunk/psphot/src/psphot.h	(revision 12626)
+++ /trunk/psphot/src/psphot.h	(revision 12627)
@@ -103,2 +103,5 @@
 psExit psphotGetExitStatus ();
 bool psphotSetHeaderNstars (psMetadata *recipe, psArray *sources);
+bool psphotAddNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add);
+bool psphotRadialPlot (const char *filename, pmSource *source);
+bool psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe);
Index: /trunk/psphot/src/psphotRadialPlot.c
===================================================================
--- /trunk/psphot/src/psphotRadialPlot.c	(revision 12627)
+++ /trunk/psphot/src/psphotRadialPlot.c	(revision 12627)
@@ -0,0 +1,81 @@
+# include "psphot.h"
+
+// this variable is defined in psmodules.h if ohana-config is found
+# if (HAVE_KAPA)
+
+# include <kapa.h>
+
+bool psphotRadialPlot (const char *filename, pmSource *source) {
+
+    // XXX get the 'showWindow' option from the recipes somewhere
+    int kapa = pmKapaOpen (false);
+    if (kapa == -1) {
+	psError(PSPHOT_ERR_UNKNOWN, true, "failure to open kapa");
+	return false;
+    }
+
+    KapaResize (kapa, 500, 500);
+    KapaInitGraph (&graphdata);
+
+    // examine sources to set data range
+    graphdata.xmin = -0.05;
+    graphdata.ymin = -0.05;
+    graphdata.xmax = +2.05;
+    graphdata.ymax = +2.05;
+    KapaSetLimits (kapa, &graphdata);
+  
+    KapaSetFont (kapa, "helvetica", 14);
+    KapaBox (kapa, &graphdata);
+    KapaSendLabel (kapa, "&ss&h_x| (pixels)", KAPA_LABEL_XM);
+    KapaSendLabel (kapa, "&ss&h_y| (pixels)", KAPA_LABEL_YM);
+	       
+    int nPts = source->pixels->numRows * source->pixels->numCols;
+    psVector *radius = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *lflux  = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *rmask  = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+    psVector *lfmask = psVectorAllocEmpty (nPts, PS_TYPE_F32);
+
+    int n = 0;
+    int nm = 0;
+    for (int iy = 0; iy < source->pixels->numRows; iy++) {
+	for (int ix = 0; ix < source->pixels->numCols; ix++) {
+	    
+	    if (source->mask->data.U8[iy][ix]) {
+		rmask->data.F32[nm] = RADIUS;
+		lfmask->data.F32[nm] = log10(source->pixels->data.F32[iy][ix]);
+		nm++;
+	    } else {
+		radius->data.F32[n] = RADIUS;
+		lflux->data.F32[n] = log10(source->pixels->data.F32[iy][ix]);
+		n++;
+	    }
+	}
+    }
+  
+    // set the plot range here based on lflux, radius
+
+    graphdata.color = KapaColorByName ("black");
+    graphdata.ptype = 0;
+    graphdata.size = 0.3;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, nm, &graphdata);
+    KapaPlotVector (kapa, nm, rmask->data.F32);
+    KapaPlotVector (kapa, nm, lfmask->data.F32);
+  
+    graphdata.color = KapaColorByName ("red");
+    graphdata.ptype = 2;
+    graphdata.size = 0.5;
+    graphdata.style = 2;
+    KapaPrepPlot (kapa, n, &graphdata);
+    KapaPlotVector (kapa, n, radius->data.F32);
+    KapaPlotVector (kapa, n, lflux->data.F32);
+
+    psLogMsg ("psphot", 3, "saving plot to %s", file->filename);
+    KapaPS (kapa, false, KAPA_PS_NEWPAGE, filename, "none");
+
+    psFree (radius);
+    psFree (lflux);
+    psFree (rmask);
+    psFree (lfmask);
+
+}
Index: /trunk/psphot/src/psphotSourcePlots.c
===================================================================
--- /trunk/psphot/src/psphotSourcePlots.c	(revision 12626)
+++ /trunk/psphot/src/psphotSourcePlots.c	(revision 12627)
@@ -10,11 +10,12 @@
     PS_ASSERT (status);
 
-    int NX = 10*(2*OUTER+1);
-    int NY = 0;
-
     // examine PSF sources in S/N order (brightest first)
     sources = psArraySort (sources, psphotSortBySN);
 
-    bool newRow = true;
+    // counters to track the size of the image and area used in a row
+    int dX = 0;				// starting corner of next box
+    int dY = 0;				// height of row so far
+    int NX = 10*(2*OUTER+1);		// full width of output image
+    int NY = 0;				// total height of output image
 
     // first, examine the PSF and SAT stars:
@@ -30,25 +31,33 @@
 	if (!keep) continue;
 
-	if (newRow) {
-	    dX = 0;
-	    dY = 0;
-	    newRow = false;
+	// how does this subimage get placed into the output image?
+	if (dX + source->pixels->numCols >= NX) {
+	    // too wide for the rest of this row
+	    if (dX == 0) {
+		// alone on this row
+		NY += source->pixels->numRows;
+		dX = 0;
+		dY = 0;
+	    } else {
+		// start the next row
+		NY += dY;
+		dX = source->pixels->numCols;
+		dY = source->pixels->numRows;
+	    }
+	} else {
+	    // extend this row
+	    dX += source->pixels->numCols;
+	    dY = PS_MAX (dY, source->pixels->numRows);
 	}
-
-	if (dX + source->pixels->numCols > NX) {
-	    // go to the next row
-	    // but, if we have only this one entry, we will truncate it.
-	}
-	dX += source->pixels->numCols;
-	dY = PS_MAX (dY, source->pixels->numRows);
-
-	// for a new row:
-	NY += dY;
-
-	RadialPlot (source);
+	psphotRadialPlot ("radial.plots.ps", source);
     }
 
     // allocate output image
-    psImage *output = psImageAlloc (NX, NY, PS_TYPE_F32);
+    psImage *outpos = psImageAlloc (NX, NY, PS_TYPE_F32);
+    psImage *outsub = psImageAlloc (NX, NY, PS_TYPE_F32);
+
+    int Xo = 0;				// starting corner of next box
+    int Yo = 0;				// starting corner of next box
+    int dY = 0;				// height of row so far
 
     // first, examine the PSF and SAT stars:
@@ -64,11 +73,31 @@
 	if (!keep) continue;
 
-	// add to image
+	// how does this subimage get placed into the output image?
+	if (Xo + source->pixels->numCols >= NX) {
+	    // too wide for the rest of this row
+	    if (Xo == 0) {
+		// alone on this row
+		PlaceImage (source, Xo, Yo);
+		Yo += source->pixels->numRows;
+		Xo = 0;
+		dY = 0;
+	    } else {
+		// start the next row
+		Yo += dY;
+		Xo = 0;
+		PlaceImage (source, Xo, Yo);
+		Xo = source->pixels->numCols;
+		dY = source->pixels->numRows;
+	    }
+	} else {
+	    // extend this row
+	    PlaceImage (source, Xo, Yo);
+	    Xo += source->pixels->numCols;
+	    dY = PS_MAX (dY, source->pixels->numRows);
+	}
     }
 
     psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d failed: %f sec\n", sources->n, Nmoments, Nfail, psTimerMark ("psphot"));
-
     return (sources);
 }
 
-// XXX EAM : filter out bad peaks (eg, no valid pixels available for sky)
Index: /trunk/psphot/src/psphotSummaryPlots.c
===================================================================
--- /trunk/psphot/src/psphotSummaryPlots.c	(revision 12626)
+++ /trunk/psphot/src/psphotSummaryPlots.c	(revision 12627)
@@ -33,5 +33,4 @@
 	return false;
     }
-
 
     KapaResize (kapa, 500, 500);
