Index: /trunk/ppImage/src/ppImageAstrom.c
===================================================================
--- /trunk/ppImage/src/ppImageAstrom.c	(revision 11351)
+++ /trunk/ppImage/src/ppImageAstrom.c	(revision 11352)
@@ -5,4 +5,6 @@
 # include "ppImage.h"
 
+// this function is mostly equivalent to the top-level of psastro, with some
+// modifications since the data has already been loaded.
 bool ppImageAstrom (pmConfig *config) {
 
@@ -16,5 +18,4 @@
     pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSASTRO.INPUT");
     if (!status) {
-
 	// psphotReadout requires a pmFPAfile supplied with the name PSASTRO.INPUT
 	// create a pmFPAfile which points at PSPHOT.OUTPUT
@@ -27,22 +28,51 @@
     }
 
-    psastroConvertFPA (input->fpa, recipe);
+    // convert the output sources created by psphot into astrometry objects
+    if (!psastroConvertFPA (input->fpa, recipe)) {
+	psErrorStackPrint(stderr, "error loading input data\n");
+	exit (1);
+    }
 
     // interpret the available initial astrometric information
     // apply the initial guess
-    psastroAstromGuess (config);
+    if (!psastroAstromGuess (config)) {
+	psErrorStackPrint(stderr, "failed to determine initial astrometry guess\n");
+	exit (1);
+    }
 
     // load the reference stars overlapping the data stars
     psArray *refs = psastroLoadRefstars(config);
-
-    psastroChooseRefstars(config, refs); 
-
-    if (psMetadataLookupBool (NULL, recipe, "ASTROM.CHIP")) {
-	psastroChipAstrom (config, refs);
-    } 
-    if (psMetadataLookupBool (NULL, recipe, "ASTROM.MOSAIC")) {
-	psastroMosaicAstrom (config, refs);
+    if (!refs) {
+	psErrorStackPrint(stderr, "failed to load reference data\n");
+	exit (1);
     }
 
+    if (!psastroChooseRefstars (config, refs)) {
+	psErrorStackPrint(stderr, "failed to select reference data for chips\n");
+	exit (1);
+    }
+
+    // XXX does this check the recipe??
+    bool chipastro = psMetadataLookupBool (NULL, config->arguments, "PSASTRO.CHIP.MODE");
+    bool mosastro  = psMetadataLookupBool (NULL, config->arguments, "PSASTRO.MOSAIC.MODE");
+    if (!chipastro && !mosastro) {
+	psLogMsg ("psastro", 3, "no astrometry mode selected, assuming chip mode\n");
+	chipastro= true;
+    }
+
+    if (chipastro) {
+      if (!psastroChipAstrom (config, refs)) {
+	    psErrorStackPrint(stderr, "failed to perform single chip astrometry\n");
+	    exit (1);
+	}
+    } 
+    if (mosastro) {
+	if (!psastroMosaicAstrom (config, refs)) {
+	    psErrorStackPrint(stderr, "failed to perform mosaic camera astrometry\n");
+	    exit (1);
+	}
+    }
+
+    // XXX should this be left to the ppImageLoop?
     psastroDataSave (config);
 
Index: /trunk/ppImage/src/ppImageLoop.c
===================================================================
--- /trunk/ppImage/src/ppImageLoop.c	(revision 11351)
+++ /trunk/ppImage/src/ppImageLoop.c	(revision 11352)
@@ -209,4 +209,5 @@
         ppImageAstrom(config);
     }
+    // XXX should we keep the addstar command as an option, or just run it externally?
     if (options->doAddstar) {
         ppImageAddstar(config);
Index: /trunk/ppImage/src/ppImagePhotom.c
===================================================================
--- /trunk/ppImage/src/ppImagePhotom.c	(revision 11351)
+++ /trunk/ppImage/src/ppImagePhotom.c	(revision 11352)
@@ -7,4 +7,5 @@
 // the top portion of this function is equivalent to psphotParseCamera,
 // but different in a few important ways.  
+// XXX move this section to ppImageParseCamera?
 bool ppImagePhotom (pmConfig *config, pmFPAview *view) {
 
@@ -27,11 +28,16 @@
 	// we set the freeLevel to be FPA so this pmFPAfile may be used as input to psastro
 	// XXX make this the resonsibility of a ppImageAstrom call?
-	pmFPAfile *outfile = pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.OUTPUT");
-	outfile->freeLevel = PM_FPA_LEVEL_FPA;
+	// XXX test for psastro requests?
+	// XXX need to make this an INTERNAL file if output is not requested.
+	bool saveOutput = psMetadataLookupBool (NULL, recipe, "SAVE.OUTPUT");
+	if (saveOutput) {
+	  pmFPAfile *outfile = pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.OUTPUT");
+	  outfile->freeLevel = PM_FPA_LEVEL_FPA;
+	}
     }
 
     // if we have requested PSPHOT.SRC (externally supplied sources), attempt to resolve it 
     if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.SRC")) { 
-	pmFPAfileDefineFromArgs (&status, config, "PSPHOT.SRC", "SRC");
+	pmFPAfileDefineFromArgs (&status, config, "PSPHOT.SRC", "PSPHOT.SRC");
 	if (!status) {
 	    psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.SRC");
@@ -42,4 +48,10 @@
     // select recipe options supplied on command line
     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
+
+    // NOTE the difference here from psphotParseCamera: the mask and weight
+    // images are supplied by ppImage and need not / should not be loaded here.
+
+    // optionally load the PSF Model and/or fixed stars
+    pmFPAfileBindFromArgs (NULL, input, config, "PSPHOT.PSF", "PSPHOT.PSF");
 
     // set default recipe values here
@@ -60,5 +72,8 @@
     // optionally save the residual image 
     if (psMetadataLookupBool(NULL, recipe, "SAVE.RESID")) {
-	pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.RESID");
+	if (!pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.RESID")) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKMDL");
+	    return false;
+	}
     }
 
@@ -70,21 +85,39 @@
     // optionally save the background model (small FITS image)
     if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKMDL")) {
-	pmFPAfileDefineFromFPA (config, input->fpa, DX, DY, "PSPHOT.BACKMDL");
+	if (!pmFPAfileDefineFromFPA (config, input->fpa, DX, DY, "PSPHOT.BACKMDL")) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKMDL");
+	    return false;
+	}
     }
     // optionally save the full background image
     if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKGND")) {
