Index: trunk/ppSim/src/ppSimLoop.c
===================================================================
--- trunk/ppSim/src/ppSimLoop.c	(revision 15482)
+++ trunk/ppSim/src/ppSimLoop.c	(revision 18011)
@@ -1,34 +1,48 @@
 #include "ppSim.h"
+
+# define ESCAPE(CODE,MSG) { \
+  psError(CODE, false, MSG); \
+  psFree (rng); \
+  return false; }
 
 bool ppSimLoop(pmConfig *config)
 {
+    bool status;
+
+    // XXX if we are supplying a PSF, then we should use that to specify the seeing.
+    // we will need to force the psf to be loaded here (deactivate everyone, activate psf, load
+    // it, then calculate seeing as appropriate).
+
     PS_ASSERT_PTR_NON_NULL(config, PS_EXIT_PROG_ERROR);
 
-    pmFPAfile *file = psMetadataLookupPtr(NULL, config->files, OUTPUT_FILE); // Output file
+    // in this program, we are looping over the output image, rather than the input as in ppImage
+    pmFPAfile *file = psMetadataLookupPtr(NULL, config->files, "PPSIM.OUTPUT"); // Output file
     assert(file);
+
     pmFPA *fpa = file->fpa;             // FPA for file
     assert(fpa);
 
-    ppSimType type = psMetadataLookupS32(NULL, config->arguments, "TYPE"); // Type of image to simulate
+    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSIM_RECIPE); // Recipe
 
     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator
 
-    int binning = psMetadataLookupS32(NULL, config->arguments, "BINNING"); // Binning in x and y
-
-    // Load catalogue stars
+    char *typeStr = psMetadataLookupStr(NULL, recipe, "IMAGE.TYPE"); // Type of image to simulate
+    ppSimType type = ppSimTypeFromString (typeStr); // Type of image to simulate
+    int binning = psMetadataLookupS32(NULL, recipe, "BINNING"); // Binning in x and y
+
     psArray *stars = psArrayAllocEmpty (1);
