Index: trunk/ppSub/src/ppSubArguments.c
===================================================================
--- trunk/ppSub/src/ppSubArguments.c	(revision 23289)
+++ trunk/ppSub/src/ppSubArguments.c	(revision 23298)
@@ -29,5 +29,5 @@
 {
     fprintf(stderr, "\nPan-STARRS PSF-matched image subtraction\n\n");
-    fprintf(stderr, "Usage: %s INPUT.fits REFERENCE.fits OUTPUT_ROOT \n"
+    fprintf(stderr, "Usage: %s OUTPUT_ROOT \n"
             "\t[-psf REFERENCE.psf.fits]\n\n"
             "This subtracts the convolved REFERENCE from the INPUT, by default.\n",
@@ -202,10 +202,13 @@
 
     psMetadata *arguments = config->arguments; // Command-line arguments
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-inimage", 0, "Input image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-inmask", 0, "Input mask image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-invariance", 0, "Input variance image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-insources", 0, "Input source list", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-refimage", 0, "Reference image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-refmask", 0, "Reference mask image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-refvariance", 0, "Reference variance image", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-refsources", 0, "Reference source list", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-kernel", 0, "Precalculated kernel to apply", NULL);
     psMetadataAddStr(arguments, PS_LIST_TAIL, "-stats", 0, "Statistics file", NULL);
     psMetadataAddF32(arguments, PS_LIST_TAIL, "-region", 0, "Size of iso-kernel region", NAN);
@@ -253,12 +256,15 @@
     psMetadataAddBool(arguments, PS_LIST_TAIL, "-visual", 0, "Show diagnostic plots", NULL);
 
-    if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 4) {
+    if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 2) {
         usage(argv[0], arguments, config);
     }
 
-    fileList("INPUT", argv[1], "Name of the input image",     config);
-    fileList("REF",   argv[2], "Name of the reference image", config);
     psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[3]);
 
+
+    const char *inImage = psMetadataLookupStr(NULL, arguments, "-inimage"); // Name of input image
+    if (inImage && strlen(inImage) > 0) {
+        fileList("INPUT", inImage, "Name of the input image", config);
+    }
     const char *inMask = psMetadataLookupStr(NULL, arguments, "-inmask"); // Name of input mask
     if (inMask && strlen(inMask) > 0) {
@@ -274,4 +280,8 @@
     }
 
