Index: /trunk/dvoTools/src/dvoApplyCorr.h
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorr.h	(revision 20179)
+++ /trunk/dvoTools/src/dvoApplyCorr.h	(revision 20180)
@@ -32,5 +32,6 @@
 
 // apply the correction factor pixel-by-pixel
-bool dvoApplyCorrReadout (pmConfig *config, pmFPAview *view, char *inName, char *corrName);
+// XXX : old value bool dvoApplyCorrReadout (pmConfig *config, pmFPAview *view, char *inName, char *corrName);
+bool dvoApplyCorrReadout (pmCell *inCell, pmChip *corrChip);
 
 // free memory, check for leaks
Index: /trunk/dvoTools/src/dvoApplyCorrArguments.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrArguments.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoApplyCorrArguments.c	(revision 20180)
@@ -35,10 +35,10 @@
     // save the following additional recipe values based on command-line options
     // these options override the DVOCORR recipe values loaded from recipe files
-    psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
+    // psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
 
     // XXX add options from command-line here
 
     // drop the local view on the options (saved on config->arguments)
-    psFree (options);
+    // psFree (options);
 
     // chip selection is used to limit chips to be processed
Index: /trunk/dvoTools/src/dvoApplyCorrLoop.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrLoop.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoApplyCorrLoop.c	(revision 20180)
@@ -10,5 +10,4 @@
     pmChip *chip;
     pmCell *cell;
-    pmReadout *readout;
 
     // psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, RECIPE_NAME);
@@ -17,5 +16,12 @@
     pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "DVOFLAT.INPUT");
     if (!status) {
-        psErrorStackPrint(stderr, "Can't find input data!\n");
+        psErrorStackPrint(stderr, "Can't find input flat-field image\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // select the input image
+    pmFPAfile *corr = psMetadataLookupPtr(&status, config->files, "DVOFLAT.CORR");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find correction image\n");
         exit(EXIT_FAILURE);
     }
@@ -40,4 +46,6 @@
 	}
 
+	pmChip *corrChip = pmFPAviewThisChip(view, corr->fpa);
+
 	// process each cell in the Chip
         while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
@@ -50,21 +58,9 @@
 	    }
 
-	    // process each of the readouts
-	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
-		if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoApplyCorr\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-		if (!readout->data_exists) continue;
-
-		// XXX put the function here which multiplies the input image and the correction image
-		dvoApplyCorrReadout (config, view, "DVOFLAT.INPUT", "DVOFLAT.CORR");
-
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoApplyCorr\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
+	    // multiply the input image and the correction image
+	    if (!dvoApplyCorrReadout (cell, corrChip)) {
+		psError(PS_ERR_UNKNOWN, false, "failed to apply correction to chip %d, cell %d dvoApplyCorr\n", view->chip, view->cell);
+		psFree (view);
+		return false;
 	    }
 	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
Index: /trunk/dvoTools/src/dvoApplyCorrParseCamera.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrParseCamera.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoApplyCorrParseCamera.c	(revision 20180)
@@ -4,4 +4,5 @@
 
 # include "dvoApplyCorr.h"
+bool dvoApplyCorrSelectCorrFile (pmConfig *config, pmFPA *input);
 
 dvoApplyCorrOptions *dvoApplyCorrParseCamera (pmConfig *config) {
@@ -29,12 +30,8 @@
         return NULL;
     }
+    output->save = TRUE;
 
     // find the flat-field correction image (from command-line, config file, or detrend db)
-    status = false;
-    pmFPAfileDefineFromArgs  (&status, config, "DVOFLAT.CORR", "CORR");
-    psErrorClear();
-    pmFPAfileDefineFromConf  (&status, config, "DVOFLAT.CORR");
-    psErrorClear();
-    pmFPAfileDefineFromDetDB (&status, config, "DVOFLAT.CORR", input->fpa, PM_DETREND_TYPE_FLAT_CORRECTION);
+    status = dvoApplyCorrSelectCorrFile (config, input->fpa);
     if (!status) {
 	psError (PS_ERR_IO, false, "can't find a flat-field correction image source");
@@ -52,5 +49,5 @@
             if (! pmFPASelectChip(output->fpa, chipNum, false)) {
                 psError(PS_ERR_IO, false, "Chip number %d doesn't exist in camera.\n", chipNum);
-                return false;
+                return NULL;
             }
         }
