Index: trunk/psModules/src/camera/pmFPAMaskWeight.h
===================================================================
--- trunk/psModules/src/camera/pmFPAMaskWeight.h	(revision 18508)
+++ trunk/psModules/src/camera/pmFPAMaskWeight.h	(revision 18554)
@@ -5,6 +5,6 @@
  * @author Eugene Magnier, IfA
  *
- * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
- * @date $Date: 2008-05-17 02:42:01 $
+ * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
  * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -32,5 +32,4 @@
     PM_MASK_MARK     = 0x80,            ///< The pixel is marked as temporarily ignored
 } pmMaskValue;
-#else
 #define PM_MASK_MARK 0x80            ///< The pixel is marked as temporarily ignored
 #define PM_MASK_SAT  0x04            ///< The pixel is saturated in the image of interest
@@ -43,6 +42,6 @@
 /// iterating using pmReadoutReadNext, in which case the HDU can't be generated.
 bool pmReadoutSetMask(pmReadout *readout, ///< Readout for which to set mask
-                      psMaskType sat,   ///< Mask value to give saturated pixels
-                      psMaskType bad    ///< Mask value to give bad (low) pixels
+                      psMaskType satMask, ///< Mask value to give saturated pixels
+                      psMaskType badMask  ///< Mask value to give bad (low) pixels
     );
 
Index: trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 18508)
+++ trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 18554)
@@ -10,4 +10,5 @@
 #include "pmErrorCodes.h"
 #include "pmConfig.h"
+#include "pmConfigMask.h"
 #include "pmDetrendDB.h"
 
@@ -489,4 +490,11 @@
         psFree(realName);
         return NULL;
+    }
+
+    if (file->type == PM_FPA_FILE_MASK) {
+	if (!pmConfigMaskReadHeader (config, phu)) {
+	    psError(PS_ERR_IO, false, "error in mask bits");
+	    return NULL;
+	}
     }
 
@@ -660,4 +668,5 @@
     file->fileLevel = input->fileLevel;
 
+
     // define the rule to identify these files in the file->names data
     psFree (file->filerule);
@@ -735,4 +744,11 @@
         psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
 
+	if ((i == 0) && (file->type == PM_FPA_FILE_MASK)) {
+	    if (!pmConfigMaskReadHeader (config, phu)) {
+		psError(PS_ERR_IO, false, "error in mask bits");
+		return NULL;
+	    }
+	}
+
         psFree(view);
         psFree(name);
@@ -806,4 +822,11 @@
 	psFree(formatName);
         return NULL;
+    }
+
+    if (file->type == PM_FPA_FILE_MASK) {
+	if (!pmConfigMaskReadHeader (config, phu)) {
+	    psError(PS_ERR_IO, false, "error in mask bits");
+	    return NULL;
+	}
     }
 
Index: trunk/psModules/src/camera/pmFPAfileFitsIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 18508)
+++ trunk/psModules/src/camera/pmFPAfileFitsIO.c	(revision 18554)
@@ -7,4 +7,5 @@
 
 #include "pmConfig.h"
+#include "pmConfigMask.h"
 #include "pmDetrendDB.h"
 
@@ -496,4 +497,13 @@
     }
 
+    // whenever we write out a mask image, we should define the bits which represent mask concepts
+    if (file->type == PM_FPA_FILE_MASK) {
+	assert (phu->header);
+	if (!pmConfigMaskWriteHeader (config, phu->header)) {
+	    psError(PS_ERR_UNKNOWN, false, "failed to set the bitmask names in the PHU header for Image %s (%s)\n", file->filename, file->name);
+	    return false;
+	}
+    }
+
     switch (file->fileLevel) {
       case PM_FPA_LEVEL_FPA:
Index: trunk/psModules/src/camera/pmFPAfileIO.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileIO.c	(revision 18508)
+++ trunk/psModules/src/camera/pmFPAfileIO.c	(revision 18554)
@@ -9,4 +9,5 @@
 
 #include "pmConfig.h"
+#include "pmConfigMask.h"
 #include "pmDetrendDB.h"
 
@@ -428,4 +429,13 @@
             }
             pmConfigConformHeader(hdu->header, file->format);