+    const char *refImage = psMetadataLookupStr(NULL, arguments, "-refimage"); // Name of reference image
+    if (refImage && strlen(refImage) > 0) {
+        fileList("INPUT", refImage, "Name of the reference image", config);
+    }
     const char *refMask = psMetadataLookupStr(NULL, arguments, "-refmask"); // Name of reference mask
     if (refMask && strlen(refMask) > 0) {
@@ -285,4 +295,9 @@
     if (refSources && strlen(refSources) > 0) {
         fileList("REF.SOURCES", refSources, "Name of the reference source list", config);
+    }
+
+    const char *kernel = psMetadataLookupStr(NULL, arguments, "-kernel"); // Name of kernel
+    if (kernel && strlen(kernel) > 0) {
+        fileList("KERNEL", kernel, "Name of the kernel to apply", config);
     }
 
Index: trunk/ppSub/src/ppSubCamera.c
===================================================================
--- trunk/ppSub/src/ppSubCamera.c	(revision 23289)
+++ trunk/ppSub/src/ppSubCamera.c	(revision 23298)
@@ -22,210 +22,175 @@
 #include "ppSub.h"
 
+// Define an input file
+static pmFPAfile *defineInputFile(pmConfig *config,// Configuration
+                                  pmFPAfile *bind,    // File to which to bind, or NULL
+                                  char *filerule,     // Name of file rule
+                                  char *argname,      // Argument name
+                                  pmFPAfileType fileType // Type of file
+    )
+{
+    bool status;
+
+    // look for the file on the RUN metadata
+    pmFPAfile *file = pmFPAfileDefineFromRun(&status, config, filerule); // File to return
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+        return NULL;
+    }
+    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);
+        }
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+            return false;
+        }
+    }
+
+    if (!file) {
+        return NULL;
+    }
+
+    if (file->type != fileType) {
+        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        return NULL;
+    }
+
+    return file;
+}
+
+// Define an output file
+static pmFPAfile *defineOutputFile(pmConfig *config, // Configuration
+                                   pmFPAfile *template,    // File to use as basis for definition
+                                   char *filerule,     // Name of file rule
+                                   pmFPAfileType fileType // Type of file
+    )
+{
+
+    pmFPAfile *file = pmFPAfileDefineFromFile(config, template, 1, 1, filerule);
+    if (!file) {
+        psError(PS_ERR_IO, 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));
+        return NULL;
+    }
+
+    return file;
+}
+
+
+// Define an output file that will be used in a calculation
+// This means it might already be available in the RUN metadata
+static pmFPAfile *defineCalcFile(pmConfig *config, // Configuration
+                                 pmFPAfile *bind,    // File to which to bind, or NULL
+                                 char *filerule,     // Name of file rule
+                                 pmFPAfileType fileType // Type of file
+    )
+{
+    bool status;
+
+    // look for the file on the RUN metadata
+    pmFPAfile *file = pmFPAfileDefineFromRun(&status, config, filerule); // File to return
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+        return NULL;
+    }
+    if (file) {
+        // It's an input
+        file->save = false;
+    }
+
+    // define new version of file
+    if (!file) {
+        pmFPAfileDefineOutput(config, bind ? bind->fpa : NULL, filerule);
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Failed to load file definition for %s", filerule);
+            return false;
+        }
+        if (file) {
+            // It's an output
+            file->save = true;
+        }
+    }
+
+    if (!file) {
+        return NULL;
+    }
+
+    if (file->type != fileType) {
+        psError(PS_ERR_UNKNOWN, true, "%s is not of type %s", filerule, pmFPAfileStringFromType(fileType));
+        return NULL;
+    }
+
+    return file;
+}
+
+
 bool ppSubCamera(pmConfig *config)
 {
-    bool status = false;                // result from pmFPAfileDefine operations
+    psAssert(config, "Require configuration");
 
     // Input image
-    pmFPAfile *input = pmFPAfileDefineFromArgs(&status, config, "PPSUB.INPUT", "INPUT");
-    if (!status || !input) {
+    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;
     }
-    if (input->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT is not of type IMAGE");
-        return false;
-    }
-
-    // Input mask
-    pmFPAfile *inputMask = pmFPAfileBindFromArgs(&status, input, config, "PPSUB.INPUT.MASK", "INPUT.MASK");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.INPUT.MASK");
-        return NULL;
-    }
-    if (inputMask && inputMask->type != PM_FPA_FILE_MASK) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT.MASK is not of type MASK");
-        return false;
-    }
-
-    // Input variance map
-    pmFPAfile *inputVariance = pmFPAfileBindFromArgs(&status, input, config, "PPSUB.INPUT.VARIANCE", "INPUT.VARIANCE");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.INPUT.VARIANCE");
-        return NULL;
-    }
-    if (inputVariance && inputVariance->type != PM_FPA_FILE_VARIANCE) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT.VARIANCE is not of type VARIANCE");
-        return false;
-    }
-
-    // Input source list
-    pmFPAfile *inputSources = pmFPAfileBindFromArgs(&status, input, config, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.INPUT.SOURCES");
-        return NULL;
-    }
-    if (inputSources && inputSources->type != PM_FPA_FILE_CMF) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT.SOURCES is not of type CMF");
-        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, input, "PPSUB.INPUT.SOURCES", "INPUT.SOURCES", PM_FPA_FILE_CMF);
 
     // Reference image
-    status = false;
-    pmFPAfile *ref = pmFPAfileDefineFromArgs(&status, config, "PPSUB.REF", "REF");
+    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;
     }