@@ -59,2 +56,48 @@
     return (options);
 }
+
+bool dvoApplyCorrSelectCorrFile (pmConfig *config, pmFPA *input) {
+
+    bool status;
+    pmFPAfile *file = NULL;
+
+    file = pmFPAfileDefineFromArgs  (&status, config, "DVOFLAT.CORR", "CORR");
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load file definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != PM_FPA_FILE_IMAGE) {
+	    psError(PS_ERR_IO, true, "DVOFLAT.CORR is not of type IMAGE");
+	    return false;
+	}
+	return true;
+    }
+
+    file = pmFPAfileDefineFromConf  (&status, config, "DVOFLAT.CORR");
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load file definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != PM_FPA_FILE_IMAGE) {
+	    psError(PS_ERR_IO, true, "DVOFLAT.CORR is not of type IMAGE");
+	    return false;
+	}
+	return true;
+    }
+
+    file = pmFPAfileDefineFromDetDB (&status, config, "DVOFLAT.CORR", input, PM_DETREND_TYPE_FLAT_CORRECTION);
+    if (!status) {
+	psError (PS_ERR_UNKNOWN, false, "failed to load file definition");
+	return false;
+    }
+    if (file) {
+	if (file->type != PM_FPA_FILE_IMAGE) {
+	    psError(PS_ERR_IO, true, "DVOFLAT.CORR is not of type IMAGE");
+	    return false;
+	}
+	return true;
+    }
+    return false;
+}
Index: /trunk/dvoTools/src/dvoApplyCorrReadout.c
===================================================================
--- /trunk/dvoTools/src/dvoApplyCorrReadout.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoApplyCorrReadout.c	(revision 20180)
@@ -5,40 +5,52 @@
 #include "dvoApplyCorr.h"
 
-// this function is operating on each readout, assuming there is a correspondence between
-// readouts in the input (raw) flat-field image and the correction frame.  this is not really
-// true
+// this function is operating on each cell (well, readout) of the flat to be corrected.  The
+// input chip is supplied, but may be in a different format (eg, chip-mosaic vs single cell)
 
-bool dvoApplyCorrReadout (pmConfig *config, pmFPAview *view, char *inName, char *corrName) {
+bool dvoApplyCorrReadout (pmCell *inCell, pmChip *corrChip) {
     
+    // XXX for now, let's just assume the input is per-cell, and the correction is per-chip
+    // Also, let's assume they are both binned 1x1
+
     bool status;
 
-    pmFPAfile *inFile = psMetadataLookupPtr (&status, config->files, inName);
-    pmFPAfile *corrFile = psMetadataLookupPtr (&status, config->files, corrName);
-    assert (inFile);
-    assert (corrFile);
+    pmCell *corrCell = corrChip->cells->data[0];
+    pmReadout *corrRO = corrCell->readouts->data[0];
+    psImage *corrImage = corrRO->image;
 
-    pmReadout *inData = pmFPAviewThisReadout (view, inFile->fpa);
-    pmReadout *corrData = pmFPAviewThisReadout (view, corrFile->fpa);
-    assert (inData);
-    assert (corrData);
+    pmReadout *inRO = inCell->readouts->data[0];
+    psImage *inImage = inRO->image;
 
-    // dimensions of input image:
-    assert (inData->image->numCols == corrData->image->numCols);
-    assert (inData->image->numRows == corrData->image->numRows);
+    int x0 = psMetadataLookupS32(&status, inCell->concepts, "CELL.X0"); // Position of (0,0) on chip
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.X0 hasn't been set for cell.\n");
+        return false;
+    }
+    int y0 = psMetadataLookupS32(&status, inCell->concepts, "CELL.Y0"); // Position of (0,0) on chip
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.Y0 hasn't been set for cell.\n");
+        return false;
+    }
 