+
+	    // whenever we write out a mask image, we should define the bits which represent mask concepts
+	    if (file->type == PM_FPA_FILE_MASK) {
+		assert (hdu->header);
+		if (!pmConfigMaskWriteHeader (config, hdu->header)) {
+		    psError(PS_ERR_UNKNOWN, false, "failed to set the bitmask names in the PHU header for Image %s (%s)\n", file->filename, file->name);
+		    return false;
+		}
+	    }
         }
 
@@ -792,4 +802,13 @@
           }
 
+	  // XXX if we have a mask file, then we need to read the mask bit names
+	  // defined for this file
+	  if (file->type == PM_FPA_FILE_MASK) {
+	    if (!pmConfigMaskReadHeader (config, phu)) {
+		psError(PS_ERR_IO, false, "error in mask bits");
+		return false;
+	    }
+	  }
+
           // determine the current format from the header
           // determine camera if not specified already
Index: trunk/psModules/src/camera/pmHDUUtils.c
===================================================================
--- trunk/psModules/src/camera/pmHDUUtils.c	(revision 18508)
+++ trunk/psModules/src/camera/pmHDUUtils.c	(revision 18554)
@@ -9,4 +9,25 @@
 #include "pmFPA.h"
 #include "pmHDUUtils.h"
+
+pmHDU *pmHDUGetFirst (const pmFPA *fpa) {
+
+    // XXX we probably should have an indicator in pmFPA about the depths.
+
+    if (!fpa) return NULL;
+    if (fpa->hdu) return fpa->hdu;
+
+    for (int i = 0; i < fpa->chips->n; i++) {
+	pmChip *chip = fpa->chips->data[i];
+	if (!chip) continue;
+	if (chip->hdu) return chip->hdu;
+	if (!chip->cells) continue;
+	for (int j = 0; j < chip->cells->n; j++) {
+	    pmCell *cell = chip->cells->data[j];
+	    if (!cell) continue;
+	    if (cell->hdu) return cell->hdu;
+	}
+    }
+    return NULL;
+}
 
 pmHDU *pmHDUFromFPA(const pmFPA *fpa)
Index: trunk/psModules/src/camera/pmHDUUtils.h
===================================================================
--- trunk/psModules/src/camera/pmHDUUtils.h	(revision 18508)
+++ trunk/psModules/src/camera/pmHDUUtils.h	(revision 18554)
@@ -4,6 +4,6 @@
  * @author Paul Price, IfA
  *
- * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-03-30 21:12:56 $
+ * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
  * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -14,4 +14,7 @@
 /// @addtogroup Camera Camera Layout
 /// @{
+
+/// Get the first HDU encountered in the hierarchy
+pmHDU *pmHDUGetFirst (const pmFPA *fpa);
 
 /// Get the lowest HDU in the hierarchy
Index: trunk/psModules/src/config/pmConfigMask.c
===================================================================
--- trunk/psModules/src/config/pmConfigMask.c	(revision 18508)
+++ trunk/psModules/src/config/pmConfigMask.c	(revision 18554)
@@ -9,5 +9,5 @@
 #include "pmConfigMask.h"
 
-psMaskType pmConfigMask(const char *masks, const pmConfig *config)
+psMaskType pmConfigMaskGet(const char *masks, const pmConfig *config)
 {
     assert (config);
@@ -39,2 +39,202 @@
     return mask;
 }