-    if (ref->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSUB.REF is not of type IMAGE");
-        return false;
-    }
-
-    // Reference mask
-    pmFPAfile *refMask = pmFPAfileBindFromArgs(&status, ref, config, "PPSUB.REF.MASK", "REF.MASK");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.REF.MASK");
-        return NULL;
-    }
-    if (refMask && refMask->type != PM_FPA_FILE_MASK) {
-        psError(PS_ERR_IO, true, "PPSUB.REF.MASK is not of type MASK");
-        return false;
-    }
-
-    // Reference variance map
-    pmFPAfile *refVariance = pmFPAfileBindFromArgs(&status, ref, config, "PPSUB.REF.VARIANCE", "REF.VARIANCE");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.REF.VARIANCE");
-        return NULL;
-    }
-    if (refVariance && refVariance->type != PM_FPA_FILE_VARIANCE) {
-        psError(PS_ERR_IO, true, "PPSUB.REF.VARIANCE is not of type VARIANCE");
-        return false;
-    }
-
-    // Reference source list
-    pmFPAfile *refSources = pmFPAfileBindFromArgs(&status, ref, config, "PPSUB.REF.SOURCES", "REF.SOURCES");
-    if (!status) {
-        psError(PS_ERR_UNKNOWN, false, "Failed to load file definition PPSUB.REF.SOURCES");
-        return NULL;
-    }
-    if (refSources && refSources->type != PM_FPA_FILE_CMF) {
-        psError(PS_ERR_IO, true, "PPSUB.REF.SOURCES is not of type CMF");
-        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, ref, "PPSUB.REF.SOURCES", "REF.SOURCES", PM_FPA_FILE_CMF);
+
 
     // Output image
-    pmFPAfile *output = pmFPAfileDefineFromFile(config, input, 1, 1, "PPSUB.OUTPUT");
-    if (!output) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT"));
-        return false;
-    }
-    if (output->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT is not of type IMAGE");
+    pmFPAfile *output = defineOutputFile(config, input, "PPSUB.OUTPUT", PM_FPA_FILE_IMAGE);
+    pmFPAfile *outMask = defineOutputFile(config, output, "PPSUB.OUTPUT.MASK", PM_FPA_FILE_MASK);
+    if (!output || !outMask) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
         return false;
     }
     output->save = true;
-
-    // Output mask
-    pmFPAfile *outMask = pmFPAfileDefineOutput(config, output->fpa, "PPSUB.OUTPUT.MASK");
-    if (!outMask) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.MASK"));
-        return false;
-    }
-    if (outMask->type != PM_FPA_FILE_MASK) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.MASK is not of type MASK");
-        return false;
-    }
     outMask->save = true;
-
-    // Output variance
-    if (inputVariance && refVariance) {
-        pmFPAfile *outVariance = pmFPAfileDefineOutput(config, output->fpa, "PPSUB.OUTPUT.VARIANCE");
-        if (!outVariance) {
-            psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.VARIANCE"));
-            return false;
-        }
-        if (outVariance->type != PM_FPA_FILE_VARIANCE) {
-            psError(PS_ERR_IO, true, "PPSUB.OUTPUT.VARIANCE is not of type VARIANCE");
-            return false;
-        }
-        outVariance->save = true;
-    }
+    pmFPAfile *outVar = NULL;
+    if (inVar && refVar) {
+        outVar = defineOutputFile(config, output, "PPSUB.OUTPUT.VARIANCE", PM_FPA_FILE_VARIANCE);
+        if (!outVar) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define output files");
+            return false;
+        }
+        outVar->save = true;
+    }
+
 
     // Convolved input image
