Index: /trunk/ppSim/src/Makefile.am
===================================================================
--- /trunk/ppSim/src/Makefile.am	(revision 42942)
+++ /trunk/ppSim/src/Makefile.am	(revision 42943)
@@ -38,4 +38,5 @@
 	ppSimRandomGaussian.c	  \
 	ppSimBadPixels.c          \
+	ppSimBadRegions.c         \
 	ppSimBadCTE.c             \
 	ppSimVersion.c
Index: /trunk/ppSim/src/ppSim.h
===================================================================
--- /trunk/ppSim/src/ppSim.h	(revision 42942)
+++ /trunk/ppSim/src/ppSim.h	(revision 42943)
@@ -151,4 +151,10 @@
     );
 
+/// Add rectuangular bad regions to an image
+bool ppSimBadRegions(pmReadout *readout, ///< Readout for which to generate bad pixels
+                    const pmConfig *config, ///< Configuration
+                    psRandom *rng       ///< Random number generator
+    );
+
 float ppSimStarSkyNoise (float skySigma, float seeingSigma);
 float ppSimStarPeakToFlux (float peak, float seeingSigma);
Index: /trunk/ppSim/src/ppSimBadRegions.c
===================================================================
--- /trunk/ppSim/src/ppSimBadRegions.c	(revision 42943)
+++ /trunk/ppSim/src/ppSimBadRegions.c	(revision 42943)
@@ -0,0 +1,65 @@
+# include "ppSim.h"
+
+// generate a set of bad areas.  Each bad area will be a rectangle with a range
+// of possible sizes. here are the relevant parameters:
+// BAD.REGIONS.NMAX
+// BAD.REGIONS.DXMIN, BAD.REGIONS.DXMAX
+// BAD.REGIONS.DYMIN, BAD.REGIONS.DYMAX
+
+# define GET_INT_ARG(VAR,NAME)				\
+  int VAR = psMetadataLookupS32(&mdok, recipe, NAME);	\
+  if (!mdok) {							      \
+    psError(PS_ERR_BAD_PARAMETER_VALUE, true, "%s not set.", NAME);   \
+    return false;						      \
+  }
+
+bool ppSimBadRegions(pmReadout *readout, const pmConfig *config, psRandom *rng)
+{
+    PS_ASSERT_PTR_NON_NULL(readout, false);
+    PS_ASSERT_IMAGE_NON_NULL(readout->image, false);
+    PS_ASSERT_PTR_NON_NULL(readout->parent, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
+    if (!recipe) {
+        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSIM_RECIPE);
+        return false;
+    }
+
+    GET_INT_ARG(nMax, "BAD.REGIONS.NMAX");
+    if (!nMax) return true; // skip if none are requested
+
+    GET_INT_ARG(dXmin, "BAD.REGIONS.DXMIN");
+    GET_INT_ARG(dXmax, "BAD.REGIONS.DXMAX");
+    GET_INT_ARG(dYmin, "BAD.REGIONS.DYMIN");
+    GET_INT_ARG(dYmax, "BAD.REGIONS.DYMAX");
+
+    psImage *image = readout->image;    // Image of interest
+    int numCols = image->numCols;
+    int numRows = image->numRows;
+
+    // add 1 to nMax so we can read nMax
+    int nMaxUse = (nMax + 1)*psRandomUniform(rng);
+
+    for (int n = 0; n < nMaxUse; n++) {
+
+      int dX = (dXmax - dXmin)*psRandomUniform(rng) + dXmin;
+      int dY = (dYmax - dYmin)*psRandomUniform(rng) + dYmin;
+      
+      // choose a starting corner (0 to numCols - dX), (0 to numCols - dY)
+      int Xo = (numCols - dX)*psRandomUniform(rng);
+      int Yo = (numRows - dY)*psRandomUniform(rng);
+
+      int Xe = MIN (Xo + dX, numCols);
+      int Ye = MIN (Yo + dY, numRows);
+
+      // now set the bad region to NAN
+      for (int x = Xo; x < Xe; x++) {
+	for (int y = Yo; y < Ye; y++) {
+	  image->data.F32[y][x] = NAN;
+        }
+      }
+    }
+    return true;
+}
Index: /trunk/ppSim/src/ppSimLoop.c
===================================================================
--- /trunk/ppSim/src/ppSimLoop.c	(revision 42942)
+++ /trunk/ppSim/src/ppSimLoop.c	(revision 42943)
@@ -173,4 +173,6 @@
                 if (!ppSimBadPixels(readout, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding bad pixels");
 
+                if (!ppSimBadRegions(readout, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding bad regions");
+
                 if (!ppSimAddOverscan (readout, config, biasCols, biasRows, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding overscan region");
                 psFree(biasRows);