-    // NOTE : the output pmFPA points at the same pixels as the input pmFPA
+    int xParity = psMetadataLookupS32(&status, inCell->concepts, "CELL.XPARITY"); // Parity in x
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY hasn't been set for cell.\n");
+        return false;
+    }
+    int yParity = psMetadataLookupS32(&status, inCell->concepts, "CELL.YPARITY"); // Parity in y
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY hasn't been set for cell.\n");
+        return false;
+    }
 
-    // the corr image is a multiplicative factor
-    for (int j = 0; j < inData->image->numRows; j++) {
-	for (int i = 0; i < inData->image->numCols; i++) {
-	    inData->image->data.F32[j][i] *= corrData->image->data.F32[j][i]; 
+    // The corr image is a multiplicative factor.  Need to convert the input flat pixel
+    // coordinates to the correction cell/pixel coords.
+    for (int j = 0; j < inImage->numRows; j++) {
+	int jC = (yParity < 0) ? y0 + j*yParity : y0 + j*yParity + 1;
+	for (int i = 0; i < inImage->numCols; i++) {
+	    int iC = (xParity < 0) ? x0 + i*xParity : x0 + i*xParity + 1;
+	    inImage->data.F32[j][i] *= corrImage->data.F32[jC][iC]; 
 	}
     }
-
-    // psFits *fits = psFitsOpen ("tmp.fits", "w");
-    // psFitsWriteImage (fits, NULL, inData->image, 0, NULL);
-    // psFitsClose (fits);
-    // exit (0);
-
     return true;
 }
Index: /trunk/dvoTools/src/dvoMakeCorr.h
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorr.h	(revision 20179)
+++ /trunk/dvoTools/src/dvoMakeCorr.h	(revision 20180)
@@ -32,5 +32,5 @@
 
 // convert low-res image to hi-res image
-bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, char *inName, char *refName);
+bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, psImage *inImage, pmChip *inChip, char *refName);
 
 // free memory, check for leaks
Index: /trunk/dvoTools/src/dvoMakeCorrArguments.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrArguments.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoMakeCorrArguments.c	(revision 20180)
@@ -35,10 +35,7 @@
     // save the following additional recipe values based on command-line options
     // these options override the DVOCORR recipe values loaded from recipe files
-    psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
+    // psMetadata *options = pmConfigRecipeOptions (config, RECIPE_NAME);
 
     // XXX add options from command-line here
-
-    // drop the local view on the options (saved on config->arguments)
-    psFree (options);
 
     // the input file is a required argument; if not found, we will exit
Index: /trunk/dvoTools/src/dvoMakeCorrLoop.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrLoop.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoMakeCorrLoop.c	(revision 20180)
@@ -5,4 +5,7 @@
 #include "dvoMakeCorr.h"
 
+// XXX currently, the input image (the grid map generated by relphot) does not supply enough
+// header information so the camera and format can be identified.
+
 bool dvoMakeCorrLoop (pmConfig *config, dvoMakeCorrOptions *options) {
 
@@ -10,7 +13,14 @@
     pmChip *chip;
     pmCell *cell;
-    pmReadout *readout;
+    psRegion fullImage = {0, 0, 0, 0};
 
     // psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, RECIPE_NAME);
+
+    // use the reference image to identify the desired extension from DVOCORR.INPUT
+    pmFPAfile *refhead = psMetadataLookupPtr(&status, config->files, "DVOCORR.REFHEAD");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find reference image\n");
+        exit(EXIT_FAILURE);
+    }
 
     pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "DVOCORR.INPUT");
@@ -29,6 +39,14 @@
     }
 