-    pmFPAfile *inConv = pmFPAfileDefineFromFile(config, input, 1, 1, "PPSUB.INPUT.CONV");
-    if (!inConv) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file for PPSUB.INPUT.CONV"));
-        return false;
-    }
-    if (output->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT.CONV is not of type IMAGE");
-        return false;
-    }
-    // XXX should be based on recipe : inConv->save = true;
-
-    // Convolved input mask
-    pmFPAfile *inConvMask = pmFPAfileDefineOutput(config, inConv->fpa, "PPSUB.INPUT.CONV.MASK");
-    if (!inConvMask) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.INPUT.CONV.MASK"));
-        return false;
-    }
-    if (inConvMask->type != PM_FPA_FILE_MASK) {
-        psError(PS_ERR_IO, true, "PPSUB.INPUT.CONV.MASK is not of type MASK");
-        return false;
-    }
-    // XXX should be based on recipe : inConvMask->save = true;
-
-    // Convolved input variance
-    if (inputVariance) {
-        pmFPAfile *inConvVariance = pmFPAfileDefineOutput(config, inConv->fpa, "PPSUB.INPUT.CONV.VARIANCE");
-        if (!inConvVariance) {
-            psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.VARIANCE"));
-            return false;
-        }
-        if (inConvVariance->type != PM_FPA_FILE_VARIANCE) {
-            psError(PS_ERR_IO, true, "PPSUB.INPUT.CONV.VARIANCE is not of type VARIANCE");
-            return false;
-        }
-        // XXX should be based on recipe : inConvVariance->save = true;
+    defineOutputFile(config, input, "PPSUB.INPUT.CONV", PM_FPA_FILE_IMAGE);
+    defineOutputFile(config, input, "PPSUB.INPUT.CONV.MASK", PM_FPA_FILE_MASK);
+    if (inVar) {
+        defineOutputFile(config, input, "PPSUB.INPUT.CONV.VARIANCE", PM_FPA_FILE_VARIANCE);
     }
 
     // Convolved ref image
-    pmFPAfile *refConv = pmFPAfileDefineFromFile(config, ref, 1, 1, "PPSUB.REF.CONV");
-    if (!refConv) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file for PPSUB.REF.CONV"));
-        return false;
-    }
-    if (output->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSUB.REF.CONV is not of type IMAGE");
-        return false;
-    }
-    // XXX should be based on recipe : refConv->save = true;
-
-    // Convolved ref mask
-    pmFPAfile *refConvMask = pmFPAfileDefineOutput(config, refConv->fpa, "PPSUB.REF.CONV.MASK");
-    if (!refConvMask) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.REF.CONV.MASK"));
-        return false;
-    }
-    if (refConvMask->type != PM_FPA_FILE_MASK) {
-        psError(PS_ERR_IO, true, "PPSUB.REF.CONV.MASK is not of type MASK");
-        return false;
-    }
-    // XXX should be based on recipe : refConvMask->save = true;
-
-    // Convolved ref variance
-    if (refVariance) {
-        pmFPAfile *refConvVariance = pmFPAfileDefineOutput(config, refConv->fpa, "PPSUB.REF.CONV.VARIANCE");
-        if (!refConvVariance) {
-            psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.VARIANCE"));
-            return false;
-        }
-        if (refConvVariance->type != PM_FPA_FILE_VARIANCE) {
-            psError(PS_ERR_IO, true, "PPSUB.REF.CONV.VARIANCE is not of type VARIANCE");
-            return false;
-        }
-        // XXX should be based on recipe : refConvVariance->save = true;
-    }
+    defineOutputFile(config, input, "PPSUB.REF.CONV", PM_FPA_FILE_IMAGE);
+    defineOutputFile(config, input, "PPSUB.REF.CONV.MASK", PM_FPA_FILE_MASK);
+    if (refVar) {
+        defineOutputFile(config, input, "PPSUB.REF.CONV.VARIANCE", PM_FPA_FILE_VARIANCE);
+    }
+
 
     // Output JPEGs
@@ -252,14 +217,5 @@
 
     // Output subtraction kernel
-    pmFPAfile *outKernels = pmFPAfileDefineOutput(config, output->fpa, "PPSUB.OUTPUT.KERNELS");
-    if (!outKernels) {
-        psError(PS_ERR_IO, false, _("Unable to generate output file from PPSUB.OUTPUT.KERNELS"));
-        return false;
-    }
-    if (outKernels->type != PM_FPA_FILE_SUBKERNEL) {
-        psError(PS_ERR_IO, true, "PPSUB.OUTPUT.KERNELS is not of type SUBKERNEL");
-        return false;
-    }
-    outKernels->save = true;
+    pmFPAfile *kernel = defineCalcFile(config, output, "PPSUB.OUTPUT.KERNELS", PM_FPA_FILE_SUBKERNEL);
 
 