-    if (type == PPSIM_TYPE_OBJECT) {
-        ppSimLoadStars (stars, fpa, config);
-    }
-
-    // Add random stars
-    if (type == PPSIM_TYPE_OBJECT) {
-        ppSimMakeStars (stars, fpa, config, rng);
-    }
-
-    // Add random galaxies
     psArray *galaxies = psArrayAllocEmpty (1);
     if (type == PPSIM_TYPE_OBJECT) {
-        ppSimMakeGalaxies (galaxies, fpa, config, rng);
+	// Load forced-photometry positions (these are placed on fpa->analysis for use in ppSimPhotomReadout)
+	if (!ppSimLoadSpots (fpa, config)) ESCAPE (PS_ERR_UNKNOWN, "failed to load forced-photometry spots");
+
+	// Load catalogue stars
+        if (!ppSimLoadStars (stars, fpa, config)) ESCAPE (PS_ERR_UNKNOWN, "failed to load catalog stars");
+
+	// Add random stars
+        if (!ppSimMakeStars (stars, fpa, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "failed to make random stars");
+
+	// Add random galaxies
+        if (!ppSimMakeGalaxies (galaxies, fpa, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "failed to make random galaxies");
     }
 
@@ -46,4 +60,7 @@
 
     ppSimUpdateConceptsFPA (fpa, config);
+    if (fpa->hdu) { // XXX only do this if there is no INPUT image
+        if (!ppSimInitHeader(config, fpa, NULL, NULL)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
+    }
 
     pmChip *chip;                       // Chip from FPA
@@ -98,8 +115,6 @@
             psVector *biasCols = ppSimMakeBiassec (cell, config);
 
-            for (int i = 0; i < cell->readouts->n; i++) {
-
-                pmReadout *readout = cell->readouts->data[i];
-                assert (readout);
+	    pmReadout *readout;
+	    while ((readout = pmFPAviewNextReadout (view, fpa, 1))) {
 
                 // if we have not read in a weight or generated a fake image above, we need to
@@ -117,19 +132,20 @@
                 }
 
-                psVector *biasRows = ppSimMakeBias (readout, config, rng);
+                psVector *biasRows = ppSimMakeBias (&status, readout, config, rng);
+		if (!status) ESCAPE (PS_ERR_UNKNOWN, "problem generating dark structure");
                 if (type == PPSIM_TYPE_BIAS) goto done;
 
-                ppSimMakeDark (readout, config);
+		if (!ppSimMakeDark (readout, config)) ESCAPE (PS_ERR_UNKNOWN, "problem generating dark structure");
                 if (type == PPSIM_TYPE_DARK) goto done;
 
-                ppSimMakeSky (readout, expCorr, type, config);
+                if (!ppSimMakeSky (readout, expCorr, type, config)) ESCAPE (PS_ERR_UNKNOWN, "problem generating sky background");
                 if (type == PPSIM_TYPE_FLAT) goto done;
 
                 if (type == PPSIM_TYPE_OBJECT) {
-                    ppSimInsertStars (readout, expCorr, stars, config);
+                    if (!ppSimInsertStars (readout, expCorr, stars, config)) ESCAPE (PS_ERR_UNKNOWN, "problem inserting stars");
                 }
 
                 if (type == PPSIM_TYPE_OBJECT) {
-                    ppSimInsertGalaxies (readout, expCorr, galaxies, config);
+                    if (!ppSimInsertGalaxies (readout, expCorr, galaxies, config)) ESCAPE (PS_ERR_UNKNOWN, "problem inserting galaxies");
                 }
 
@@ -137,10 +153,10 @@
 
             done:
-                ppSimAddNoise(readout->image, readout->weight, cell, config, rng);
-                ppSimSaturate(readout, config);
-
-                ppSimBadPixels(readout, config, rng);
-
-                ppSimAddOverscan (readout, config, biasCols, biasRows, rng);
+                if (!ppSimAddNoise(readout->image, readout->weight, cell, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding noise");
+                if (!ppSimSaturate(readout, config)) ESCAPE (PS_ERR_UNKNOWN, "problem setting saturation levels");
+
+                if (!ppSimBadPixels(readout, config, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding bad pixels");
+
+                if (!ppSimAddOverscan (readout, config, biasCols, biasRows, rng)) ESCAPE (PS_ERR_UNKNOWN, "problem adding overscan region");
                 psFree(biasRows);
 
@@ -148,11 +164,15 @@
                 readout->parent->data_exists = true;
                 readout->parent->parent->data_exists = true;
+
+		// if there is an input image, merge it with the simulated image
+		if (!ppSimMergeReadouts (config, view)) ESCAPE (PS_ERR_UNKNOWN, "problem merging input image with simulated image");
             }
             psFree(biasCols);
 
-            ppSimUpdateConceptsCell (cell, config);
+            if (!ppSimUpdateConceptsCell (cell, config)) ESCAPE (PS_ERR_UNKNOWN, "problem updating cell concepts");
 
             if (cell->hdu) {
-                ppSimInitHeader(config, NULL, NULL, cell);
+		// XXX only do this if there is no INPUT image?
+                if (!ppSimInitHeader(config, NULL, NULL, cell)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
             }
 
@@ -166,7 +186,13 @@
         }
 
+	// XXX why no UpdateConceptsChip??
+
         if (chip->hdu) {
-            ppSimInitHeader(config, NULL, chip, NULL);
-        }
+	    // XXX only do this if there is no INPUT image
+            if (!ppSimInitHeader(config, NULL, chip, NULL)) ESCAPE (PS_ERR_UNKNOWN, "problem setting output header");
+        }
+
+        // we perform photometry on the readouts of this chip in the output
+	if (!ppSimPhotom (config, view)) ESCAPE (PS_ERR_UNKNOWN, "problem performing photometry");
 
         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
@@ -174,16 +200,10 @@
             psFree(rng);
             psFree(view);
-            // return PS_EXIT_SYS_ERROR;
             return false;
         }
-
     }
 
     psFree(stars);
     psFree(galaxies);
-
-    if (fpa->hdu) {
-        ppSimInitHeader(config, fpa, NULL, NULL);
-    }
 
     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
@@ -191,5 +211,4 @@
         psFree(rng);
         psFree(view);
-        // return PS_EXIT_SYS_ERROR;
         return false;
     }
