Index: /trunk/ppMerge/src/ppMergeArguments.c
===================================================================
--- /trunk/ppMerge/src/ppMergeArguments.c	(revision 18557)
+++ /trunk/ppMerge/src/ppMergeArguments.c	(revision 18558)
@@ -138,5 +138,8 @@
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-nkeep",    0, "Minimum number of pixels in stack to keep", 0);
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-weights", 0, "Use image weights in combination?", false);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-maskval",  0, "Mask value for input data", NULL);
+
+    // XXX EAM : not clear this should be allowed on the command line.
+    // psMetadataAddStr(arguments, PS_LIST_TAIL, "-maskval",  0, "Mask value for input data", NULL);
+
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-combine",  0, "Statistic to use for combination", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-mean",     0, "Statistic to use to measure the mean", NULL);
@@ -159,5 +162,5 @@
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask-mode",     0, "Mode to identify bad pixels", NULL);
     psMetadataAddS32(arguments, PS_LIST_TAIL, "-mask-grow",     0, "Number of pixels to grow final mask", 0);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask-growval",  0, "Value to give grown mask pixels", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-mask-set-valud",0, "Value to set for output mask pixels", NULL);
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-mask-chip",    0, "Measure mask statistics by chip?", false);
 
@@ -264,5 +267,8 @@
     VALUE_ARG_RECIPE_INT("-nkeep",      "NKEEP",    S32, 0);
     VALUE_ARG_RECIPE_BOOL("-weights",   "WEIGHTS");
-    VALUE_ARG_RECIPE_MASK("-maskval",   "MASKVAL");
+
+    // XXX we do not supply this on the command line
+    // VALUE_ARG_RECIPE_MASK("-maskval",   "MASKVAL");
+
     VALUE_ARG_RECIPE_STAT("-combine",   "COMBINE");
     VALUE_ARG_RECIPE_STAT("-mean",      "MEAN");
@@ -281,6 +287,6 @@
     VALUE_ARG_RECIPE_FLOAT("-mask-suspect", "MASK.SUSPECT", F32);
     VALUE_ARG_RECIPE_FLOAT("-mask-bad",     "MASK.BAD",     F32);
-    VALUE_ARG_RECIPE_INT("-mask-grow",      "MASK.GROW",    S32, -1);
-    VALUE_ARG_RECIPE_MASK("-mask-growval",  "MASK.GROWVAL");
+    VALUE_ARG_RECIPE_INT("-mask-grow",      "MASK.GROW",    S32, 0);
+    VALUE_ARG_RECIPE_STR("-mask-set-value", "MASK.SET.VALUE");
     VALUE_ARG_RECIPE_BOOL("-mask-chip",     "MASK.CHIPSTATS");
 
Index: /trunk/ppMerge/src/ppMergeLoop.c
===================================================================
--- /trunk/ppMerge/src/ppMergeLoop.c	(revision 18557)
+++ /trunk/ppMerge/src/ppMergeLoop.c	(revision 18558)
@@ -39,5 +39,4 @@
     float frachigh = psMetadataLookupF32(NULL, arguments, "FRACHIGH"); // Reject fraction of hi pixels
     int nKeep = psMetadataLookupS32(NULL, arguments, "NKEEP"); // Minimum number of values to keep
-    psMaskType maskVal = psMetadataLookupU8(NULL, arguments, "MASKVAL"); // Value to mask
     psStatsOptions combineStat = psMetadataLookupS32(NULL, arguments, "COMBINE"); // Combination statistic
     bool useWeights = psMetadataLookupBool(NULL, arguments, "WEIGHTS"); // Use weights?
@@ -49,7 +48,15 @@
     int fringeSmoothY = psMetadataLookupS32(NULL, arguments, "FRINGE.YSMOOTH"); // Smoothing regions in y
 