+    // XXX for now, do not use the I/O system to read this file; do it manually
+    if (!pmFPAfileOpen (input, view, config)) {
+	psError(PS_ERR_UNKNOWN, false, "failed to open grid file\n");
+	psFree (view);
+	return false;
+    }
+    input->state = PM_FPA_STATE_INACTIVE;  
+
     // process each chip in the FPA
-    while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
+    while ((chip = pmFPAviewNextChip(view, refhead->fpa, 1)) != NULL) {
         psLogMsg ("dvoMakeCorrLoop", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
         if (!chip->process || !chip->file_exists) continue;
@@ -39,6 +57,13 @@
 	}
 
+	// load the input data for this extension
+	pmChip *inChip = pmFPAviewThisChip (view, input->fpa);
+	char *inName = psMetadataLookupStr (&status, inChip->concepts, "CHIP.NAME");
+	psFitsMoveExtName (input->fits, inName);
+	psImage *inImage = psFitsReadImage (input->fits, fullImage, 0);
+	assert (inImage);
+
 	// process each cell in the Chip
-        while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
+        while ((cell = pmFPAviewNextCell(view, refhead->fpa, 1)) != NULL) {
             psLogMsg ("dvoMakeCorrLoop", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
             if (!cell->process || !cell->file_exists) continue;
@@ -49,22 +74,7 @@
 	    }
 
-	    // process each of the readouts
-	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
-		if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
-		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoMakeCorr\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-		if (!readout->data_exists) continue;
+	    // XXX put the function here which unbins the input image
+	    dvoMakeCorrUnbin (config, view, "DVOCORR.OUTPUT", inImage, inChip, "DVOCORR.REFHEAD");
 
-		// XXX put the function here which unbins the input image
-		dvoMakeCorrUnbin (config, view, "DVOCORR.OUTPUT", "DVOCORR.INPUT", "DVOCORR.REFHEAD");
-
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-		    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d, readout %d in dvoMakeCorr\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-	    }
 	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
 		psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d, cell %d in dvoMakeCorr\n", view->chip, view->cell);
@@ -73,4 +83,6 @@
 	    }
 	}
+	psFree (inImage);
+
 	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
 	    psError(PS_ERR_UNKNOWN, false, "failed IO for chip %d in dvoMakeCorr\n", view->chip);
@@ -85,4 +97,5 @@
     }
 
+    pmFPAfileClose (input, view);
     psFree (view);
 
Index: /trunk/dvoTools/src/dvoMakeCorrParseCamera.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrParseCamera.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoMakeCorrParseCamera.c	(revision 20180)
@@ -7,15 +7,15 @@
 dvoMakeCorrOptions *dvoMakeCorrParseCamera (pmConfig *config) {
 
+    // the REFERENCE image defines the camera, and all recipes and options the follow
+    pmFPAfile *refhead = pmFPAfileDefineFromArgs (NULL, config, "DVOCORR.REFHEAD", "REFHEAD");
+    if (!refhead) {
+        psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.REFHEAD");
+        return NULL;
+    }
+
     // the input image defines the camera, and all recipes and options the follow
     pmFPAfile *input = pmFPAfileDefineFromArgs (NULL, config, "DVOCORR.INPUT", "INPUT");
     if (!input) {
         psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.INPUT");
-        return NULL;
-    }
-
-    // the input image defines the camera, and all recipes and options the follow
-    pmFPAfile *refhead = pmFPAfileDefineFromArgs (NULL, config, "DVOCORR.REFHEAD", "REFHEAD");
-    if (!refhead) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from DVOCORR.REFHEAD");
         return NULL;
     }
@@ -29,5 +29,5 @@
     // the following files are output targets
     // XXX get the binning from where?
-    pmFPAfile *output = pmFPAfileDefineFromFPA(config, input->fpa, 1, 1, "DVOCORR.OUTPUT");
+    pmFPAfile *output = pmFPAfileDefineFromFPA(config, refhead->fpa, 1, 1, "DVOCORR.OUTPUT");
     if (!output) {
         psError(PS_ERR_IO, false, _("Unable to generate output file from DVOCORR.OUTPUT"));
@@ -35,4 +35,5 @@
         return NULL;
     }
