Index: branches/tap_branches/ppSub/src/ppSubCamera.c
===================================================================
--- branches/tap_branches/ppSub/src/ppSubCamera.c	(revision 25900)
+++ branches/tap_branches/ppSub/src/ppSubCamera.c	(revision 27838)
@@ -23,5 +23,6 @@
 
 // Define an input file
-static pmFPAfile *defineInputFile(pmConfig *config,// Configuration
+static pmFPAfile *defineInputFile(bool *success,
+                                  pmConfig *config,// Configuration
                                   pmFPAfile *bind,    // File to which to bind, or NULL
                                   char *filerule,     // Name of file rule
@@ -32,32 +33,40 @@
     bool status;
 
-    // look for the file on the RUN metadata
-    pmFPAfile *file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
+    *success = false;
+
+    pmFPAfile *file = NULL;
+
+    // look for the file on the argument list
+    if (bind) {
+        file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
+    } else {
+        file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
+    }
+
     if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
-        return NULL;
+        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
+        return false;
     }
     if (!file) {
-        // look for the file on the argument list
-        if (bind) {
-            file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
-        } else {
-            file = pmFPAfileDefineFromArgs(&status, config, filerule, argname);
-        }
+        // look for the file on the RUN metadata
+        file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
         if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
-            return false;
+            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
+            return NULL;
         }
     }
 
     if (!file) {
+        // no file defined
+        *success = true;
         return NULL;
     }
 
     if (file->type != fileType) {
-        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
-        return NULL;
-    }
-
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        return NULL;
+    }
+
+    *success = true;
     return file;
 }
@@ -75,9 +84,9 @@
         pmFPAfileDefineOutput(config, template->fpa, filerule);
     if (!file) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from %s"), filerule);
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from %s"), filerule);
         return NULL;
     }
     if (file->type != fileType) {
-        psError(PS_ERR_IO, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
         return NULL;
     }
@@ -92,4 +101,5 @@
                                  pmFPAfile *bind,    // File to which to bind, or NULL
                                  char *filerule,     // Name of file rule
+                                 const char *argname,   // Argument name for file
                                  pmFPAfileType fileType // Type of file
     )
@@ -98,7 +108,12 @@
 
     // look for the file on the RUN metadata
-    pmFPAfile *file = pmFPAfileDefineFromRun(&status, bind, config, filerule); // File to return
+    pmFPAfile *file = pmFPAfileDefineFromRun(&status, NULL, config, filerule); // File to return
     if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
+        return NULL;
+    }
+    file = pmFPAfileBindFromArgs(&status, bind, config, filerule, argname);
+    if (!status) {
+        psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
         return NULL;
     }
@@ -112,5 +127,5 @@
         file = pmFPAfileDefineOutput(config, bind ? bind->fpa : NULL, filerule);
         if (!status) {
-            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+            psError(psErrorCodeLast(), false, "Failed to load file definition for %s", filerule);
             return false;
         }
