Index: trunk/ppMerge/src/ppMergeMask.c
===================================================================
--- trunk/ppMerge/src/ppMergeMask.c	(revision 24006)
+++ trunk/ppMerge/src/ppMergeMask.c	(revision 24114)
@@ -31,5 +31,14 @@
     int sample = psMetadataLookupS32(NULL, config->arguments, "SAMPLE"); ///< Size of sample for statistics
     bool chipStats = psMetadataLookupBool(&mdok, config->arguments, "MASK.CHIPSTATS"); ///< Statistics on chip?
-    float maskSuspect = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT"); ///< Threshold for suspect pixels
+
+    char *maskSuspectMode  = psMetadataLookupStr(NULL, config->arguments, "MASK.SUSPECT.MODE"); ///< Threshold for suspect pixels
+    if (strcasecmp(maskSuspectMode, "SIGMA") && strcasecmp(maskSuspectMode, "VALUE")) {
+        psError (PS_ERR_UNKNOWN, true, "Invalid choice for MASK.SUSPECT.MODE: %s\n", maskSuspectMode);
+        return false;
+    }
+    float maskSuspectSigma = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT.SIGMA"); ///< Threshold for suspect pixels
+    float maskSuspectMin   = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT.MIN"); ///< Threshold for suspect pixels
+    float maskSuspectMax   = psMetadataLookupF32(NULL, config->arguments, "MASK.SUSPECT.MAX"); ///< Threshold for suspect pixels
+
     float maskBad = psMetadataLookupF32(NULL, config->arguments, "MASK.BAD"); ///< Threshold for bad pixels
     pmMaskIdentifyMode maskMode = psMetadataLookupS32(NULL, config->arguments, "MASK.MODE"); ///< Mode for identifying bad pixels
@@ -154,43 +163,64 @@
                 valueIndex = 0;
             }
-            for (int i = 0; i < num; i++) {
-                int pixel = numPix * psRandomUniform(rng);
-                int x = pixel % numCols;
-                int y = pixel / numCols;
-                if (mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValRaw)) continue;
-                if (outMask && (outMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValOut)) continue;
-                if (!isfinite(image->data.F32[y][x])) continue;
-
-                values->data.F32[valueIndex++] = image->data.F32[y][x];
-            }
-
-            if (!chipStats) {
-                values->n = valueIndex;
-                if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
-                    psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout.");
-                    psFree(inView);
-                    psFree(readout);
-                    goto MERGE_MASK_ERROR;
-                }
-
-                float mean = psStatsGetValue(statistics, meanStat);
-                float stdev = psStatsGetValue(statistics, stdevStat);
-
-                // this function increments the count for each suspect pixel in each input plane
-                // maskValRaw is used to test for valid input pixels
-                if (!pmMaskFlagSuspectPixels(outRO, readout, mean, stdev, maskSuspect, maskValRaw)) {
-                    psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
-                    psFree(inView);
-                    psFree(readout);
-                    goto MERGE_MASK_ERROR;
-                }
-                pmCellFreeData(inCell);
-
-                if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
-                    psFree(inView);
-                    psFree(readout);
-                    goto MERGE_MASK_ERROR;
-                }
-            }
+
+	    if (!strcasecmp(maskSuspectMode, "VALUE")) {
+		// this function increments the count for each suspect pixel in each input plane
+		// maskValRaw is used to test for valid input pixels
+		if (!pmMaskFlagSuspectPixelsByValue(outRO, readout, maskSuspectMin, maskSuspectMax, maskValRaw)) {
+		    psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
+		    psFree(inView);
+		    psFree(readout);
+		    goto MERGE_MASK_ERROR;
+		}
+		pmCellFreeData(inCell);
+
+		if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
+		    psFree(inView);
+		    psFree(readout);
+		    goto MERGE_MASK_ERROR;
+		}
+	    } else {
+		// extract a subset of pixels for stats measurement -- don't use pixels which are masked for this calculation
+		for (int i = 0; i < num; i++) {
+		    int pixel = numPix * psRandomUniform(rng);
+		    int x = pixel % numCols;
+		    int y = pixel / numCols;
+		    if (mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValRaw)) continue;
+		    if (outMask && (outMask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValOut)) continue;
+		    if (!isfinite(image->data.F32[y][x])) continue;
+
+		    values->data.F32[valueIndex] = image->data.F32[y][x];
+		    valueIndex++;
+		}
+
+		// for per-readout stats, measure the stats and find the suspect pixels
+		if (!chipStats) {
+		    values->n = valueIndex;
+		    if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
+			psError(PS_ERR_UNKNOWN, false, "Unable to do statistics on readout.");
+			psFree(inView);
+			psFree(readout);
+			goto MERGE_MASK_ERROR;
+		    }
+		    float mean = psStatsGetValue(statistics, meanStat);
+		    float stdev = psStatsGetValue(statistics, stdevStat);
+
+		    // this function increments the count for each suspect pixel in each input plane
+		    // maskValRaw is used to test for valid input pixels
+		    if (!pmMaskFlagSuspectPixelsBySigma(outRO, readout, mean, stdev, maskSuspectSigma, maskValRaw)) {
+			psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
+			psFree(inView);
+			psFree(readout);
+			goto MERGE_MASK_ERROR;
+		    }
+		    pmCellFreeData(inCell);
+
+		    if (!pmFPAfileIOChecks(config, inView, PM_FPA_AFTER)) {
+			psFree(inView);
+			psFree(readout);
+			goto MERGE_MASK_ERROR;
+		    }
+		}
+	    }
             psFree(readout);
             psFree(outRO);
@@ -198,5 +228,6 @@
 
         // Additional run through cells if we want chip-level statistics
-        if (chipStats && valueIndex > 0) {
+	// only used for MASK.SUSPECT.MODE == SIGMA
+        if (!strcasecmp(maskSuspectMode, "SIGMA") && chipStats && valueIndex > 0) {
             values->n = valueIndex;
             if (!psVectorStats(statistics, values, NULL, NULL, 0)) {
@@ -221,5 +252,5 @@
                 float stdev = psStatsGetValue(statistics, stdevStat);
 
-                if (!pmMaskFlagSuspectPixels(outRO, readout, mean, stdev, maskSuspect, maskValRaw)) {
+                if (!pmMaskFlagSuspectPixelsBySigma(outRO, readout, mean, stdev, maskSuspectSigma, maskValRaw)) {
                     psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
                     goto MERGE_MASK_ERROR;
