Index: /trunk/psphot/src/Makefile.am
===================================================================
--- /trunk/psphot/src/Makefile.am	(revision 12586)
+++ /trunk/psphot/src/Makefile.am	(revision 12587)
@@ -16,4 +16,5 @@
 	psphotArguments.c	\
 	psphotParseCamera.c	\
+	psphotMosaicChip.c	\
 	psphotImageLoop.c	\
 	psphotMaskReadout.c	\
Index: /trunk/psphot/src/psphot.h
===================================================================
--- /trunk/psphot/src/psphot.h	(revision 12586)
+++ /trunk/psphot/src/psphot.h	(revision 12587)
@@ -24,4 +24,5 @@
 bool            psphotParseCamera (pmConfig *config);
 bool            psphotImageLoop (pmConfig *config);
+bool            psphotMosaicChip(pmConfig *config, const pmFPAview *view, char *outFile, char *inFile);
 
 bool            psphotModelTest (pmReadout *readout, psMetadata *recipe);
Index: /trunk/psphot/src/psphotImageLoop.c
===================================================================
--- /trunk/psphot/src/psphotImageLoop.c	(revision 12586)
+++ /trunk/psphot/src/psphotImageLoop.c	(revision 12587)
@@ -1,6 +1,4 @@
 # include "psphot.h"
 
-// XXX the errors in the pmFPAfileIOChecks could also be due to a programming or config error
-// XXX we need to either handle those errors or handle the error in pmFPAfileIOChecks and exit
 bool psphotImageLoop (pmConfig *config) {
 
@@ -10,4 +8,9 @@
     pmReadout *readout;
 
+    pmFPAfile *load = psMetadataLookupPtr (&status, config->files, "PSPHOT.LOAD");
+    if (!status) {
+	psError(PSPHOT_ERR_PROG, false, "Can't find input data!");
+	return false;
+    }
     pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT");
     if (!status) {
@@ -25,7 +28,14 @@
     }
 
-    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+    // for psphot, we force data to be read at the chip level 
+    while ((chip = pmFPAviewNextChip (view, load->fpa, 1)) != NULL) {
         psLogMsg ("psphot", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
         if (! chip->process || ! chip->file_exists) { continue; }
+
+	// load just the input image data (image, mask, weight)
+	pmFPAfileActivate (config->files, false, NULL);
+	pmFPAfileActivate (config->files, true, "PSPHOT.LOAD");
+	pmFPAfileActivate (config->files, true, "PSPHOT.MASK");
+	pmFPAfileActivate (config->files, true, "PSPHOT.WEIGHT");
 	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
             psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d in psphot\n", view->chip);
@@ -33,25 +43,34 @@
 	    return false;
 	}
+	pmFPAfileActivate (config->files, true, NULL);
 	
+	// mosaic the cells of a chip into a single contiguous chip.
+	// this probably needs to return a new fpa? 
+        if (!psphotMosaicChip(config, view, "PSPHOT.INPUT", "PSPHOT.LOAD")) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to mosaic chip.\n");
+            return false;
+        }
+
+	// try to load the data
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
+            psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d in psphot\n", view->chip);
+	    psFree (view);
+	    return false;
+	}
+
+	// there is now only a single chip (multiple readouts?). loop over it and process
+	// XXX activate / de-activate files? no I/O here?
 	while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
             psLogMsg ("psphot", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
-            if (! cell->process || ! cell->file_exists) { continue; }
-	    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
-		psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d, cell %d in psphot\n", view->chip, view->cell);
-		psFree (view);
-		return false;
-	    }
+            // if (! cell->process || ! cell->file_exists) { continue; }
+            if (! cell->process) { continue; }
 	    
 	    // process each of the readouts
 	    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) {
-		    psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d, cell %d, readout %d in psphot\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-		
+		psLogMsg ("psphot", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
 		if (! readout->data_exists) { continue; }
-		
+
 		// run the actual photometry analysis
+		// XXX calling psphotReadout here will operate on the mosaic'ed chips (for each readout)
 		if (!psphotReadout (config, view)) {
 		    psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
@@ -59,17 +78,8 @@
 		    return false;
 		}
-
-		if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-		    psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d, cell %d, readout %d in psphot\n", view->chip, view->cell, view->readout);
-		    psFree (view);
-		    return false;
-		}
-	    }
-	    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
-		psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d, cell %d in psphot\n", view->chip, view->cell);
-		psFree (view);
-		return false;
 	    }
 	}