@@ -126,5 +141,5 @@
 
     if (file->type != fileType) {
-        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        psError(PPSUB_ERR_CONFIG, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
         return NULL;
     }
@@ -136,4 +151,6 @@
 bool ppSubCamera(ppSubData *data)
 {
+    bool success = true;
+
     psAssert(data, "Require processing data");
     pmConfig *config = data->config;
@@ -141,30 +158,57 @@
 
     // Input image
-    pmFPAfile *input = defineInputFile(config, NULL, "PPSUB.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
-    if (!input) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.INPUT");
-        return false;
-    }
-    defineInputFile(config, input, "PPSUB.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK);
-    pmFPAfile *inVar = defineInputFile(config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE",
-                                       PM_FPA_FILE_VARIANCE);
-    defineInputFile(config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
+    pmFPAfile *input = defineInputFile(&success, config, NULL, "PPSUB.INPUT", "INPUT", PM_FPA_FILE_IMAGE);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT");
+        return false;
+    }
+
+    defineInputFile(&success, config, input, "PPSUB.INPUT.MASK", "INPUT.MASK", PM_FPA_FILE_MASK);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.MASK");
+        return false;
+    }
+
+    pmFPAfile *inVar = defineInputFile(&success, config, input, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE", PM_FPA_FILE_VARIANCE);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.VARIANCE");
+        return false;
+    }
+
+    defineInputFile(&success, config, NULL, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.INPUT.SOURCES");
+        return false;
+    }
 
     // Reference image
-    pmFPAfile *ref = defineInputFile(config, NULL, "PPSUB.REF", "REF", PM_FPA_FILE_IMAGE);
-    if (!ref) {
-        psError(PS_ERR_IO, false, "Failed to build FPA from PPSUB.REF");
-        return false;
-    }
-    defineInputFile(config, ref, "PPSUB.REF.MASK", "REF.MASK", PM_FPA_FILE_MASK);
-    pmFPAfile *refVar = defineInputFile(config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE",
-                                        PM_FPA_FILE_VARIANCE);
-    defineInputFile(config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
-
+    pmFPAfile *ref = defineInputFile(&success, config, NULL, "PPSUB.REF", "REF", PM_FPA_FILE_IMAGE);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF");
+        return false;
+    }
+
+    defineInputFile(&success, config, ref, "PPSUB.REF.MASK", "REF.MASK", PM_FPA_FILE_MASK);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.MASK");
+        return false;
+    }
+
+    pmFPAfile *refVar = defineInputFile(&success, config, ref, "PPSUB.REF.VARIANCE", "REF.VARIANCE", PM_FPA_FILE_VARIANCE);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.VARIANCE");
+        return false;
+    }
+
+    defineInputFile(&success, config, NULL, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
+    if (!success) {
+        psError(psErrorCodeLast(), false, "Failed to build FPA from PPSUB.REF.SOURCES");
+        return false;
+    }
 
     // Now that the camera has been determined, we can read the recipe
     psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, PPSUB_RECIPE); // Recipe for ppSim
     if (!recipe) {
-        psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find recipe %s", PPSUB_RECIPE);
+        psError(PPSUB_ERR_CONFIG, false, "Unable to find recipe %s", PPSUB_RECIPE);
         return false;
     }
@@ -180,7 +224,4 @@
     data->inverse = psMetadataLookupBool(NULL, recipe, "INVERSE");
     data->photometry = psMetadataLookupBool(NULL, recipe, "PHOTOMETRY");
-
-    bool mdok;                          // Status of MD lookup
-    bool saveConv = psMetadataLookupBool(&mdok, recipe, "SAVE.CONVOLVED"); // Save convolved images?
 
     // Convolved input image
@@ -189,21 +230,17 @@
                                              PM_FPA_FILE_MASK);
     if (!inConvImage || !inConvMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
-        return false;
-    }
-    if (saveConv) {
-        inConvImage->save = true;
-        inConvMask->save = true;
-    }
+        psError(psErrorCodeLast(), false, "Unable to define output files");
+        return false;
+    }
+    inConvImage->save = data->saveInConv;
+    inConvMask->save = data->saveInConv;
     if (inVar) {
         pmFPAfile *inConvVar = defineOutputFile(config, inConvImage, false, "PPSUB.INPUT.CONV.VARIANCE",
                                                 PM_FPA_FILE_VARIANCE);
         if (!inConvVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
-            return false;
-        }
-        if (saveConv) {
-            inConvVar->save = true;
-        }
+            psError(psErrorCodeLast(), false, "Unable to define output files");
+            return false;
+        }
+        inConvVar->save = data->saveInConv;
     }
 
@@ -213,21 +250,17 @@
                                               PM_FPA_FILE_MASK);
     if (!refConvImage || !refConvMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
-        return false;
-    }
-    if (saveConv) {
-        refConvImage->save = true;
-        refConvMask->save = true;
-    }
+        psError(psErrorCodeLast(), false, "Unable to define output files");
+        return false;
+    }
+    refConvImage->save = data->saveRefConv;
+    refConvMask->save = data->saveRefConv;
     if (refVar) {
         pmFPAfile *refConvVar = defineOutputFile(config, refConvImage, false, "PPSUB.REF.CONV.VARIANCE",
                                                  PM_FPA_FILE_VARIANCE);
         if (!refConvVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
-            return false;
-        }
-        if (saveConv) {
-            refConvVar->save = true;
-        }
+            psError(psErrorCodeLast(), false, "Unable to define output files");
+            return false;
+        }
+        refConvVar->save = data->saveRefConv;
     }
 
@@ -236,5 +269,5 @@
     pmFPAfile *outMask = defineOutputFile(config, output, false, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
     if (!output || !outMask) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+        psError(psErrorCodeLast(), false, "Unable to define output files");
         return false;
     }
@@ -245,5 +278,5 @@
                                              PM_FPA_FILE_VARIANCE);
         if (!outVar) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -258,5 +291,5 @@
                                               PM_FPA_FILE_MASK);
         if (!inverse || !invMask) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            psError(psErrorCodeLast(), false, "Unable to define output files");
             return false;
         }