+
+bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue)
+{
+    assert (config);
+    PS_ASSERT_STRING_NON_EMPTY(maskName, false);
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    psMetadataAddU8 (recipe, PS_LIST_TAIL, maskName, PS_META_REPLACE, "user-defined mask", maskValue);
+
+    return true;
+}
+
+// replace the named masks in the recipe with values in the header:
+// replace only the names in the header in the recipe
+bool pmConfigMaskReadHeader (pmConfig *config, psMetadata *header) {
+
+    bool status = false;
+    char namekey[80];
+    char valuekey[80];
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    int nMask = psMetadataLookupS32 (&status, header, "MSKNUM");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "Unable to find MSKNUM in header.");
+        return false;
+    }
+
+    for (int i = 0; i < nMask; i++) {
+
+	snprintf (namekey,  64, "MSKNAM%02d", i);
+	snprintf (valuekey, 64, "MSKVAL%02d", i);
+
+	char *name = psMetadataLookupStr (&status, header, namekey);
+	psU8 bit = psMetadataLookupU8 (&status, header, valuekey);
+
+	// XXX validate that bit is a 2^n value?
+
+	psMetadataItem *item = psMetadataLookup (header, name);
+	if (!item) {
+	    psWarning("mask recipe entry %s not in recipe\n", name);
+	    psMetadataAddU8 (recipe, PS_LIST_TAIL, name, 0, "Bitmask bit value", bit);
+	} else {
+	    item->data.U8 = bit;
+	}
+    }
+    
+    return true;
+}
+
+// write the named mask bits to the header
+bool pmConfigMaskWriteHeader (pmConfig *config, psMetadata *header) {
+
+    char namekey[80];
+    char valuekey[80];
+
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "MASKS"); // The recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find MASKS recipe.");
+        return false;
+    }
+
+    int nMask = 0;
+
+    psMetadataIterator *iter = psMetadataIteratorAlloc(recipe, PS_LIST_HEAD, NULL); // Iterator
+
+    psMetadataItem *item;               // Item from iteration
+    while ((item = psMetadataGetAndIncrement(iter))) {
+
+	if (item->type != PS_DATA_U8) {
+	    psWarning("mask recipe entry %s is not a bit value\n", item->name);
+	    continue;
+	}
+
+	snprintf (namekey,  64, "MSKNAM%02d", nMask);
+	snprintf (valuekey, 64, "MSKVAL%02d", nMask);
+
+	psMetadataAddStr (header, PS_LIST_TAIL, namekey, 0, "Bitmask bit name", item->name);
+	psMetadataAddU8 (header, PS_LIST_TAIL, valuekey, 0, "Bitmask bit value", item->data.U8);
+	nMask ++;
+    }
+    
+    psMetadataAddS32 (header, PS_LIST_TAIL, "MSKNUM", 0, "Bitmask bit count", nMask);
+    return true;
+}
+
+// examine named mask values in mask recipe and set the bits for maskValue and markValue
+// this function sets an appropriate value for the following required named mask concepts: 
+// FLAT (used to mark out-of-range corrections in the flat-fielding)
+// BLANK (used to mark non-existent pixels)
+// SAT (used to mark pixels with values out-of-range on the high end)
+// BAD (used to mark pixels with values out-of-range on the low end)
+// If there is no explicit value for the above, the 'DETECTOR' and 'RANGE' bits are used
+// If these latter do not exist, the value 0x01 is used.
+// The values actually used for these names are written back to the config file
+bool pmConfigMaskSetBits (psMaskType *outMaskValue, psMaskType *outMarkValue, pmConfig *config) {
+
+    psMaskType maskValue = 0;
+
+    // mask for generic detector defect
+    psMaskType detectorMask = pmConfigMaskGet("DETECTOR", config); 
+    maskValue |= detectorMask;
+
+    // mask for dark structures
+    psMaskType darkMask = pmConfigMaskGet("DARK", config);
+    maskValue |= darkMask;
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType flatMask = pmConfigMaskGet("FLAT", config); 
+    if (!flatMask) {
+	flatMask = detectorMask;
+	pmConfigMaskSet (config, "FLAT", flatMask);
+    }
+    if (!flatMask) {
+	flatMask = 0x01;
+	pmConfigMaskSet (config, "FLAT", flatMask);
+    }
+    maskValue |= flatMask;
+
+    // mask for non-existent data  (default to DETECTOR if not defined)
+    psMaskType blankMask = pmConfigMaskGet("BLANK", config); 
+    if (!blankMask) {
+	blankMask = detectorMask;
+	pmConfigMaskSet (config, "BLANK", blankMask);
+    }
+    if (!blankMask) {
+	blankMask = 0x01;
+	pmConfigMaskSet (config, "BLANK", blankMask);
+    }
+    maskValue |= blankMask;
+
+    // mask for generic data range errors
+    psMaskType rangeMask = pmConfigMaskGet("RANGE", config);
+    maskValue |= rangeMask;
+
+    // mask for saturated data  (default to RANGE if not defined)
+    psMaskType satMask = pmConfigMaskGet("SAT", config);
+    if (!satMask) {
+	satMask = rangeMask;
+	pmConfigMaskSet (config, "SAT", satMask);
+    }
+    if (!satMask) {
+	satMask = 0x01;
+	pmConfigMaskSet (config, "SAT", satMask);
+    }
+    maskValue |= satMask;
+    
+    // mask for below-range data  (default to RANGE if not defined)
+    psMaskType badMask = pmConfigMaskGet("BAD", config);
+    if (!badMask) {
+	badMask = rangeMask;
+	pmConfigMaskSet (config, "BAD", badMask);
+    }
+    if (!badMask) {
+	badMask = 0x01;
+	pmConfigMaskSet (config, "BAD", badMask);
+    }
+    maskValue |= badMask;
+
+    // XXX not sure what to do with these
+    psMaskType crMask = pmConfigMaskGet("CR", config);
+    maskValue |= crMask;
+
+    psMaskType ghostMask = pmConfigMaskGet("GHOST", config);
+    maskValue |= ghostMask;
+
+    // search for an unset bit to use for MARK:
+    psMaskType markValue = 0x80;
+
+    int nBits = sizeof(psMaskType) * 8;
+    for (int i = 0; !markValue && (i < nBits); i++) {
+	if (maskValue & markValue) {
+	    markValue >>= 1;
+	} else {
+	    markValue = markValue;
+	}
+    }
+    if (!markValue) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
+	return false;
+    }
+
+    // update the config table
+    pmConfigMaskSet (config, "MASK.VALUE", maskValue);
+    pmConfigMaskSet (config, "MARK.VALUE", markValue);
+
+    *outMaskValue = maskValue;
+    *outMarkValue = markValue;
+
+    return true;
+}
Index: trunk/psModules/src/config/pmConfigMask.h
===================================================================
--- trunk/psModules/src/config/pmConfigMask.h	(revision 18508)
+++ trunk/psModules/src/config/pmConfigMask.h	(revision 18554)
@@ -4,6 +4,6 @@
  *  @author Paul Price, IfA
  *