-	pmFPAfileDefineFromFPA (config, input->fpa,  1,  1, "PSPHOT.BACKGND");
+	if (!pmFPAfileDefineFromFPA (config, input->fpa,  1,  1, "PSPHOT.BACKGND")) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.BACKGND");
+	    return false;
+	}
     }
     // optionally save the background-subtracted image
     if (psMetadataLookupBool(NULL, recipe, "SAVE.BACKSUB")) {
-	pmFPAfileDefineFromFPA (config, input->fpa,  1,  1, "PSPHOT.BACKSUB");
+	if (!pmFPAfileDefineFromFPA (config, input->fpa,  1,  1, "PSPHOT.BACKSUB")) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.");
+	    return false;
+	}
     }
     // optionally save the PSF Model
     if (psMetadataLookupBool(NULL, recipe, "SAVE.PSF")) {
-	pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.PSF.SAVE");
+	if (!pmFPAfileDefineOutput (config, input->fpa, "PSPHOT.PSF.SAVE")) {
+	    psError(PSPHOT_ERR_CONFIG, false, "Cannot find a rule for PSPHOT.PSF.SAVE");
+	    return false;
+	}
     }
-    // optionally load the PSF Model
-    if (psMetadataLookupBool(NULL, recipe, "LOAD.PSF")) {
-	pmFPAfileDefineInput (config, input->fpa, "PSPHOT.PSF.LOAD");
+
+    // optionally save output plots
+    if (psMetadataLookupBool(NULL, recipe, "SAVE.PLOTS")) {
+	if (!pmFPAfileDefineOutput (config, input->fpa, "SOURCE.PLOT.MOMENTS")) {
+	    psTrace ("psphot", 3, "Cannot find a rule for SOURCE.PLOT.MOMENTS");
+	}
+	if (!pmFPAfileDefineOutput (config, input->fpa, "SOURCE.PLOT.PSFMODEL")) {
+	    psTrace ("psphot", 3, "Cannot find a rule for SOURCE.PLOT.PSFMODEL");
+	}
     }
 
@@ -92,4 +125,8 @@
     // pmFPAfileConstruct (config->files, format, config->camera, "PSPHOT.PSF_SAMPLE");
 
+    // XXX probably need to deactivate all files and activate the psphot ones explicitly
+
+    // In this section, we iterate over the cells and readout for this chip
+    // and run the psphot analysis routine here
     // XXX worry about this not having unique PHOTCODES...
     // view->cell = -1;