+
+	// save output which is saved at the chip level
 	if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
             psError(PSPHOT_ERR_DATA, false, "failed IO for chip %d in psphot\n", view->chip);
@@ -78,4 +88,5 @@
 	}
     }
+    // save output which is saved at the fpa level
     if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) {
 	psError(PSPHOT_ERR_DATA, false, "failed IO for fpa in psphot\n");
@@ -101,2 +112,5 @@
 // PSPHOT.PSF     : sample PSF images
 
+// PSPHOT.MASK
+// PSPHOT.WEIGHT
+// 
Index: /trunk/psphot/src/psphotImageMedian.c
===================================================================
--- /trunk/psphot/src/psphotImageMedian.c	(revision 12586)
+++ /trunk/psphot/src/psphotImageMedian.c	(revision 12587)
@@ -122,4 +122,5 @@
     } else {
 	if (file->mode == PM_FPA_MODE_INTERNAL) {
+	    // we are not using PSPHOT.BACKMDL as an I/O file: already defined above
 	    model = file->readout;
 	} else {
@@ -128,4 +129,5 @@
 	    if (model == NULL) {
 		// readout does not yet exist: create from input
+		// XXX we have an inconsistency in this calculation here and in pmFPACopy
 		pmFPAfileCopyStructureView (file->fpa, inFPA, DX, DY, view);
 		model = pmFPAviewThisReadout (view, file->fpa);
Index: /trunk/psphot/src/psphotMosaicChip.c
===================================================================
--- /trunk/psphot/src/psphotMosaicChip.c	(revision 12587)
+++ /trunk/psphot/src/psphotMosaicChip.c	(revision 12587)
@@ -0,0 +1,36 @@
+# include "psphot.h"
+
+bool psphotMosaicChip(pmConfig *config, const pmFPAview *view, char *outFile, char *inFile)
+{
+    bool status;                        // Status of MD lookup
+
+    pmFPAfile *in = psMetadataLookupPtr(&status, config->files, inFile); // Input file
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find required I/O file!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    pmFPAfile *out = psMetadataLookupPtr(&status, config->files, outFile); // Output file
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find required I/O file!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // XXXX we are failing to get the output hdu right
+    pmChip *outChip = pmFPAviewThisChip(view, out->fpa);
+    pmChip *inChip = pmFPAviewThisChip(view, in->fpa);
+    if (!outChip->hdu && !outChip->parent->hdu) {
+        const char *name = psMetadataLookupStr(&status, in->fpa->concepts, "FPA.NAME"); // Name of FPA
+        pmFPAAddSourceFromView(out->fpa, name, view, out->format);
+    }
+
+    psTrace("pmChipMosaic", 5, "mosaic chip %s to %s (xbin,ybin: %d,%d to %d,%d)\n",
+            in->name, out->name, in->xBin, in->yBin, out->xBin, out->yBin);
+    status = pmChipMosaic(outChip, inChip);
+    return status;
+}
+
+// XXX does this do everything needed?
+// * mask & weight
+// * loaded PSF model (in readout->analysis)
+// * loaded SRC sources (in readout->analysis)
Index: /trunk/psphot/src/psphotParseCamera.c
===================================================================
--- /trunk/psphot/src/psphotParseCamera.c	(revision 12586)
+++ /trunk/psphot/src/psphotParseCamera.c	(revision 12587)
@@ -6,12 +6,23 @@
     bool status = false;
 
-    // the input image defines the camera
-    pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT", "INPUT");
+    // the file to be loaded may have subdivisions at the cell and readout level
+    // we load into pmFPAfile *load, then reformat into pmFPAfile *input
+    pmFPAfile *load = pmFPAfileDefineFromArgs (&status, config, "PSPHOT.LOAD", "INPUT");
     if (!status) {
-	psError(PSPHOT_ERR_CONFIG, false, "Failed to build FPA from PSPHOT.INPUT");
+	psError(PSPHOT_ERR_CONFIG, false, "Failed to build FPA from PSPHOT.LOAD");
 	return status;
+    }
+    load->dataLevel = PM_FPA_LEVEL_CHIP; // force load at the CHIP level
+
+    // the psphot analysis is performed on chips
+    pmFPAfile *input = pmFPAfileDefineChipMosaic(config, input->fpa, "PSPHOT.INPUT");
+    if (!input) {
+        psError(PSPHOT_ERR_CONFIG, false, _("Unable to generate new file from PSPHOT.INPUT"));
+        return NULL;
     }
 
     // if we have requested PSPHOT.SRC, attempt to resolve it 
+    // this is a list of input sources, stored in a psphot output format file
+# if (0)    
     if (psMetadataLookupPtr(NULL, config->arguments, "SRC")) { 
 	pmFPAfileDefineFromArgs (&status, config, "PSPHOT.SRC", "SRC");
@@ -21,25 +32,22 @@
 	}
     }
+# endif
 
     // select recipe options supplied on command line
     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
 
+    // these values are used below to define the background subtraction images.
+
     // if MASK or WEIGHT was supplied on command line, bind files to input fpa
     // XXX these do not quite yet work: pmFPAAddSourceFromHeader is not appropriate
-    pmFPAfileBindFromArgs (NULL, input, config, "PSPHOT.MASK", "MASK");
-    pmFPAfileBindFromArgs (NULL, input, config, "PSPHOT.WEIGHT", "WEIGHT");
+    // the mask and weight will be mosaic'ed with the image
+    pmFPAfileBindFromArgs (NULL, load, config, "PSPHOT.MASK",   "MASK");
+    pmFPAfileBindFromArgs (NULL, load, config, "PSPHOT.WEIGHT", "WEIGHT");
 
     // optionally load the PSF Model and/or fixed stars
-    pmFPAfileBindFromArgs (NULL, input, config, "PSPHOT.PSF", "PSF");
-
-    // set default recipe values here
-    // XXX drop this?  we put this in the default recipe?
-    psMetadataAddStr (recipe, PS_LIST_TAIL, "FITMODE",         PS_META_NO_REPLACE, "default fitting mode", "NONE");
-    psMetadataAddStr (recipe, PS_LIST_TAIL, "BREAK_POINT",     PS_META_NO_REPLACE, "default break point",  "NONE");
-    psMetadataAddF32 (recipe, PS_LIST_TAIL, "ZERO_PT",         PS_META_NO_REPLACE, "default zero point",    25.00);
-    psMetadataAddS32 (recipe, PS_LIST_TAIL, "BACKGROUND.XBIN", PS_META_NO_REPLACE, "default binning",          64);
-    psMetadataAddS32 (recipe, PS_LIST_TAIL, "BACKGROUND.YBIN", PS_META_NO_REPLACE, "default binning",          64);
-    psMetadataAddStr (recipe, PS_LIST_TAIL, "PHOTCODE",        PS_META_NO_REPLACE, "default photcode",     "NONE");
-    // photcode will be added in psphotReadout
+    // XXX bind this to the input or the load file?
+    // if the readout->analysis entries are copied, we can bind to the load file
+    // XXX add this back in later
+    // pmFPAfileBindFromArgs (NULL, input, config, "PSPHOT.PSF", "PSF");
 
     // XXX we need to be able to distinguish several cases:
@@ -49,7 +57,6 @@
     // 4) the particular output data was requested but was not generated (surprising failure)
 
-    // these calls bind the I/O handle to the specified fpa
-    bool saveOutput = psMetadataLookupBool (NULL, recipe, "SAVE.OUTPUT");
-    if (saveOutput) {
+    // the output sources are carried on the input->fpa structures
+    if (psMetadataLookupBool (NULL, recipe, "SAVE.OUTPUT")) {
 	if (!pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.OUTPUT")) {
 	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.OUTPUT");
@@ -57,5 +64,4 @@
 	}
     }
-
     // optionally save the residual image 
     if (psMetadataLookupBool(NULL, recipe, "SAVE.RESID")) {
@@ -65,12 +71,8 @@
 	}
     }
-
-    int DX = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
-    int DY = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
-
-    // these calls construct a new fpa for the I/O handle 
-
     // optionally save the background model (small FITS image)
     if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKMDL")) {
+	int DX = psMetadataLookupS32 (&status, recipe, "BACKGROUND.XBIN");
+	int DY = psMetadataLookupS32 (&status, recipe, "BACKGROUND.YBIN");
 	if (!pmFPAfileDefineFromFPA (config, input->fpa, DX, DY, "PSPHOT.BACKMDL")) {
 	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKMDL");
