Index: /trunk/ppStack/src/ppStackLoop.c
===================================================================
--- /trunk/ppStack/src/ppStackLoop.c	(revision 18590)
+++ /trunk/ppStack/src/ppStackLoop.c	(revision 18591)
@@ -204,5 +204,4 @@
 
     bool mdok;                          // Status of MD lookup
-    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
     bool tempDelete = psMetadataLookupBool(&mdok, config->arguments, "TEMP.DELETE"); // Delete temporary files?
     const char *tempImage = psMetadataLookupStr(NULL, config->arguments, "TEMP.IMAGE"); // Suffix for temporary images
@@ -242,4 +241,9 @@
     psMetadata *ppsub = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe
     int overlap = 2 * psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Overlap by kernel size between consecutive scans
+
+    if (!pmConfigMaskSetBits(NULL, NULL, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine mask value.");
+        return false;
+    }
 
     memDump("start");
@@ -790,5 +794,5 @@
         if (stats) {
             psTrace("ppStack", 1, "Gathering statistics on stacked image....\n");
-            ppStatsFPA(stats, outCell->parent->parent, view, maskBlank, config);
+            ppStatsFPA(stats, outCell->parent->parent, view, pmConfigMaskGet("BLANK", config), config);
         }
 
Index: /trunk/ppStack/src/ppStackMatch.c
===================================================================
--- /trunk/ppStack/src/ppStackMatch.c	(revision 18590)
+++ /trunk/ppStack/src/ppStackMatch.c	(revision 18591)
@@ -30,5 +30,8 @@
     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe
     int size = psMetadataLookupS32(NULL, recipe, "KERNEL.SIZE"); // Kernel half-size
-    psMaskType maskBad = pmConfigMaskGet(psMetadataLookupStr(NULL, recipe, "MASK.BAD"), config); // Value to mask
+
+    psMaskType maskIn = pmConfigMaskGet("MASK.VALUE", config); // Bits to mask going in to pmSubtractionMatch
+    psMaskType maskOut = pmConfigMaskGet("BLANK", config); // Bits to mask after pmSubtractionMatch
+
     bool mdok;                          // Status of MD lookup
     bool renorm = psMetadataLookupBool(&mdok, config->arguments, "RENORM"); // Renormalise variances?
@@ -41,5 +44,5 @@
     float penalty = psMetadataLookupF32(NULL, config->arguments, "PENALTY"); // Penalty for wideness
 
-    if (!pmReadoutMaskNonfinite(readout, maskBad)) {
+    if (!pmReadoutMaskNonfinite(readout, maskIn)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in readout.");
         return false;
@@ -64,6 +67,4 @@
         int ringsOrder = psMetadataLookupS32(NULL, recipe, "RINGS.ORDER"); // RINGS polynomial order
         int binning = psMetadataLookupS32(NULL, recipe, "SPAM.BINNING"); // Binning for SPAM kernel
-        psMaskType maskBlank = pmConfigMaskGet(psMetadataLookupStr(NULL, recipe, "MASK.BLANK"),
-                                            config); // Mask for blank reg.
         float badFrac = psMetadataLookupF32(NULL, recipe, "BADFRAC"); // Maximum bad fraction
         bool optimum = psMetadataLookupBool(&mdok, recipe, "OPTIMUM"); // Derive optimum parameters?
@@ -114,5 +115,5 @@
                                 sources, stampsName, type, size, order, widths, orders, inner, ringsOrder,
                                 binning, penalty, optimum, optWidths, optOrder, optThresh, iter, rej,
-                                maskBad, maskBlank, badFrac, PM_SUBTRACTION_MODE_1)) {
+                                maskIn, maskOut, badFrac, PM_SUBTRACTION_MODE_1)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
             psFree(fake);
@@ -200,5 +201,5 @@
     if (renorm) {
         psLogMsg("ppStack", PS_LOG_INFO, "Renormalising variance map.");
-        if (!pmReadoutWeightRenorm(readout, maskBad, renormMean, renormStdev, renormWidth, rng)) {
+        if (!pmReadoutWeightRenorm(readout, maskOut, renormMean, renormStdev, renormWidth, rng)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to renormalise variances.");
             psFree(output);
@@ -209,5 +210,5 @@
     // Ensure the background value is zero
     psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for background
-    if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskBad, rng)) {
+    if (!psImageBackground(bg, NULL, readout->image, readout->mask, maskOut, rng)) {
         psWarning("Can't measure background for image.");
         psErrorClear();
Index: /trunk/ppStack/src/ppStackReadout.c
===================================================================
--- /trunk/ppStack/src/ppStackReadout.c	(revision 18590)
+++ /trunk/ppStack/src/ppStackReadout.c	(revision 18591)
@@ -32,7 +32,5 @@
     int iter = psMetadataLookupS32(NULL, config->arguments, "ITER"); // Rejection iterations
     float combineRej = psMetadataLookupF32(NULL, config->arguments, "COMBINE.REJ"); // Combination threshold
-    psMaskType maskBad = psMetadataLookupU8(NULL, config->arguments, "MASK.BAD"); // Value to mask
-    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
-//    float threshold = psMetadataLookupF32(NULL, config->arguments, "THRESHOLD.MASK"); // Threshold for mask deconvolution
+    psMaskType maskVal = pmConfigMaskGet("BLANK", config); // Value to mask
     bool useVariance = psMetadataLookupBool(&mdok, config->arguments, "VARIANCE"); // Use variance for rejection?
     bool safe = psMetadataLookupBool(&mdok, config->arguments, "SAFE"); // Play safe when combining small numbers of pixels?
@@ -67,5 +65,5 @@
     }
 
-    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, kernelSize, iter, combineRej, true,
+    if (!pmStackCombine(outRO, stack, maskVal, maskVal, kernelSize, iter, combineRej, true,
                         useVariance, safe)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts with rejection.");
@@ -93,5 +91,5 @@
                                             psRegionSet(0, outRO->image->numCols - 1,
                                                         0, outRO->image->numRows - 1),
-                                            maskBlank);
+                                            maskVal);
         psString name = NULL;           // Name of image
         psStringAppend(&name, "inspect_%03d_%03d.fits", sectionNum, i);
@@ -140,6 +138,5 @@
     // Get the recipe values
     bool mdok;                          // Status of MD lookup
-    psMaskType maskBad = psMetadataLookupU8(NULL, config->arguments, "MASK.BAD"); // Value to mask
-    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
+    psMaskType maskVal = pmConfigMaskGet("BLANK", config); // Value to mask
     bool useVariance = psMetadataLookupBool(&mdok, config->arguments, "VARIANCE"); // Use variance for rejection?
 
@@ -208,5 +205,5 @@
                                              psRegionSet(0, outRO->image->numCols - 1,
                                                          0, outRO->image->numRows - 1),
-                                             maskBlank);
+                                             maskVal);
             psString name = NULL;           // Name of image
             psStringAppend(&name, "reject_%03d.fits", i);
