Index: /branches/eam_02_branch/psModules/src/objects/pmModel.c
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmModel.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmModel.c	(revision 12956)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.9.6.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-04-21 21:30:21 $
+ *  @version $Revision: 1.9.6.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-23 03:26:23 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -160,11 +160,11 @@
     float skySave = params->data.F32[PM_PAR_SKY];
 
-    if (mode & PM_MODEL_ADD_NORM) {
+    if (mode & PM_MODEL_OP_NORM) {
 	params->data.F32[PM_PAR_I0] = 1.0;
     }
-    if (!(mode & PM_MODEL_ADD_SKY)) {
+    if (!(mode & PM_MODEL_OP_SKY)) {
 	params->data.F32[PM_PAR_SKY] = 0.0;
     }
-    if (mode & PM_MODEL_ADD_CENTER) {
+    if (mode & PM_MODEL_OP_CENTER) {
 	params->data.F32[PM_PAR_XPOS] = image->col0 + 0.5*image->numCols;
 	params->data.F32[PM_PAR_YPOS] = image->row0 + 0.5*image->numRows;
@@ -184,5 +184,5 @@
     psImageInterpolateOptions *Rx = NULL;
     psImageInterpolateOptions *Ry = NULL;
-    if (model->residuals && (mode & (PM_MODEL_ADD_RES0 | PM_MODEL_ADD_RES1))) {
+    if (model->residuals && (mode & (PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1))) {
 	Ro = psImageInterpolateOptionsAlloc(
 	    PS_INTERPOLATE_BILINEAR,
@@ -217,5 +217,5 @@
 
             // add in the desired components for this coordinate
-            if (mode & PM_MODEL_ADD_FUNC) {
+            if (mode & PM_MODEL_OP_FUNC) {
                 pixelValue += modelFunc (NULL, params, x);
             } 
@@ -227,5 +227,5 @@
 		float oy = yBin*(imageRow + 0.5 - yCenter) + yResidCenter;
 
-		if (mode & PM_MODEL_ADD_RES0) {
+		if (mode & PM_MODEL_OP_RES0) {
 		    psU8 mflux = 0;
 		    double Fo = 0.0;
@@ -235,5 +235,5 @@
 		    }
 		}
-		if (mode & PM_MODEL_ADD_RES1) {
+		if (mode & PM_MODEL_OP_RES1) {
 		    psU8 mflux = 0;
 		    double Fx = 0.0;
Index: /branches/eam_02_branch/psModules/src/objects/pmModel.h
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmModel.h	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmModel.h	(revision 12956)
@@ -5,6 +5,6 @@
  * @author EAM, IfA
  *
- * @version $Revision: 1.6.6.2 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-04-21 21:30:21 $
+ * @version $Revision: 1.6.6.3 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-04-23 03:26:23 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -28,13 +28,13 @@
 
 typedef enum {
-    PM_MODEL_ADD_NONE 	= 0x00,
-    PM_MODEL_ADD_FUNC 	= 0x01,
-    PM_MODEL_ADD_RES0 	= 0x02,
-    PM_MODEL_ADD_RES1 	= 0x04,
-    PM_MODEL_ADD_FULL   = 0x07,
-    PM_MODEL_ADD_SKY  	= 0x08,
-    PM_MODEL_ADD_CENTER = 0x10,
-    PM_MODEL_ADD_NORM  	= 0x20,
-} pmModelAddMode;
+    PM_MODEL_OP_NONE 	= 0x00,
+    PM_MODEL_OP_FUNC 	= 0x01,
+    PM_MODEL_OP_RES0 	= 0x02,
+    PM_MODEL_OP_RES1 	= 0x04,
+    PM_MODEL_OP_FULL   = 0x07,
+    PM_MODEL_OP_SKY  	= 0x08,
+    PM_MODEL_OP_CENTER = 0x10,
+    PM_MODEL_OP_NORM  	= 0x20,
+} pmModelOpMode;
 
 /** pmModel data structure
Index: /branches/eam_02_branch/psModules/src/objects/pmPSF.c
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmPSF.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmPSF.c	(revision 12956)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.19.2.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-04-21 21:30:21 $
+ *  @version $Revision: 1.19.2.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-23 03:26:23 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -425,5 +425,5 @@
     // no need to mask the source here
     // XXX should we measure this for the analytical model only or the full model?
-    pmModelAdd (image, NULL, model, PM_MODEL_ADD_FULL);
+    pmModelAdd (image, NULL, model, PM_MODEL_OP_FULL);
 
     // loop over a range of source fluxes
Index: /branches/eam_02_branch/psModules/src/objects/pmSource.c
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmSource.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmSource.c	(revision 12956)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.25.4.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-04-22 22:23:20 $
+ *  @version $Revision: 1.25.4.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-23 03:26:23 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -39,5 +39,7 @@
     psFree(tmp->pixels);
     psFree(tmp->weight);
-    psFree(tmp->mask);
+    psFree(tmp->maskObj);
+    psFree(tmp->maskView);
+    psFree(tmp->modelFlux);
     psFree(tmp->moments);
     psFree(tmp->modelPSF);
@@ -47,4 +49,5 @@
 }
 
+// free only the pixel data associated with this source
 void pmSourceFreePixels(pmSource *source)
 {
@@ -55,9 +58,13 @@
     psFree (source->pixels);
     psFree (source->weight);
-    psFree (source->mask);
+    psFree (source->maskObj);
+    psFree (source->maskView);
+    psFree (source->modelFlux);
 
     source->pixels = NULL;
     source->weight = NULL;
-    source->mask = NULL;
+    source->maskObj = NULL;
+    source->maskView = NULL;
+    source->modelFlux = NULL;
     return;
 }
@@ -76,5 +83,7 @@
     source->pixels = NULL;
     source->weight = NULL;
-    source->mask = NULL;
+    source->maskObj = NULL;
+    source->maskView = NULL;
+    source->modelFlux = NULL;
     source->moments = NULL;
     source->blends = NULL;
@@ -117,9 +126,11 @@
     source->pixels = psMemIncrRefCounter (in->pixels);
     source->weight = psMemIncrRefCounter (in->weight);
-    source->mask = psMemIncrRefCounter (in->mask);
+    source->maskObj = psMemIncrRefCounter (in->maskObj);
+    source->maskView = psMemIncrRefCounter (in->maskView);
     source->moments = psMemIncrRefCounter (in->moments);
     source->blends = NULL;
     source->modelPSF = NULL;
     source->modelEXT = NULL;
+    source->modelFlux = NULL;
     source->type = in->type;
     source->mode = in->mode;
@@ -151,8 +162,12 @@
     srcRegion = psRegionForImage (readout->image, srcRegion);
 
-    mySource->pixels = psMemIncrRefCounter(psImageSubset(readout->image, srcRegion));
-    mySource->weight = psMemIncrRefCounter(psImageSubset(readout->weight, srcRegion));
-    mySource->mask   = psMemIncrRefCounter(psImageSubset(readout->mask,  srcRegion));
-    mySource->region = srcRegion;
+    // these images are subset images of the equivalent parents
+    mySource->pixels   = psMemIncrRefCounter(psImageSubset(readout->image, srcRegion));
+    mySource->weight   = psMemIncrRefCounter(psImageSubset(readout->weight, srcRegion));
+    mySource->maskView = psMemIncrRefCounter(psImageSubset(readout->mask,  srcRegion));
+    mySource->region   = srcRegion;
+
+    // the object mask is a copy, and used to define the source pixels
+    mySource->maskObj = psImageCopy (NULL, mySource->maskView, PS_TYPE_MASK);
 
     return true;
@@ -183,5 +198,6 @@
     extend |= (mySource->pixels == NULL);
     extend |= (mySource->weight == NULL);
-    extend |= (mySource->mask == NULL);
+    extend |= (mySource->maskObj == NULL);
+    extend |= (mySource->maskView == NULL);
 
     // extend = true;
@@ -190,12 +206,18 @@
         psFree (mySource->pixels);
         psFree (mySource->weight);
-        psFree (mySource->mask);
-
-        mySource->pixels = psMemIncrRefCounter(psImageSubset(readout->image,  newRegion));
-        mySource->weight = psMemIncrRefCounter(psImageSubset(readout->weight, newRegion));
-        mySource->mask   = psMemIncrRefCounter(psImageSubset(readout->mask,   newRegion));
-        mySource->region = newRegion;
-    }
-
+        psFree (mySource->maskView);
+
+        mySource->pixels   = psMemIncrRefCounter(psImageSubset(readout->image,  newRegion));
+        mySource->weight   = psMemIncrRefCounter(psImageSubset(readout->weight, newRegion));
+        mySource->maskView = psMemIncrRefCounter(psImageSubset(readout->mask,   newRegion));
+        mySource->region   = newRegion;
+
+	// XXX how do we extend the mask?  do we need to keep the old masked pixels?
+	// the object mask is a copy, and used to define the source pixels
+        psFree (mySource->maskObj);
+	mySource->maskObj = psImageCopy (NULL, mySource->maskView, PS_TYPE_MASK);
+	
+	// XXX what about the modelFlux image?
+    }
     return extend;
 }
@@ -207,4 +229,6 @@
 
 // XXX EAM include a S/N cutoff in selecting the sources?
+// XXX this function should probably accept the values, not a recipe. wrap with a 
+// psphot-specific function which applies the recipe values
 pmPSFClump pmSourcePSFClump(psArray *sources, psMetadata *recipe)
 {
@@ -458,6 +482,6 @@
         // XXX EAM : can we use the value of SATURATE if mask is NULL?
         inner = psRegionForSquare (source->peak->x, source->peak->y, 2);
-        inner = psRegionForImage (source->mask, inner);
-        int Nsatpix = psImageCountPixelMask (source->mask, inner, PM_MASK_SAT);
+        inner = psRegionForImage (source->maskView, inner);
+        int Nsatpix = psImageCountPixelMask (source->maskView, inner, PM_MASK_SAT);
 
         // saturated star (size consistent with PSF or larger)
@@ -572,5 +596,5 @@
     PS_ASSERT_PTR_NON_NULL(source->peak, false);
     PS_ASSERT_PTR_NON_NULL(source->pixels, false);
-    PS_ASSERT_PTR_NON_NULL(source->mask, false);
+    PS_ASSERT_PTR_NON_NULL(source->maskObj, false);
     PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
 
@@ -622,5 +646,5 @@
         psF32 *vPix = source->pixels->data.F32[row];
         psF32 *vWgt = source->weight->data.F32[row];
-        psU8  *vMsk = (source->mask == NULL) ? NULL : source->mask->data.U8[row];
+        psU8  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.U8[row];
 
         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
@@ -751,85 +775,62 @@
     // in some places (psphotEnsemble), we need a normalized version
     // in others, we just want the model.  which is more commonly used?
-    pmModelAdd (source->modelFlux, source->mask, model, PM_MODEL_ADD_FULL | PM_MODEL_ADD_NORM);
+    pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM);
     return true;
 }
 
-// XXX should this API take an operator (+/-)?
-// XXX should we specify norm, etc?
-bool pmSourceAdd (pmSource *source) {
+// should we call pmSourceCacheModel if it does not exist?
+bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add) {
+
+    pmModel *model = pmSourceGetModel (NULL, source);
+    if (model == NULL) continue;  // model must be defined
 
     if (source->modelFlux) {
 	// add in the pixels from the modelFlux image
-	psImageSubsetAdd (source->pixels, source->modelFlux);
+	int dX = source->modelFlux->col0 - source->pixels->col0;
+	int dY = source->modelFlux->row0 - source->pixels->row0;
+	assert (dX >= 0);
+	assert (dY >= 0);
+	assert (dX + source->modelFlux->numCols < source->pixels->numCols);
+	assert (dY + source->modelFlux->numRows < source->pixels->numRows);
+	
+	float Io = 1.0;
+	if (mode & PM_MODEL_OP_NORM) {
+	    Io = 1.0 / model->params->data.F32[PM_PAR_I0];
+	}
+
+	// XXX need to respect the source and model masks?
+	for (int iy = 0; iy < source->modelFlux->numRows; iy++) {
+	    oy = iy + dY;
+	    for (int ix = 0; ix < source->modelFlux->numCols; ix++) {
+		ox = ix + dX;
+		float value = Io*source->modelFlux->data.F32[iy][ix];
+		if (add) {
+		    source->pixels->data.F32[oy][ox] -= value;
+		} else {
+		    source->pixels->data.F32[oy][ox] += value;
+		}
+	    }
+	}
     } else {
-	pmModel *model = pmSourceGetModel (NULL, source);
-	if (model == NULL) continue;  // model must be defined
-	pmModelAdd (source->pixels, source->mask, model, PM_MODEL_ADD_FULL);
+	if (add) {
+	    pmModelAdd (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL);
+	} else {
+	    pmModelSub (source->pixels, source->maskObj, model, PM_MODEL_OP_FULL);
+	}
     }	
 
-    // we would need to save X,Y somehow (or use the peak?)
-    // psTrace ("psphot", 3, "replacing object at %f,%f\n", 
-    // model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
+    if (add) {
+	psTrace ("psphot", 3, "replacing object at %f,%f\n", source->peak->xf, source->peak->yf);
+    } else {
+	psTrace ("psphot", 3, "removing object at %f,%f\n", source->peak->xf, source->peak->yf);
+    }
     return true;
 }
 
-bool pmSourceSub (pmSource *source) {
-
-    if (source->modelFlux) {
-	// add in the pixels from the modelFlux image
-	psImageSubsetSub (source->pixels, source->modelFlux);
-    } else {
-	pmModel *model = pmSourceGetModel (NULL, source);
-	if (model == NULL) continue;  // model must be defined
-	pmModelSub (source->pixels, source->mask, model, PM_MODEL_ADD_FULL);
-    }	
-    return true;
-}
-
-// XXX merge this function with psImageOverlay, which is probably mid-defined
-bool psImageSubsetAdd (psImage *input, psImage *subset) {
-
-    // col0,row0 in both images refer to parent coordinates
-
-    int dX = subset->col0 - input->col0;
-    int dY = subset->row0 - input->row0;
-    assert (dX >= 0);
-    assert (dY >= 0);
-    assert (dX + subset->numCols < input->numCols);
-    assert (dY + subset->numRows < input->numRows);
-    assert (input->type.type == PS_TYPE_F32);
-    assert (subset->type.type == PS_TYPE_F32);
-
-    for (int iy = 0; iy < subset->numRows; iy++) {
-	oy = iy + dY;
-	for (int ix = 0; ix < subset->numCols; ix++) {
-	    ox = ix + dX;
-	    input->data.F32[oy][ox] += subset->data.F32[iy][ix];
-	}
-    }
-    return true;
-}
-
-// XXX merge this function with psImageOverlay, which is probably mid-defined
-bool psImageSubsetSub (psImage *input, psImage *subset) {
-
-    // col0,row0 in both images refer to parent coordinates
-
-    int dX = subset->col0 - input->col0;
-    int dY = subset->row0 - input->row0;
-    assert (dX >= 0);
-    assert (dY >= 0);
-    assert (dX + subset->numCols < input->numCols);
-    assert (dY + subset->numRows < input->numRows);
-    assert (input->type.type == PS_TYPE_F32);
-    assert (subset->type.type == PS_TYPE_F32);
-
-    for (int iy = 0; iy < subset->numRows; iy++) {
-	oy = iy + dY;
-	for (int ix = 0; ix < subset->numCols; ix++) {
-	    ox = ix + dX;
-	    input->data.F32[oy][ox] -= subset->data.F32[iy][ix];
-	}
-    }
-    return true;
-}
+bool pmSourceAdd (pmSource *source, pmSourceOpMode mode) {
+    pmSourceOp (source, mode, true);
+}
+
+bool pmSourceSub (pmSource *source, pmSourceOpMode mode) {
+    pmSourceOp (source, mode, false);
+}
Index: /branches/eam_02_branch/psModules/src/objects/pmSource.h
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmSource.h	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmSource.h	(revision 12956)
@@ -3,6 +3,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.10.6.1 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-04-21 21:30:21 $
+ * @version $Revision: 1.10.6.2 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-04-23 03:26:23 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -58,22 +58,24 @@
 typedef struct
 {
-    const int id;   ///< Unique ID for object
-    pmPeak *peak;   ///< Description of peak pixel.
-    psImage *pixels;   ///< Rectangular region including object pixels.
-    psImage *weight;   ///< Image variance.
-    psImage *mask;   ///< Mask which marks pixels associated with objects.
-    pmMoments *moments;   ///< Basic moments measure for the object.
-    pmModel *modelPSF;   ///< PSF Model fit (parameters and type)
-    pmModel *modelEXT;   ///< EXT (floating) Model fit (parameters and type).
-    pmSourceType type;   ///< Best identification of object.
-    pmSourceMode mode;   ///< Best identification of object.
+    const int id;			///< Unique ID for object
+    pmPeak *peak;			///< Description of peak pixel.
+    psImage *pixels;			///< Rectangular region including object pixels.
+    psImage *weight;			///< Image variance.
+    psImage *modelFlux;			///< cached copy of the model for this source
+    psImage *maskObj;			///< unique mask for this object which marks included pixels associated with objects.
+    psImage *maskView;			///< view into global image mask for this object region
+    pmMoments *moments;			///< Basic moments measure for the object.
+    pmModel *modelPSF;			///< PSF Model fit (parameters and type)
+    pmModel *modelEXT;			///< EXT (floating) Model fit (parameters and type).
+    pmSourceType type;			///< Best identification of object.
+    pmSourceMode mode;			///< Best identification of object.
     psArray *blends;
-    float psfMag;   ///< calculated from flux in modelPsf
-    float extMag;   ///< calculated from flux in modelEXT
-    float errMag;   ///< error in psfMag OR extMag (depending on type)
-    float apMag;   ///< apMag corresponding to psfMag or extMag (depending on type)
-    float pixWeight;   // model-weighted coverage of valid pixels
-    psRegion region;   // area on image covered by selected pixels
-    float sky, skyErr;   //?< The sky and its error at the center of the object
+    float psfMag;			///< calculated from flux in modelPsf
+    float extMag;			///< calculated from flux in modelEXT
+    float errMag;			///< error in psfMag OR extMag (depending on type)
+    float apMag;	       ///< apMag corresponding to psfMag or extMag (depending on type)
+    float pixWeight;			// model-weighted coverage of valid pixels
+    psRegion region;			// area on image covered by selected pixels
+    float sky, skyErr;			//?< The sky and its error at the center of the object
 }
 pmSource;
Index: /branches/eam_02_branch/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- /branches/eam_02_branch/psModules/src/objects/pmSourcePhotometry.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/src/objects/pmSourcePhotometry.c	(revision 12956)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA; GLG, MHPCC
  *
- *  @version $Revision: 1.22.4.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-04-21 21:30:21 $
+ *  @version $Revision: 1.22.4.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2007-04-23 03:26:23 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -109,5 +109,5 @@
     // XXX use pmSourceAdd instead?
     if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
-        pmModelAdd (source->pixels, source->mask, model, PM_MODEL_ADD_FULL);
+        pmModelAdd (source->pixels, source->mask, model, PM_MODEL_OP_FULL);
     }
 
@@ -212,5 +212,5 @@
     // if source was originally subtracted, re-subtract object, leave local sky
     if (source->mode & PM_SOURCE_MODE_SUBTRACTED) {
-        pmModelSub (source->pixels, source->mask, model, PM_MODEL_ADD_FULL);
+        pmModelSub (source->pixels, source->mask, model, PM_MODEL_OP_FULL);
     }
 
Index: /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel.c
===================================================================
--- /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel.c	(revision 12956)
@@ -136,5 +136,5 @@
 
     // create an image with the model, and add noise: gain is 1, subtracted sky is 100, readnoise is 5
-    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_ADD_FULL);
+    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_OP_FULL);
     int npix = 0;
     for (int j = 0; j < source->pixels->numRows; j++) {
Index: /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel_Delta.c
===================================================================
--- /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 12955)
+++ /branches/eam_02_branch/psModules/test/objects/tap_pmSourceFitModel_Delta.c	(revision 12956)
@@ -54,5 +54,5 @@
 
     // create an image with the model, and add noise: gain is 1, subtracted sky is 100, readnoise is 5
-    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_ADD_FULL);
+    pmModelAdd (source->pixels, source->mask, source->modelEXT, PM_MODEL_OP_FULL);
     int npix = 0;
     for (int j = 0; j < source->pixels->numRows; j++) {