@@ -267,5 +300,5 @@
                                                  PM_FPA_FILE_VARIANCE);
             if (!invVar) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+                psError(psErrorCodeLast(), false, "Unable to define output files");
                 return false;
             }
@@ -278,9 +311,9 @@
     pmFPAfile *jpeg1 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG1");
     if (!jpeg1) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG1"));
         return false;
     }
     if (jpeg1->type != PM_FPA_FILE_JPEG) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG1 is not of type JPEG");
         return false;
     }
@@ -288,15 +321,28 @@
     pmFPAfile *jpeg2 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.JPEG2");
     if (!jpeg2) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.JPEG2"));
         return false;
     }
     if (jpeg2->type != PM_FPA_FILE_JPEG) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.JPEG2 is not of type JPEG");
         return false;
     }
     jpeg2->save = true;
 
+    // Output residual JPEG
+    pmFPAfile *jpeg3 = pmFPAfileDefineOutput(config, NULL, "PPSUB.OUTPUT.RESID.JPEG");
+    if (!jpeg3) {
+        psError(psErrorCodeLast(), false, _("Unable to generate output file from PPSUB.OUTPUT.RESID.JPEG"));
+        return false;
+    }
+    if (jpeg3->type != PM_FPA_FILE_JPEG) {
+        psError(psErrorCodeLast(), true, "PPSUB.OUTPUT.RESID.JPEG is not of type JPEG");
+        return false;
+    }
+    jpeg3->save = true;
+
     // Output subtraction kernel
-    pmFPAfile *kernel = defineCalcFile(config, output, "PPSUB.OUTPUT.KERNELS", PM_FPA_FILE_SUBKERNEL);
+    pmFPAfile *kernel = defineCalcFile(config, output, "PPSUB.OUTPUT.KERNELS", "KERNEL",
+                                       PM_FPA_FILE_SUBKERNEL);
     if (!kernel) {
         psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to define file PPSUB.OUTPUT.KERNELS");
@@ -305,26 +351,28 @@
 
     // psPhot input
-    if (data->photometry) {
+    if (data->photometry || 1) {
         psphotModelClassInit();        // load implementation-specific models
 
         pmFPAfile *psphot = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.INPUT");
         if (!psphot) {
-            psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.INPUT");
+            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.INPUT");
             return false;
         }
         if (psphot->type != PM_FPA_FILE_IMAGE) {
-            psError(PS_ERR_IO, true, "PSPHOT.INPUT is not of type IMAGE");
-            return false;
-        }
+            psError(psErrorCodeLast(), true, "PSPHOT.INPUT is not of type IMAGE");
+            return false;
+        }
+        // specify the number of psphot input images
+        psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
         pmFPAfileActivate(config->files, false, "PSPHOT.INPUT");
 
-        // Internal-ish file for getting the PSF from the minuend
-        pmFPAfile *psf = pmFPAfileDefineOutputFromFile(config, psphot, "PSPHOT.PSF.LOAD");
+        // Internal file for getting the PSF from the minuend
+        pmFPAfile *psf = pmFPAfileDefineFromFPA(config, output->fpa, 1, 1, "PSPHOT.PSF.LOAD");
         if (!psf) {
-            psError(PS_ERR_IO, false, "Failed to build FPA from PSPHOT.PSF.LOAD");
+            psError(psErrorCodeLast(), false, "Failed to build FPA from PSPHOT.PSF.LOAD");
             return false;
         }
         if (psf->type != PM_FPA_FILE_PSF) {
-            psError(PS_ERR_IO, true, "PSPHOT.PSF.LOAD is not of type PSF");
+            psError(psErrorCodeLast(), true, "PSPHOT.PSF.LOAD is not of type PSF");
             return false;
         }
@@ -332,5 +380,5 @@
 
         if (!psphotDefineFiles(config, psphot)) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to set up psphot files.");
+            psError(psErrorCodeLast(), false, "Unable to set up psphot files.");
             return false;
         }
@@ -343,5 +391,5 @@
                                                  PM_FPA_FILE_CMF);
         if (!outSources) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to set up output source file.");
+            psError(psErrorCodeLast(), false, "Unable to set up output source file.");
             return false;
         }
@@ -352,5 +400,5 @@
                                                      PM_FPA_FILE_CMF);
             if (!invSources) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to set up inverse source file.");
+                psError(psErrorCodeLast(), false, "Unable to set up inverse source file.");
                 return false;
             }