@@ -220,5 +217,5 @@
 #endif
 
-    if (!pmStackCombine(outRO, stack, maskBad, maskBlank, 0, 0, NAN, numGood != num, useVariance, false)) {
+    if (!pmStackCombine(outRO, stack, maskVal, maskVal, 0, 0, NAN, numGood != num, useVariance, false)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to combine input readouts.");
         psFree(fpaList);
Index: /trunk/ppSub/src/ppSubLoop.c
===================================================================
--- /trunk/ppSub/src/ppSubLoop.c	(revision 18590)
+++ /trunk/ppSub/src/ppSubLoop.c	(revision 18591)
@@ -14,9 +14,4 @@
 bool ppSubLoop(pmConfig *config)
 {
-    // Value to mask
-    psMaskType maskBlank = pmConfigMaskGet(psMetadataLookupStr(NULL, config->arguments, "MASK.BLANK"), config) |
-        pmConfigMaskGet(psMetadataLookupStr(NULL, config->arguments, "MASK.BAD"),
-                     config); // Mask for subtracted image
-
     bool mdok;                          // Status of MD lookup
     const char *statsName = psMetadataLookupStr(&mdok, config->arguments, "STATS"); // Filename for statistics
@@ -34,4 +29,9 @@
         }
         psFree(resolved);
+    }
+
+    if (!pmConfigMaskSetBits(NULL, NULL, config)) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to determine mask value.");
+        return false;
     }
 
@@ -147,5 +147,5 @@
                     return false;
                 }
-                ppStatsFPA(stats, output->fpa, view, maskBlank, config);
+                ppStatsFPA(stats, output->fpa, view, pmConfigMaskGet("BLANK", config), config);
             }
 
Index: /trunk/ppSub/src/ppSubReadout.c
===================================================================
--- /trunk/ppSub/src/ppSubReadout.c	(revision 18590)
+++ /trunk/ppSub/src/ppSubReadout.c	(revision 18591)
@@ -77,8 +77,6 @@
     int binning = psMetadataLookupS32(NULL, config->arguments, "SPAM.BINNING"); // Binning for SPAM kernel
     float penalty = psMetadataLookupF32(NULL, config->arguments, "PENALTY"); // Penalty for wideness