- *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-03-05 01:06:37 $
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *  Copyright 2007 Institute for Astronomy, University of Hawaii
  */
@@ -23,7 +23,18 @@
 ///
 /// The mask values are derived from the MASKS recipe
-psMaskType pmConfigMask(const char *masks, ///< List of symbolic names, space/comma delimited
+psMaskType pmConfigMaskGet(const char *masks, ///< List of symbolic names, space/comma delimited
                         const pmConfig *config ///< Configuration
                         );
 
+bool pmConfigMaskSet(const pmConfig *config, const char *maskName, psMaskType maskValue);
+
+// replace the named masks in the recipe with values in the header:
+// replace only the names in the header in the recipe
+bool pmConfigMaskReadHeader (pmConfig *config, psMetadata *header);
+
+// write the named mask bits to the header
+bool pmConfigMaskWriteHeader (pmConfig *config, psMetadata *header);
+
+bool pmConfigMaskSetBits (psMaskType *outMaskValue, psMaskType *outMarkValue, pmConfig *config);
+
 #endif
Index: trunk/psModules/src/detrend/pmMaskBadPixels.c
===================================================================
--- trunk/psModules/src/detrend/pmMaskBadPixels.c	(revision 18508)
+++ trunk/psModules/src/detrend/pmMaskBadPixels.c	(revision 18554)
@@ -123,10 +123,11 @@
     psTrace ("psModules.detrend", 3, "suspect: %f +/- %f\n", median, stdev);
 
+    // XXX this loop could result in pixels with suspect = 0.0 but no valid input pixels (all
+    // masked).  need to track the number of good as well as suspect pixels?
     for (int y = 0; y < image->numRows; y++) {
         for (int x = 0; x < image->numCols; x++) {
-            if (fabs((image->data.F32[y][x] - median) / stdev) >= rej &&
-		(!mask || !(mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal))) {
-                suspect->data.F32[y][x] += 1.0;
-            }
+            if (fabs((image->data.F32[y][x] - median) / stdev) < rej) continue;
+	    if (mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) continue;
+	    suspect->data.F32[y][x] += 1.0;
         }
     }
@@ -140,4 +141,5 @@
 }
 
