Index: branches/pap/ppImage/src/ppImageDetrendReadout.c
===================================================================
--- branches/pap/ppImage/src/ppImageDetrendReadout.c	(revision 23948)
+++ branches/pap/ppImage/src/ppImageDetrendReadout.c	(revision 25027)
@@ -17,6 +17,6 @@
     // Masking on the basis of pixel value needs to be done before anything else, so the values are pristine.
     if (options->doMaskBuild) {
-	psImageMaskType satMask = options->doMaskSat ? options->satMask : 0;
-	psImageMaskType lowMask = options->doMaskLow ? options->lowMask : 0;
+        psImageMaskType satMask = options->doMaskSat ? options->satMask : 0;
+        psImageMaskType lowMask = options->doMaskLow ? options->lowMask : 0;
         pmReadoutGenerateMask(input, satMask, lowMask);
     }
@@ -56,5 +56,5 @@
         if (!pmBiasSubtract(input, options->overscan, bias, oldDark, view)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to subtract bias.");
-	    psFree(detview);
+            psFree(detview);
             return false;
         }
@@ -64,11 +64,33 @@
     if (options->doVarianceBuild) {
         // create the target mask and variance images
-        pmReadoutGenerateVariance(input, true);
+        psImage *noiseImage = NULL;
+        if (options->doNoiseMap) {
+            // XXX convert the noiseMap image to a binned image
+            pmReadout *noiseMap = NULL;
+            noiseMap = pmFPAfileThisReadout(config->files, detview, "PPIMAGE.NOISEMAP");
+            noiseImage = psImageCopy (NULL, input->image, PS_TYPE_F32);
+            psImageInit (noiseImage, 0.0);
+
+            // XXX this works, but is not really quite right: the model shoud include the
+            // offset information, we are not really getting exactly the right mapping from the
+            // original file.
+            psImageBinning *binning = psImageBinningAlloc();
+            binning->nXruff = noiseMap->image->numCols;
+            binning->nYruff = noiseMap->image->numRows;
+            binning->nXfine = input->image->numCols;
+            binning->nYfine = input->image->numRows;
+            psImageBinningSetScale(binning, PS_IMAGE_BINNING_LEFT);
+
+            psImageUnbin (noiseImage, noiseMap->image, binning);
+            psFree (binning);
+        }
+        pmReadoutGenerateVariance(input, noiseImage, true);
+        psFree (noiseImage);
     }
 
     if (options->doDark && dark) {
-        if (!pmDarkApply(input, dark, options->maskValue)) {
+        if (!pmDarkApply(input, dark, options->darkMask)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to subtract dark.");
-	    psFree(detview);
+            psFree(detview);
             return false;
         }
@@ -79,5 +101,5 @@
                         options->remnanceSize, options->remnanceThresh)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to mask remnance.");
-	    psFree(detview);
+            psFree(detview);
             return false;
         }
@@ -88,5 +110,5 @@
         pmReadout *shutter = pmFPAfileThisReadout(config->files, detview, "PPIMAGE.SHUTTER");
         if (!pmShutterCorrectionApply(input, shutter, pmConfigMaskGet("FLAT", config))) {
-	    psFree(detview);
+            psFree(detview);
             return false;
         }
@@ -97,5 +119,15 @@
         pmReadout *flat = pmFPAfileThisReadout(config->files, detview, "PPIMAGE.FLAT");
         if (!pmFlatField(input, flat, options->flatMask)) {
-	    psFree(detview);
+            psFree(detview);
+            return false;
+        }
+    }
+
+    // Pattern noise correction
+    if (options->doPattern) {
+        if (!pmPatternRow(input, options->patternOrder, options->patternIter, options->patternRej,
+                          options->patternThresh, options->patternMean, options->patternStdev,
+                          options->maskValue, options->darkMask)) {
+            psFree(detview);
             return false;
         }
@@ -119,35 +151,35 @@
     psMetadata *normlist = psMetadataLookupMetadata(&mdok, config->arguments, "NORMALIZATION.TABLE");
     if (normlist) {
-	pmFPAfile *inputFile = psMetadataLookupPtr(&mdok, config->files, "PPIMAGE.INPUT");
-
-	// get the menu of class IDs
-        psMetadata *menu = psMetadataLookupMetadata(&mdok, inputFile->camera, "CLASSID"); 
+        pmFPAfile *inputFile = psMetadataLookupPtr(&mdok, config->files, "PPIMAGE.INPUT");
+
+        // get the menu of class IDs
+        psMetadata *menu = psMetadataLookupMetadata(&mdok, inputFile->camera, "CLASSID");
         if (!menu) {
             psError(PS_ERR_IO, false, "Unable to find CLASSID metadata in camera configuration");
-	    psFree(detview);
-            return false;
-        }
-	// get the rule for class_id for the desired class
-        const char *rule = psMetadataLookupStr(&mdok, menu, options->normClass); 
+            psFree(detview);
+            return false;
+        }
+        // get the rule for class_id for the desired class
+        const char *rule = psMetadataLookupStr(&mdok, menu, options->normClass);
         if (!rule) {
             psError(PS_ERR_IO, false, "Unable to find NORM.CLASS value %s in CLASSID in camera configuration", options->normClass);
-	    psFree(detview);
-            return false;
-        }
-	// get the class_id from the rule
+            psFree(detview);
+            return false;
+        }
+        // get the class_id from the rule
         char *classID = pmFPAfileNameFromRule(rule, inputFile, view);
         if (!classID) {
             psError(PS_ERR_IO, false, "error converting CLASSID rule %s to name\n", rule);
-	    psFree(detview);
-            return false;
-        }
-
-	// get normalization from the class_id
-	float norm = psMetadataLookupF32 (&mdok, normlist, classID);
-	if (!mdok) {
-	    psError(PS_ERR_IO, false, "failed to find class ID %s in normalization table\n", classID);
-	    psFree(detview);
-	    return false;
-	}
+            psFree(detview);
+            return false;
+        }
+
+        // get normalization from the class_id
+        float norm = psMetadataLookupF32 (&mdok, normlist, classID);
+        if (!mdok) {
+            psError(PS_ERR_IO, false, "failed to find class ID %s in normalization table\n", classID);
+            psFree(detview);
+            return false;
+        }
 
         pmHDU *hdu = pmHDUFromReadout(input); // HDU of interest
@@ -157,8 +189,8 @@
         psFree(comment);
 
-	// apply the normalization
+        // apply the normalization
         psBinaryOp(input->image, input->image, "*", psScalarAlloc(norm, PS_TYPE_F32));
 
-	psFree (classID);
+        psFree (classID);
     }
 # endif
@@ -167,5 +199,5 @@
         pmCell *fringe = pmFPAfileThisCell(config->files, detview, "PPIMAGE.FRINGE");
         if (!ppImageDetrendFringeMeasure(input, fringe, false, options)) {
-	    psFree(detview);
+            psFree(detview);
             return false;
         }