+    output->save = TRUE;
 
     // Chip selection: turn on only the chips specified (pass status to suppress missing-key log msg)
Index: /trunk/dvoTools/src/dvoMakeCorrUnbin.c
===================================================================
--- /trunk/dvoTools/src/dvoMakeCorrUnbin.c	(revision 20179)
+++ /trunk/dvoTools/src/dvoMakeCorrUnbin.c	(revision 20180)
@@ -5,12 +5,10 @@
 #include "dvoMakeCorr.h"
 
-bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, char *inName, char *refName) {
+bool dvoMakeCorrUnbin (pmConfig *config, pmFPAview *view, char *outName, psImage *inImage, pmChip *inChip, char *refName) {
     
     bool status;
 
-    pmFPAfile *inFile = psMetadataLookupPtr (&status, config->files, inName);
     pmFPAfile *refFile = psMetadataLookupPtr (&status, config->files, refName);
     pmFPAfile *outFile = psMetadataLookupPtr (&status, config->files, outName);
-    assert (inFile);
     assert (refFile);
     assert (outFile);
@@ -19,6 +17,6 @@
     assert (refCell);
 
-    pmReadout *inData = pmFPAviewThisReadout (view, inFile->fpa);
-    assert (inData);
+    pmChip *refChip = pmFPAviewThisChip (view, refFile->fpa);
+    assert (refChip);
 
     // determine the output array size based on the reference TRIMSEC values
@@ -28,27 +26,36 @@
     // I have the fine and ruff image sizes, determine the binning factor
     psImageBinning *binning = psImageBinningAlloc();
-    binning->nXruff = inData->image->numCols;
-    binning->nYruff = inData->image->numRows;
+    binning->nXruff = inImage->numCols;
+    binning->nYruff = inImage->numRows;
     binning->nXfine = trimsec->x1 - trimsec->x0;
     binning->nYfine = trimsec->y1 - trimsec->y0;
     psImageBinningSetScale (binning, PS_IMAGE_BINNING_CENTER);
-    psImageBinningSetSkip(binning, inData->image);
+    psImageBinningSetSkip(binning, inImage);
+
+    // generate a local view of the 0th readout
+    pmFPAview *myView = pmFPAviewAlloc (0);
+    *myView = *view;
+    myView->readout = 0;
 
     // construct the supporing pmFPA/pmChip/pmCell structures
-    pmReadout *outData = pmFPAviewThisReadout (view, outFile->fpa);
+    pmReadout *outData = pmFPAviewThisReadout (myView, outFile->fpa);
     if (outData == NULL) {
-	pmChip *inChip = pmFPAviewThisChip (view, inFile->fpa);
-	pmChip *outChip = pmFPAviewThisChip (view, outFile->fpa);
+	pmChip *outChip = pmFPAviewThisChip (myView, outFile->fpa);
+	pmCell *outCell = pmFPAviewThisCell (myView, outFile->fpa);
 
-	pmChipCopyStructure (outChip, inChip, binning->nXbin, binning->nYbin);
-	outData = pmFPAviewThisReadout (view, outFile->fpa);
+	pmChipCopyStructure (outChip, refChip, 1, 1);
+
+	outData = pmReadoutAlloc (outCell);
 	assert (outData != NULL);
+
+	// outData = pmFPAviewThisReadout (myView, outFile->fpa);
+	// assert (outData != NULL);
     }
 
     // generate the output (fine-scale) image array
-    psImageRecycle (outData->image, binning->nXfine, binning->nYfine, PS_TYPE_F32);
+    outData->image = psImageRecycle (outData->image, binning->nXfine, binning->nYfine, PS_TYPE_F32);
 
     // linear interpolation to full fine scale
-    if (!psImageUnbin (outData->image, inData->image, binning)) {
+    if (!psImageUnbin (outData->image, inImage, binning)) {
 	psError (PS_ERR_UNKNOWN, true, "failed to unbin image");
 	psFree (binning);