+// the maskVal supplied here is the value SET for this mask (ie, it is not used to avoid pixels)
 bool pmMaskIdentifyBadPixels(pmReadout *output, psMaskType maskVal, float thresh, pmMaskIdentifyMode mode)
 {
Index: trunk/psModules/src/objects/pmPSF.c
===================================================================
--- trunk/psModules/src/objects/pmPSF.c	(revision 18508)
+++ trunk/psModules/src/objects/pmPSF.c	(revision 18554)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-01-02 20:41:55 $
+ *  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -404,5 +404,5 @@
 
 // we generate the growth curve for the center of the image with the specified psf model
-bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal, psMaskType mark)
+bool pmGrowthCurveGenerate (pmReadout *readout, pmPSF *psf, bool ignore, psMaskType maskVal, psMaskType markVal)
 {
     PS_ASSERT_PTR_NON_NULL(readout, false);
@@ -416,4 +416,7 @@
     // create template model
     pmModel *modelRef = pmModelAlloc(psf->type);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
 
     // use the center of the center pixel of the image
@@ -465,5 +468,5 @@
 
         // mask the given aperture and measure the apMag
-        psImageKeepCircle (mask, xc, yc, radius, "OR", mark);
+        psImageKeepCircle (mask, xc, yc, radius, "OR", markVal);
         if (!pmSourcePhotometryAper (&apMag, model, image, mask, maskVal)) {
             psError(PM_ERR_PHOTOM, false, "Measuring apMag for radius == %g", radius);
@@ -473,7 +476,5 @@
             break;
         }
-
-        // XXX since we re-mask on each pass, this could be dropped.
-        psImageKeepCircle (mask, xc, yc, radius, "AND", PS_NOT_U8(mark));
+        psImageKeepCircle (mask, xc, yc, radius, "AND", PS_NOT_U8(markVal));
 
         // the 'ignore' mode is for testing
Index: trunk/psModules/src/objects/pmPSFtry.c
===================================================================
--- trunk/psModules/src/objects/pmPSFtry.c	(revision 18508)
+++ trunk/psModules/src/objects/pmPSFtry.c	(revision 18554)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-06-10 01:32:15 $
+ *  @version $Revision: 1.57 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -98,5 +98,5 @@
 
 // generate a pmPSFtry with a copy of the test PSF sources
-pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psMaskType maskVal, psMaskType mark)
+pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psMaskType maskVal, psMaskType markVal)
 {
     bool status;
@@ -116,4 +116,7 @@
         return NULL;
     }
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
 
     // stage 1:  fit an EXT model to all candidates PSF sources
@@ -129,9 +132,12 @@
         }
 
-        // set object mask to define valid pixels -- XXX not unset?
-        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", mark);
+        // set object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", markVal);
 
         // fit model as EXT, not PSF
         status = pmSourceFitModel (source, source->modelEXT, PM_SOURCE_FIT_EXT, maskVal);
+
+	// clear object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
 
         // exclude the poor fits
@@ -170,6 +176,6 @@
         source->modelPSF->radiusFit = options->radius;
 
-        // set object mask to define valid pixels -- XXX not unset?
-        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", mark);
+        // set object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "OR", markVal);
 
         // fit the PSF model to the source
@@ -178,4 +184,5 @@
         // skip poor fits
         if (!status) {
+	    psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
             psfTry->mask->data.U8[i] = PSFTRY_MASK_PSF_FAIL;
             psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : failed PSF fit\n", i, source->peak->x, source->peak->y);
@@ -183,11 +190,14 @@
         }
 