-    psMaskType maskBad = pmConfigMaskGet(psMetadataLookupStr(NULL, config->arguments, "MASK.BAD"),
-                                    config); // Value to mask
-    psMaskType maskBlank = pmConfigMaskGet(psMetadataLookupStr(NULL, config->arguments, "MASK.BLANK"),
-                                        config); // Mask for blank reg.
+    psMaskType maskIn = pmConfigMaskGet("MASK.VALUE", config); // Bits to mask going in to pmSubtractionMatch
+    psMaskType maskOut = pmConfigMaskGet("BLANK", config); // Bits to mask after pmSubtractionMatch
     float badFrac = psMetadataLookupF32(NULL, config->arguments, "BADFRAC"); // Maximum bad fraction
     const char *stampsName = psMetadataLookupStr(&mdok, config->arguments, "STAMPS"); // Filename for stamps
@@ -115,9 +113,9 @@
     }
 
-    if (!pmReadoutMaskNonfinite(inRO, maskBad)) {
+    if (!pmReadoutMaskNonfinite(inRO, maskIn)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in input.");
         return false;
     }
-    if (!pmReadoutMaskNonfinite(refRO, maskBad)) {
+    if (!pmReadoutMaskNonfinite(refRO, maskIn)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to mask non-finite pixels in reference.");
         return false;
@@ -136,6 +134,6 @@
     if (!pmSubtractionMatch(inConv, refConv, inRO, refRO, footprint, regionSize, spacing, threshold, sources,
                             stampsName, type, size, order, widths, orders, inner, ringsOrder, binning,
-                            penalty, optimum, optWidths, optOrder, optThresh, iter, rej, maskBad,
-                            maskBlank, badFrac, mode)) {
+                            penalty, optimum, optWidths, optOrder, optThresh, iter, rej, maskIn,
+                            maskOut, badFrac, mode)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to match images.");
         psFree(inConv);
@@ -200,5 +198,5 @@
 #ifdef TESTING
     {
-        pmReadoutMaskApply(minuend, maskBlank);
+        pmReadoutMaskApply(minuend, maskOut);
         psFits *fits = psFitsOpen("minuend.fits", "w");
         psFitsWriteImage(fits, NULL, minuend->image, 0, NULL);
@@ -206,5 +204,5 @@
     }
     {
-        pmReadoutMaskApply(subtrahend, maskBlank);
+        pmReadoutMaskApply(subtrahend, maskOut);
         psFits *fits = psFitsOpen("subtrahend.fits", "w");
         psFitsWriteImage(fits, NULL, subtrahend->image, 0, NULL);
@@ -278,5 +276,5 @@
     outRO->data_exists = outCell->data_exists = outCell->parent->data_exists = true;
 
-    pmReadoutMaskApply(outRO, maskBlank);
+    pmReadoutMaskApply(outRO, maskOut);
 
     psFree(inConv);
@@ -286,5 +284,5 @@
     for (int y = 0; y < outRO->image->numRows; y++) {
         for (int x = 0; x < outRO->image->numCols; x++) {
-            if (isnan(outRO->image->data.F32[y][x]) && !(outRO->mask->data.U8[y][x] & maskBlank)) {
+            if (isnan(outRO->image->data.F32[y][x]) && !(outRO->mask->data.U8[y][x] & maskOut)) {
                 printf("Unmasked NAN at %d %d --> %d\n", x, y, outRO->mask->data.U8[y][x]);
             }
@@ -301,5 +299,5 @@
     if (renorm) {
         psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
-        if (!pmReadoutWeightRenorm(outRO, maskBlank, PS_STAT_ROBUST_MEDIAN, PS_STAT_ROBUST_STDEV,
+        if (!pmReadoutWeightRenorm(outRO, maskOut, PS_STAT_ROBUST_MEDIAN, PS_STAT_ROBUST_STDEV,
                                    renormWidth, rng)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to renormalise weights for photometry.");
Index: /trunk/ppSub/test/fake.c
===================================================================
--- /trunk/ppSub/test/fake.c	(revision 18590)
+++ /trunk/ppSub/test/fake.c	(revision 18591)
@@ -7,8 +7,8 @@
 
 // PSF for images
-#define X_AXIS_1 2.0                    // Length of x axis (FWHM) for image 1
+#define X_AXIS_1 5.0                    // Length of x axis (FWHM) for image 1
 #define Y_AXIS_1 3.0                    // Length of y axis (FWHM) for image 1
-#define X_AXIS_2 3.0                    // Length of x axis (FWHM) for image 1
-#define Y_AXIS_2 2.0                    // Length of y axis (FWHM) for image 1
+#define X_AXIS_2 5.0                    // Length of x axis (FWHM) for image 1
+#define Y_AXIS_2 5.0                    // Length of y axis (FWHM) for image 1
 
 // Image parameters