+    // set the mask and mark bit values based on the named masks
+    psMaskType maskVal;
+    psMaskType markVal;
+    if (!pmConfigMaskSetBits (&maskVal, &markVal, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
     pmCombineParams *combination = pmCombineParamsAlloc(combineStat); // Combination parameters
     combination->maskVal = maskVal;
-    combination->blank = pmConfigMask("BLANK", config);
+    combination->blank = pmConfigMaskGet("BLANK", config);
     combination->nKeep = nKeep;
     combination->fracHigh = frachigh;
@@ -294,5 +301,5 @@
             }
 
-            if (!ppStatsFPA(stats, outFPA, view, maskVal | pmConfigMask("BLANK", config), config)) {
+            if (!ppStatsFPA(stats, outFPA, view, maskVal, config)) {
                 psError(PS_ERR_UNKNOWN, true, "Unable to generate stats for image.");
                 goto ERROR;
Index: /trunk/ppMerge/src/ppMergeMask.c
===================================================================
--- /trunk/ppMerge/src/ppMergeMask.c	(revision 18557)
+++ /trunk/ppMerge/src/ppMergeMask.c	(revision 18558)
@@ -18,5 +18,5 @@
                       psRandom *rng,    // Random number generator
                       psMetadata *stats // Statistics output
-                      )
+    )
 {
     assert(config);
@@ -28,5 +28,4 @@
     psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean
     psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev
-    psMaskType maskVal = psMetadataLookupU8(NULL, config->arguments, "MASKVAL"); // Value to mask
     int sample = psMetadataLookupS32(NULL, config->arguments, "SAMPLE"); // Size of sample for statistics
     bool chipStats = psMetadataLookupBool(&mdok, config->arguments, "MASK.CHIPSTATS"); // Statistics on chip?
@@ -35,9 +34,22 @@
     pmMaskIdentifyMode maskMode = psMetadataLookupS32(NULL, config->arguments, "MASK.MODE"); // Mode for identifying bad pixels
     int maskGrow = psMetadataLookupS32(NULL, config->arguments, "MASK.GROW"); // Radius to grow mask
-    psMaskType maskGrowVal = psMetadataLookupU8(NULL, config->arguments, "MASK.GROWVAL"); // Value for grown mask
 
     bool smoothSuspect = psMetadataLookupBool(&mdok, config->arguments, "MASK.SMOOTH.SUSPECT"); // Radius to grow mask
     float smoothScale = psMetadataLookupF32(&mdok, config->arguments, "MASK.SMOOTH.SCALE"); // Radius to grow mask
 
+    psMaskType markVal;
+    psMaskType maskValRaw;
+    if (!pmConfigMaskSetBits (&maskValRaw, &markVal, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    char *maskOutName = psMetadataLookupStr (&mdok, config->arguments, "MASK.SET.VALUE");
+    psMaskType maskValOut = pmConfigMaskGet (maskOutName, config);
+    if (!maskValOut) {
+	psError (PS_ERR_UNKNOWN, true, "Undefined output mask bit value");
+	return false;
+    }
+    
     psStats *statistics = psStatsAlloc(meanStat | stdevStat); // Statistics for background
 
@@ -137,9 +149,7 @@
                 int x = pixel % numCols;
                 int y = pixel / numCols;
-                if ((mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal)) ||
-                    !isfinite(image->data.F32[y][x]) ||
-                    (outMask && (outMask->data.PS_TYPE_MASK_DATA[y][x] & maskVal))) {
-                    continue;
-                }
+                if (mask && (mask->data.PS_TYPE_MASK_DATA[y][x] & maskValRaw)) continue;
+		if (outMask && (outMask->data.PS_TYPE_MASK_DATA[y][x] & maskValOut)) continue;
+		if (!isfinite(image->data.F32[y][x])) continue;
 
                 values->data.F32[valueIndex++] = image->data.F32[y][x];
@@ -155,6 +165,10 @@
                 }
 
-                if (!pmMaskFlagSuspectPixels(outRO, readout, psStatsGetValue(statistics, meanStat),
-                                             psStatsGetValue(statistics, stdevStat), maskSuspect, maskVal)) {
+		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);
@@ -189,8 +203,6 @@
 
                 pmHDU *hdu = pmHDUFromCell(inCell); // HDU for cell
-                if (!hdu || hdu->blankPHU) {
-                    // No data here
-                    continue;
-                }
+                if (!hdu || hdu->blankPHU) continue;
+
                 pmReadout *readout = inCell->readouts->data[0]; // Readout of interest
 
@@ -198,6 +210,8 @@
                 pmReadout *outRO = pmFPAfileThisReadout(config->files, inView, "PPMERGE.OUTPUT.MASK");
 
-                if (!pmMaskFlagSuspectPixels(outRO, readout, psStatsGetValue(statistics, meanStat),
-                                             psStatsGetValue(statistics, stdevStat), maskSuspect, maskVal)) {
+		float mean = psStatsGetValue(statistics, meanStat);
+		float stdev = psStatsGetValue(statistics, stdevStat);
+
+		if (!pmMaskFlagSuspectPixels(outRO, readout, mean, stdev, maskSuspect, maskValRaw)) {
                     psError(PS_ERR_UNKNOWN, false, "Unable to find suspect values in file %d", i);
                     goto MERGE_MASK_ERROR;
@@ -229,12 +243,9 @@
     while ((outCell = pmFPAviewNextCell(outView, outFPA, 1))) {
 
-	// skipp inactive cells
+	// skip inactive cells
 	if (!outCell->process) continue;
 
         pmHDU *hdu = pmHDUFromCell(outCell); // HDU for cell
-        if (!hdu || hdu->blankPHU) {
-            // No data here
-            continue;
-        }
+        if (!hdu || hdu->blankPHU) continue;
 
         psTrace("ppMerge", 1, "Getting bad pixels for chip %d cell %d", outView->chip, outView->cell);
@@ -250,5 +261,6 @@
 	}
 
-        if (!pmMaskIdentifyBadPixels(outRO, maskVal, maskBad, maskMode)) {
+	// set the bad pixels to the value 'maskVal'
+        if (!pmMaskIdentifyBadPixels(outRO, maskValOut, maskBad, maskMode)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to mask bad pixels");
             goto MERGE_MASK_ERROR;
@@ -274,6 +286,6 @@
         }
 
-        if (maskGrowVal > 0) {
-            psImage *grown = psImageGrowMask(NULL, outRO->mask, maskVal, maskGrow, maskGrowVal); // Grown mask
+        if (maskGrow > 0) {
+            psImage *grown = psImageGrowMask(NULL, outRO->mask, maskValOut, maskGrow, maskValOut); // Grown mask
             psFree(outRO->mask);
             outRO->mask = grown;
@@ -307,6 +319,5 @@
             outRO->image = psImageAlloc(outRO->mask->numCols, outRO->mask->numRows, PS_TYPE_F32);
             psImageInit(outRO->image, 1.0);
-            if (!ppStatsFPA(stats, outRO->parent->parent->parent, outView,
-                            maskVal | pmConfigMask("BLANK", config), config)) {
+            if (!ppStatsFPA(stats, outRO->parent->parent->parent, outView, maskValOut, config)) {
                 psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to generate stats for image.");
                 psFree(outRO);
@@ -337,8 +348,4 @@
 }
 
-
-
-
-
 bool ppMergeMask(pmConfig *config)
 {
@@ -381,4 +388,7 @@
         goto PPMERGE_MASK_ERROR;
     }
+
+    // XXX this function should use pmConfigMaskReadHeader () to get the named values defined
+    // for the input masks.
 
     psString outName = ppMergeOutputFile(config); // Name of output file
@@ -414,4 +424,7 @@
 		psListAdd(inChips, PS_LIST_TAIL, chip);
 	    }
+
+	    // XXX I need to call pmConfigMaskWriteHeader for the PHU somewhere, after it is created!
+
 	    if (!pmConceptsAverageChips(outChip, inChips, true)) {
 		psError(PS_ERR_UNKNOWN, false, "Unable to average Chip concepts.");
Index: /trunk/ppMerge/src/ppMergeScaleZero.c
===================================================================
--- /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 18557)
+++ /trunk/ppMerge/src/ppMergeScaleZero.c	(revision 18558)
@@ -21,6 +21,7 @@
     psStatsOptions meanStat = psMetadataLookupS32(NULL, config->arguments, "MEAN"); // Statistic for mean
     psStatsOptions stdevStat = psMetadataLookupS32(NULL, config->arguments, "STDEV"); // Statistic for stdev
-    psMaskType maskVal = psMetadataLookupU8(NULL, config->arguments, "MASKVAL"); // Value to mask
     int shutterSize = psMetadataLookupS32(NULL, config->arguments, "SHUTTER.SIZE"); // Size of shutter region
+
+    psMaskType maskVal = pmConfigMaskGet("MASK.VALUE", config); // Value to mask
 
     psVector *gains = NULL;             // Gains for each cell
Index: /trunk/ppStats/src/ppStatsFPA.c
===================================================================
--- /trunk/ppStats/src/ppStatsFPA.c	(revision 18557)
+++ /trunk/ppStats/src/ppStatsFPA.c	(revision 18558)
@@ -21,8 +21,6 @@
     }
 
-    // Override recipe mask value if one is provided
-    if (maskVal != 0) {
-        data->maskVal = maskVal;
-    }
+    // Override recipe mask value
+    data->maskVal = maskVal;
 
     if (data->fpa) {
Index: /trunk/ppStats/src/ppStatsMetadata.c
===================================================================
--- /trunk/ppStats/src/ppStatsMetadata.c	(revision 18557)
+++ /trunk/ppStats/src/ppStatsMetadata.c	(revision 18558)
@@ -29,8 +29,6 @@
     data->doStats = false;
 
-    // Override recipe mask value if one is provided
-    if (maskVal != 0) {
-        data->maskVal = maskVal;
-    }
+    // Override recipe mask value
+    data->maskVal = maskVal;
 
     if (data->fpa) {
Index: /trunk/ppStats/src/ppStatsPixels.c
===================================================================
--- /trunk/ppStats/src/ppStatsPixels.c	(revision 18557)
+++ /trunk/ppStats/src/ppStatsPixels.c	(revision 18558)
@@ -28,8 +28,6 @@
     data->concepts = psListAlloc(NULL);
 
-    // Override recipe mask value if one is provided
-    if (maskVal != 0) {
-        data->maskVal = maskVal;
-    }
+    // Override recipe mask value 
+    data->maskVal = maskVal;
 
     if (data->fpa) {
Index: /trunk/ppStats/src/ppStatsSetupFromRecipe.c
===================================================================
--- /trunk/ppStats/src/ppStatsSetupFromRecipe.c	(revision 18557)
+++ /trunk/ppStats/src/ppStatsSetupFromRecipe.c	(revision 18558)
@@ -127,8 +127,9 @@
     }
 
+    // set the mask value used for stand-alone analyses.
     if (data->maskVal == 0) {
         const char *names = psMetadataLookupStr(&mdok, recipe, "MASKVAL"); // Names for mask value
         if (mdok) {
-            data->maskVal = pmConfigMask(names, config);
+            data->maskVal = pmConfigMaskGet(names, config);
         } else {
             psWarning("MASKVAL in recipe is not of type STR --- retaining default.\n");
Index: /trunk/pswarp/src/Makefile.am
===================================================================
--- /trunk/pswarp/src/Makefile.am	(revision 18557)
+++ /trunk/pswarp/src/Makefile.am	(revision 18558)
@@ -15,4 +15,5 @@
 	pswarpParseCamera.c		\
 	pswarpPixelFraction.c		\
+	pswarpSetMaskBits.c		\
 	pswarpTransformReadout_Opt.c	\
 	pswarpVersion.c            
Index: /trunk/pswarp/src/pswarp.h
===================================================================
--- /trunk/pswarp/src/pswarp.h	(revision 18557)
+++ /trunk/pswarp/src/pswarp.h	(revision 18558)
@@ -38,4 +38,5 @@
 pmConfig *pswarpArguments (int argc, char **argv);
 bool pswarpOptions(pmConfig *config);
+bool pswarpSetMaskBits (pmConfig *config);
 bool pswarpParseCamera (pmConfig *config);
 bool pswarpDefine (pmConfig *config);
Index: /trunk/pswarp/src/pswarpArguments.c
===================================================================
--- /trunk/pswarp/src/pswarpArguments.c	(revision 18557)
+++ /trunk/pswarp/src/pswarpArguments.c	(revision 18558)
@@ -109,28 +109,4 @@
     }
 
-    // Get mask parameters
-    psMaskType maskIn, maskPoor, maskBad; // Mask values for input, "poor" and "bad" pixels
-
-    psString maskNames = psMetadataLookupStr(&status, recipe, "MASK.IN");
-    if (!status) {
-        maskIn = 0x00;
-        psWarning("MASK.IN is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskIn);
-    }
-    maskIn = pmConfigMask(maskNames, config); // Mask for input data
-
-    maskNames = psMetadataLookupStr(&status, recipe, "MASK.POOR");
-    if (!status) {
-        maskPoor = 0x00;
-        psWarning("MASK.POOR is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskPoor);
-    }
-    maskPoor = pmConfigMask(maskNames, config); // Mask for "poor" warped data
-
-    maskNames = psMetadataLookupStr(&status, recipe, "MASK.BAD");
-    if (!status) {
-        maskBad = 0x00;
-        psWarning("MASK.BAD is not set in the %s recipe --- defaulting to %x.", PSWARP_RECIPE, maskBad);
-    }
-    maskBad = pmConfigMask(maskNames, config); // Mask for bad warped data
-
     float poorFrac = psMetadataLookupF32(&status, recipe, "POOR.FRAC"); // Frac of bad flux for a "poor"
     if (!status) {
@@ -152,10 +128,4 @@
     psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INTERPOLATION.MODE", 0,
                      "Interpolation mode", interpolationMode);
-    psMetadataAddU8(config->arguments, PS_LIST_TAIL, "MASK.IN", 0,
-                    "Mask for input data", maskIn);
-    psMetadataAddU8(config->arguments, PS_LIST_TAIL, "MASK.POOR", 0,
-                    "Mask for poor warped data", maskPoor);
-    psMetadataAddU8(config->arguments, PS_LIST_TAIL, "MASK.BAD", 0,
-                    "Mask for bad warped data", maskBad);
     psMetadataAddF32(config->arguments, PS_LIST_TAIL, "POOR.FRAC", 0,
                      "Fraction of bad flux for a pixel to be marked as poor", poorFrac);
Index: /trunk/pswarp/src/pswarpLoop.c
===================================================================
--- /trunk/pswarp/src/pswarpLoop.c	(revision 18557)
+++ /trunk/pswarp/src/pswarpLoop.c	(revision 18558)
@@ -64,7 +64,16 @@
 bool pswarpLoop(pmConfig *config)
 {
-
-    psMaskType maskPoor = psMetadataLookupU8(NULL, config->arguments, "MASK.POOR"); // Mask for "poor" data
-    psMaskType maskBad = psMetadataLookupU8(NULL, config->arguments, "MASK.BAD"); // Mask for bad data
+    bool status; 
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskValue = psMetadataLookupU8(&status, recipe, "MASK.OUTPUT"); 
+    psAssert (status, "MASK.OUTPUT was not defined");
 
     // select the input data sources
@@ -333,5 +342,5 @@
     // Perform statistics on the output image
     if (stats) {
-        if (!ppStatsFPA(stats, output->parent->parent->parent, view, maskBad | maskPoor, config)) {
+        if (!ppStatsFPA(stats, output->parent->parent->parent, view, maskValue, config)) {
             psWarning("Unable to perform statistics on warped image.");
         }
Index: /trunk/pswarp/src/pswarpParseCamera.c
===================================================================
--- /trunk/pswarp/src/pswarpParseCamera.c	(revision 18557)
+++ /trunk/pswarp/src/pswarpParseCamera.c	(revision 18558)
@@ -37,4 +37,10 @@
     if (!inMask) {
         psLogMsg ("pswarp", 3, "no mask supplied\n");
+    }
+    
+    // loading the mask here should have invoked pmConfigMaskReadHeader()
+    if (!pswarpSetMaskBits (config)) {
+        psError(PS_ERR_IO, false, "failed to set mask bits");
+        return NULL;
     }
 
Index: /trunk/pswarp/src/pswarpPixelFraction.c
===================================================================
--- /trunk/pswarp/src/pswarpPixelFraction.c	(revision 18557)
+++ /trunk/pswarp/src/pswarpPixelFraction.c	(revision 18558)
@@ -28,8 +28,18 @@
     PS_ASSERT_METADATA_NON_NULL(config->arguments, false);
 
+    bool status; 
+
     float minFrac = psMetadataLookupF32(NULL, config->arguments, "ACCEPT.FRAC"); // Minimum fraction
-    psMaskType maskPoor = psMetadataLookupU8(NULL, config->arguments, "MASK.POOR"); // Mask for "poor" data
-    psMaskType maskBad = psMetadataLookupU8(NULL, config->arguments, "MASK.BAD"); // Mask for bad data
-    psMaskType maskVal = maskPoor | maskBad; // Mask to apply
+
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskValue = psMetadataLookupU8(&status, recipe, "MASK.OUTPUT"); 
+    psAssert (status, "MASK.OUTPUT was not defined");
 
     psImage *image = readout->image;    // Image of interest
@@ -45,5 +55,5 @@
     for (int y = 0; y < numRows; y++) {
         for (int x = 0; x < numCols; x++) {
-            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
+            if (mask->data.PS_TYPE_MASK_DATA[y][x] & maskValue) {
                 numBad++;
             } else {
Index: /trunk/pswarp/src/pswarpSetMaskBits.c
===================================================================
--- /trunk/pswarp/src/pswarpSetMaskBits.c	(revision 18558)
+++ /trunk/pswarp/src/pswarpSetMaskBits.c	(revision 18558)
@@ -0,0 +1,83 @@
+# include "pswarp.h"
+
+// This function is called by the stand-alone pswarp program to set the mask values in the
+// config file.  It sets the named mask values MASK.PSPHOT and MARK.PSPHOT in the PSPHOT
+// recipe.  Functions or programs which call psphotReadout as a library function must set these
+// named mask values in the PSPHOT recipe on their own.  This function should only be called
+// after the first header of the input mask image has been loaded and the named mask bits
+// updated in the config metadata.
+
+bool pswarpSetMaskBits (pmConfig *config) {
+
+    psMaskType maskIn = 0x00;			// mask for the input image
+    psMaskType markIn = 0x00;			// mark for the input image
+    psMaskType maskOut = 0x00;			// mask for the output image
+    psMaskType markOut = 0x00;			// mark for the output image
+
+    // this function sets the required single-image mask bits
+    if (!pmConfigMaskSetBits (&maskIn, &markIn, config)) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the mask bit values");
+	return false;
+    }
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType badMask = pmConfigMaskGet("BAD.WARP", config); 
+    if (!badMask) {
+	badMask = 0x01;
+	pmConfigMaskSet (config, "BAD.WARP", badMask);
+    }
+    maskOut |= badMask;
+
+    // mask for non-linear flat regions (default to DETECTOR if not defined)
+    psMaskType poorMask = pmConfigMaskGet("POOR.WARP", config); 
+    if (!poorMask) {
+	poorMask = 0x02;
+	pmConfigMaskSet (config, "POOR.WARP", poorMask);
+    }
+    maskOut |= poorMask;
+
+    // search for an unset bit to use for MARK:
+    markOut = 0x80;
+
+    int nBits = sizeof(psMaskType) * 8;
+    for (int i = 0; !markOut && (i < nBits); i++) {
+	if (maskOut & markOut) {
+	    markOut >>= 1;
+	} else {
+	    markOut = markOut;
+	}
+    }
+
+    if (!markOut) {
+	psError (PS_ERR_UNKNOWN, true, "Unable to define the MARK bit mask: all bits taken!");
+	return false;
+    }
+
+    // update the pswarp recipe
+    psMetadata *warpRecipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!warpRecipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // set maskOut and markOut in the psphot recipe
+    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.INPUT",  PS_META_REPLACE, "user-defined mask", maskIn);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.INPUT",  PS_META_REPLACE, "user-defined mask", markIn);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MASK.OUTPUT", PS_META_REPLACE, "user-defined mask", maskOut);
+    psMetadataAddU8 (warpRecipe, PS_LIST_TAIL, "MARK.OUTPUT", PS_META_REPLACE, "user-defined mask", markOut);
+
+    // update the psphot recipe
+    psMetadata *psphotRecipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
+    if (!psphotRecipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
+        return false;
+    }
+
+    // set maskOut and markOut in the psphot recipe
+    // NOTE: psphot works on the output images, not input images, so set the MARK and MASK correctly here
+    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MARK.PSPHOT", PS_META_REPLACE, "user-defined mask", markOut);
+    psMetadataAddU8 (psphotRecipe, PS_LIST_TAIL, "MASK.PSPHOT", PS_META_REPLACE, "user-defined mask", maskOut);
+
+    return true;
+}
Index: /trunk/pswarp/src/pswarpTransformReadout_Opt.c
===================================================================
--- /trunk/pswarp/src/pswarpTransformReadout_Opt.c	(revision 18557)
+++ /trunk/pswarp/src/pswarpTransformReadout_Opt.c	(revision 18558)
@@ -17,7 +17,17 @@
     psImageInterpolateMode interpolationMode = psMetadataLookupS32(NULL, config->arguments,
                                                                    "INTERPOLATION.MODE");
-    psMaskType maskIn = psMetadataLookupU8(NULL, config->arguments, "MASK.IN"); // Mask for input data
-    psMaskType maskPoor = psMetadataLookupU8(NULL, config->arguments, "MASK.POOR"); // Mask for "poor" data
-    psMaskType maskBad = psMetadataLookupU8(NULL, config->arguments, "MASK.BAD"); // Mask for bad data
+    // load the recipe
+    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSWARP_RECIPE);
+    if (!recipe) {
+        psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSWARP_RECIPE);
+        return false;
+    }
+
+    // output mask bits
+    psMaskType maskIn   = psMetadataLookupU8(&mdok, recipe, "MASK.INPUT"); 
+    psMaskType maskPoor = pmConfigMaskGet("POOR.WARP", config); 
+    psMaskType maskBad  = pmConfigMaskGet("BAD.WARP", config); 
+    psAssert (mdok, "MASK.INPUT was not defined");
+
     float poorFrac = psMetadataLookupF32(NULL, config->arguments, "POOR.FRAC"); // Flux fraction for "poor"
 
@@ -62,5 +72,5 @@
 
     // Interpolation options
-    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, inImage,
+    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(interpolationMode, inImage, 
                                                                        inVar, inMask, maskIn, NAN, NAN,
                                                                        maskBad, maskPoor, poorFrac);