-        // XXX : use a different aperture radius from the fit radius?
-        status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal, mark);
+        status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal);
 	if (!status || isnan(source->apMag)) {
+	    psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
             psfTry->mask->data.U8[i] = PSFTRY_MASK_BAD_PHOT;
             psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : poor photometry\n", i, source->peak->x, source->peak->y);
             continue;
         }
+
+	// clear object mask to define valid pixels
+        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, options->radius, "AND", PS_NOT_U8(markVal));
 
         psfTry->fitMag->data.F32[i] = source->psfMag;
Index: trunk/psModules/src/objects/pmSource.c
===================================================================
--- trunk/psModules/src/objects/pmSource.c	(revision 18508)
+++ trunk/psModules/src/objects/pmSource.c	(revision 18554)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-06-10 02:26:17 $
+ *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -838,6 +838,5 @@
 
 // should we call pmSourceCacheModel if it does not exist?
-bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add,
-                 psMaskType maskVal, int dx, int dy)
+bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, psMaskType maskVal, int dx, int dy)
 {
     PS_ASSERT_PTR_NON_NULL(source, false);
Index: trunk/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- trunk/psModules/src/objects/pmSourcePhotometry.c	(revision 18508)
+++ trunk/psModules/src/objects/pmSourcePhotometry.c	(revision 18554)
@@ -3,6 +3,6 @@
  *  @author EAM, IfA; GLG, MHPCC
  *
- *  @version $Revision: 1.42 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-06-09 00:43:46 $
+ *  @version $Revision: 1.43 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -64,6 +64,5 @@
 
 // XXX masked region should be (optionally) elliptical
-bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode,
-                         psMaskType maskVal, psMaskType mark)
+bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal)
 {
     PS_ASSERT_PTR_NON_NULL(source, false);
@@ -230,18 +229,13 @@
         mask = source->maskObj;
     }
-    // set aperture mask circle to model radius
-    // XXX use a different radius for apertures and fits...
-    // XXX can I remove this?  the source should have the mask defined when it is constructed or
-    // when the fit / aperture radius is changed...
-    psImageKeepCircle (source->maskObj, x, y, model->radiusFit, "OR", mark);
 
     // measure the weight of included pixels
     // XXX is this supposed to use the weight or the flux?
     if (mode & PM_SOURCE_PHOT_WEIGHT) {
-        pmSourcePixelWeight (&source->pixWeight, model, source->pixels, source->maskObj, maskVal | mark);
+        pmSourcePixelWeight (&source->pixWeight, model, source->pixels, source->maskObj, maskVal);
     }
 
     // measure object aperture photometry
-    status = pmSourcePhotometryAper  (&source->apMag, model, flux, mask, maskVal | mark);
+    status = pmSourcePhotometryAper  (&source->apMag, model, flux, mask, maskVal);
     if (!status) {
         psTrace ("psModules.objects", 3, "fail mag : bad Ap Mag");
@@ -264,8 +258,4 @@
         psFree(mask);
     }
-
-    // unmask aperture
-    // XXX can I remove this?  this will probably break things downstream...
-    psImageKeepCircle (source->maskObj, x, y, model->radiusFit, "AND", PS_NOT_U8(mark));
 
     // if source was originally subtracted, re-subtract object, leave local sky
@@ -308,6 +298,5 @@
 
 // return source aperture magnitude
-bool pmSourcePhotometryAper (float *apMag, pmModel *model, psImage *image, psImage *mask,
-                             psMaskType maskVal)
+bool pmSourcePhotometryAper (float *apMag, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
 {
     PS_ASSERT_PTR_NON_NULL(apMag, false);
@@ -347,6 +336,5 @@
 
 // return source aperture magnitude
-bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask,
-                          psMaskType maskVal)
+bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal)
 {
     PS_ASSERT_PTR_NON_NULL(pixWeight, false);
Index: trunk/psModules/src/objects/pmSourcePhotometry.h
===================================================================
--- trunk/psModules/src/objects/pmSourcePhotometry.h	(revision 18508)
+++ trunk/psModules/src/objects/pmSourcePhotometry.h	(revision 18554)
@@ -4,6 +4,6 @@
  * @author EAM, IfA; GLG, MHPCC
  *
- * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-06-20 02:22:26 $
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2008-07-15 20:25:00 $
  * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  */
@@ -50,5 +50,5 @@
 
 bool pmSourceMagnitudesInit (psMetadata *config);
-bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal, psMaskType mark);
+bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psMaskType maskVal);
 bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *image, psImage *mask, psMaskType maskVal);
 bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psMaskType maskVal);
Index: trunk/psModules/src/objects/pmSourcePlotMoments.c
===================================================================
--- trunk/psModules/src/objects/pmSourcePlotMoments.c	(revision 18508)
+++ trunk/psModules/src/objects/pmSourcePlotMoments.c	(revision 18554)
@@ -5,6 +5,6 @@
  *  @author EAM, IfA
  *
- *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-11-10 01:09:20 $
+ *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2006 IfA, University of Hawaii
@@ -95,6 +95,6 @@
     graphdata.xmin = -0.05;
     graphdata.ymin = -0.05;
-    graphdata.xmax = +2.05;
-    graphdata.ymax = +2.05;
+    graphdata.xmax = +4.05;
+    graphdata.ymax = +4.05;
     KapaSetLimits (kapa, &graphdata);
 
Index: trunk/psModules/src/objects/pmSourceSky.c
===================================================================
--- trunk/psModules/src/objects/pmSourceSky.c	(revision 18508)
+++ trunk/psModules/src/objects/pmSourceSky.c	(revision 18554)
@@ -6,6 +6,6 @@
  *  @author EAM, IfA: significant modifications.
  *
- *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-01-02 20:39:04 $
+ *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-15 20:25:00 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -42,4 +42,6 @@
 
 The source.pixels and source.mask must already exist
+
+This function modifies the source mask; it should only be called before the object aperture is defined
 *****************************************************************************/
 
@@ -49,5 +51,5 @@
     psF32 Radius,
     psMaskType maskVal,
-    psMaskType mark)
+    psMaskType markVal)
 {
     psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
@@ -69,15 +71,18 @@
     psRegion srcRegion;
 
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
+
     srcRegion = psRegionForSquare(peak->x, peak->y, Radius);
     srcRegion = psRegionForImage(mask, srcRegion);
 
-    psImageMaskRegion(mask, srcRegion, "OR", mark);
+    psImageMaskRegion(mask, srcRegion, "OR", markVal);
     psStats *myStats = psStatsAlloc(statsOptions);
-    if (!psImageStats(myStats, image, mask, maskVal | mark)) {
+    if (!psImageStats(myStats, image, mask, maskVal)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
         psFree(myStats);
         return false;
     }
-    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(mark));
+    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(markVal));
     double value = psStatsGetValue(myStats, statistic);
     psFree(myStats);
@@ -101,5 +106,5 @@
     psF32 Radius,
     psMaskType maskVal,
-    psMaskType mark
+    psMaskType markVal
 )
 {
@@ -110,4 +115,7 @@
     PS_ASSERT_PTR_NON_NULL(source->peak, false);
     PS_ASSERT_INT_POSITIVE(Radius, false);
+
+    // maskVal is used to test for rejected pixels, and must include markVal
+    maskVal |= markVal;
 
     psStatsOptions statistic = psStatsSingleOption(statsOptions);
@@ -125,12 +133,12 @@
     srcRegion = psRegionForImage(mask, srcRegion);
 
-    psImageMaskRegion(mask, srcRegion, "OR", mark);
+    psImageMaskRegion(mask, srcRegion, "OR", markVal);
     psStats *myStats = psStatsAlloc(statsOptions);
-    if (!psImageStats(myStats, image, mask, maskVal | mark)) {
+    if (!psImageStats(myStats, image, mask, maskVal)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
         psFree(myStats);
         return false;
     }
-    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(mark));
+    psImageMaskRegion(mask, srcRegion, "AND", PS_NOT_U8(markVal));
     double value = psStatsGetValue(myStats, statistic);
     psFree(myStats);
