Index: trunk/ppStack/src/ppStackCamera.c
===================================================================
--- trunk/ppStack/src/ppStackCamera.c	(revision 21366)
+++ trunk/ppStack/src/ppStackCamera.c	(revision 23357)
@@ -11,20 +11,27 @@
 #include "ppStack.h"
 
-
-#if 0
-// Define an output convolved image file
-static pmFPAfile *defineOutputConvolved(const char *name, // FPA file name
-                                        pmFPA *fpa, // FPA to bind
-                                        const pmConfig *config, // Configuration
-                                        pmFPAfileType type // Expected type
-    )
+// Define a file
+static pmFPAfile *defineFile(pmConfig *config, // Configuration
+                             pmFPAfile *bind, // File to which to bind
+                             const char *name, // Name of file rule
+                             const char *filename, // Name of file
+                             pmFPAfileType type // Type of file
+                             )
 {
-    pmFPAfile *file = pmFPAfileDefineOutput(config, fpa, name);
-    if (!file) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define output convolved file %s", name);
+
+    psArray *dummy = psArrayAlloc(1);   // Dummy array of filenames for this FPA
+    dummy->data[0] = psStringCopy(filename);
+    psMetadataAddArray(config->arguments, PS_LIST_TAIL, "FILENAMES", PS_META_REPLACE,
+                       "Filenames for file rule definition", dummy);
+    psFree(dummy);
+
+    bool found = false;             // Found the file?
+    pmFPAfile *file = pmFPAfileDefineFromArgs(&found, config, name, "FILENAMES");
+    if (!file || !found) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to define file %s from %s", name, filename);
         return NULL;
     }
-    if (file->type != PM_FPA_FILE_IMAGE) {
-        psError(PS_ERR_IO, true, "PPSTACK.OUTCONV is not of type %s", pmFPAfileStringFromType(type));
+    if (file->type != type) {
+        psError(PS_ERR_IO, true, "%s is not of type %s", name, pmFPAfileStringFromType(type));
         return NULL;
     }
@@ -33,228 +40,176 @@
 }
 
-// Define an input convolved image file, using the output as a basis
-static pmFPAfile *defineInputConvolved(const char *inputName, // Input FPA file name
-                                       pmFPAfile *outFile, // Corresponding output FPA file
-                                       pmConfig *config, // Configuration
-                                       pmFPAfileType type // Expected type
-    )
-{
-    pmFPAview *view = pmFPAviewAlloc(0); // View into sky cells
-    view->chip = view->cell = view->readout = 0;
-
-    psString imageName = pmFPANameFromRule(outFile->filerule, outFile->fpa, view);
-    psArray *imageNames = psArrayAlloc(1);
-    imageNames->data[0] = imageName;
-    psMetadataAddArray(config->arguments, PS_LIST_TAIL, "INCONV.FILENAMES", PS_META_REPLACE,
-                       "Filenames of input convolved image files", imageNames);
-    psFree(imageNames);
-    bool found = false;                 // Found the file?
-    pmFPAfile *imageFile = pmFPAfileDefineFromArgs(&found, config, "PPSTACK.INCONV",
-                                                   "INCONV.FILENAMES");
-    psMetadataRemoveKey(config->arguments, "INCONV.FILENAMES");
-    if (!imageFile || !found) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to define %s file", inputName);
-        return NULL;
-    }
-    if (imageFile->type != type) {
-        psError(PS_ERR_IO, true, "PPSTACK.INCONV is not of type %s",
-                pmFPAfileStringFromType(type));
-        return NULL;
-    }
-
-    return imageFile;
-}
-#endif
-
 
 
 bool ppStackCamera(pmConfig *config)
 {
-    bool haveVariances = false;           // Do we have variance maps?
+    int num = 0;                        // Number of inputs
+    bool haveVariances = false;         // Do we have variance maps?
     bool havePSFs = false;              // Do we have PSFs?
 
-    psMetadata *inputs = psMetadataLookupMetadata(NULL, config->arguments, "INPUTS"); // The inputs info
-    psMetadataIterator *iter = psMetadataIteratorAlloc(inputs, PS_LIST_HEAD, NULL); // Iterator
-    psMetadataItem *item;               // Item from iteration
-    int i = 0;                          // Counter
-    while ((item = psMetadataGetAndIncrement(iter))) {
-        if (item->type != PS_DATA_METADATA) {
-            psError(PS_ERR_BAD_PARAMETER_TYPE, true,
-                    "Component %s of the input metadata is not of type METADATA", item->name);
-            psFree(iter);
-            return false;
-        }
-
-        psMetadata *input = item->data.md; // The input metadata of interest
-
-        psString image = psMetadataLookupStr(NULL, input, "IMAGE"); // Name of image
-        if (!image || strlen(image) == 0) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s lacks IMAGE of type STR", item->name);
-            psFree(iter);
-            return false;
-        }
-
-        bool mdok;
-        psString mask = psMetadataLookupStr(&mdok, input, "MASK"); // Name of mask
-        psString variance = psMetadataLookupStr(&mdok, input, "VARIANCE"); // Name of variance map
-        psString psf = psMetadataLookupStr(&mdok, input, "PSF"); // Name of PSF
-        psString sources = psMetadataLookupStr(&mdok, input, "SOURCES"); // Name of sources
-
-        // Add the image file
-        psArray *imageFiles = psArrayAlloc(1); // Array of filenames for this FPA
-        imageFiles->data[0] = psMemIncrRefCounter(image);
-        psMetadataAddArray(config->arguments, PS_LIST_TAIL, "IMAGE.FILENAMES", PS_META_REPLACE,
-                           "Filenames of image files", imageFiles);
-        psFree(imageFiles);
-
-        bool found = false;             // Found the file?
-        pmFPAfile *imageFile = pmFPAfileDefineFromArgs(&found, config, "PPSTACK.INPUT", "IMAGE.FILENAMES");
-        if (!imageFile || !found) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, image);
-            return false;
-        }
-        if (imageFile->type != PM_FPA_FILE_IMAGE) {
-            psError(PS_ERR_IO, true, "PPSTACK.INPUT is not of type IMAGE");
-            return false;
-        }
-
-        // Optionally add the mask file
-        if (mask && strlen(mask) > 0) {
-            psArray *maskFiles = psArrayAlloc(1); // Array of filenames for this FPA
-            maskFiles->data[0] = psMemIncrRefCounter(mask);
-            psMetadataAddArray(config->arguments, PS_LIST_TAIL, "MASK.FILENAMES", PS_META_REPLACE,
-                               "Filenames of mask files", maskFiles);
-            psFree(maskFiles);
-
-            bool status;
-            pmFPAfile *maskFile = pmFPAfileBindFromArgs(&status, imageFile, config, "PPSTACK.INPUT.MASK",
-                                                        "MASK.FILENAMES");
-            if (!status) {
+    bool status = false;                // Status of file definition
+
+    psArray *runImages = pmFPAfileDefineMultipleFromRun(&status, NULL, config,
+                                                        "PPSTACK.INPUT"); // Input images from previous run
+    if (runImages) {
+        // Defining files from the RUN metadata
+        num = runImages->n;
+
+        psArray *runMasks = pmFPAfileDefineMultipleFromRun(&status, runImages, config,
+                                                           "PPSTACK.INPUT.MASK"); // Input masks
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define input masks from RUN metadata.");
+            psFree(runImages);
+            return false;
+        }
+        psFree(runMasks);
+
+        psArray *runVars = pmFPAfileDefineMultipleFromRun(&status, runImages, config,
+                                                          "PPSTACK.INPUT.VARIANCE"); // Input variances
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define input variances from RUN metadata.");
+            psFree(runImages);
+            return false;
+        }
+        if (runVars) {
+            haveVariances = true;
+        }
+        psFree(runVars);
+
+        psArray *runPSF = pmFPAfileDefineMultipleFromRun(&status, runImages, config,
+                                                         "PPSTACK.INPUT.PSF"); // Input PSFs
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define input PSFs from RUN metadata.");
+            psFree(runImages);
+            return false;
+        }
+        if (runPSF) {
+            havePSFs = true;
+        }
+        psFree(runPSF);
+
+        psArray *runSrc = pmFPAfileDefineMultipleFromRun(&status, runImages, config,
+                                                         "PPSTACK.INPUT.SOURCES"); // Input sources
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define input sources from RUN metadata.");
+            psFree(runImages);
+            return false;
+        }
+        if (!runSrc) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to define input sources from RUN metadta.");
+            psFree(runImages);
+            return false;
+        }
+        psFree(runSrc);
+
+        psArray *runKernel = pmFPAfileDefineMultipleFromRun(&status, runImages, config,
+                                                            "PPSTACK.CONV.KERNEL"); // Convolution kernels
+        if (!status) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to define convolution kernels from RUN metadata.");
+            psFree(runImages);
+            return false;
+        }
+        if (!runSrc) {
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to define convolution kernels from RUN metadta.");
+            psFree(runImages);
+            return false;
+        }
+        psFree(runKernel);
+
+        psFree(runImages);
+    } else {
+        // Defining files from the input metadata
+        psMetadata *inputs = psMetadataLookupMetadata(NULL, config->arguments, "INPUTS"); // The inputs info
+        if (!inputs) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find inputs.");
+            return false;
+        }
+        psMetadataIterator *iter = psMetadataIteratorAlloc(inputs, PS_LIST_HEAD, NULL); // Iterator
+        psMetadataItem *item;               // Item from iteration
+        int i = 0;                          // Counter
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (item->type != PS_DATA_METADATA) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true,
+                        "Component %s of the input metadata is not of type METADATA", item->name);
+                psFree(iter);
+                return false;
+            }
+
+            psMetadata *input = item->data.md; // The input metadata of interest
+
+            psString image = psMetadataLookupStr(NULL, input, "IMAGE"); // Name of image
+            if (!image || strlen(image) == 0) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Component %s lacks IMAGE of type STR", item->name);
+                psFree(iter);
+                return false;
+            }
+
+            bool mdok;
+            psString mask = psMetadataLookupStr(&mdok, input, "MASK"); // Name of mask
+            psString variance = psMetadataLookupStr(&mdok, input, "VARIANCE"); // Name of variance map
+            psString psf = psMetadataLookupStr(&mdok, input, "PSF"); // Name of PSF
+            psString sources = psMetadataLookupStr(&mdok, input, "SOURCES"); // Name of sources
+
+            pmFPAfile *imageFile = defineFile(config, NULL, "PPSTACK.INPUT",
+                                              image, PM_FPA_FILE_IMAGE); // File for image
+            if (!imageFile) {
+                psError(PS_ERR_UNKNOWN, false, "Unable to define file from image %d (%s)", i, image);
+                return false;
+            }
+
+            if (mask && strlen(mask) > 0 &&
+                !defineFile(config, imageFile, "PPSTACK.INPUT.MASK", mask, PM_FPA_FILE_MASK)) {
                 psError(PS_ERR_UNKNOWN, false, "Unable to define file from mask %d (%s)", i, mask);
                 return false;
             }
-            if (maskFile->type != PM_FPA_FILE_MASK) {
-                psError(PS_ERR_IO, true, "PPSTACK.INPUT.MASK is not of type MASK");
-                return false;
-            }
-        }
-
-        // Optionally add the variance file
-        if (variance && strlen(variance) > 0) {
-            haveVariances = true;
-            psArray *varianceFiles = psArrayAlloc(1); // Array of filenames for this FPA
-            varianceFiles->data[0] = psMemIncrRefCounter(variance);
-            psMetadataAddArray(config->arguments, PS_LIST_TAIL, "VARIANCE.FILENAMES", PS_META_REPLACE,
-                               "Filenames of variance files", varianceFiles);
-            psFree(varianceFiles);
-
-            bool status;
-            pmFPAfile *varianceFile = pmFPAfileBindFromArgs(&status, imageFile, config,
-                                                            "PPSTACK.INPUT.VARIANCE", "VARIANCE.FILENAMES");
-            if (!status) {
-                psError(PS_ERR_UNKNOWN, false, "Unable to define file from variance %d (%s)", i, variance);
-                return false;
-            }
-            if (varianceFile->type != PM_FPA_FILE_VARIANCE) {
-                psError(PS_ERR_IO, true, "PPSTACK.INPUT.VARIANCE is not of type VARIANCE");
-                return false;
-            }
-        }
-
-        // Add the psf file
-        if (!psf || strlen(psf) == 0) {
-            if (havePSFs) {
-                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find PSF %d", i);
-                return false;
-            }
-        } else {
-            if (!havePSFs && i != 0) {
-                psWarning("PSF not provided for all inputs --- ignoring.");
-            } else {
-                psArray *psfFiles = psArrayAlloc(1); // Array of filenames for this FPA
-                psfFiles->data[0] = psMemIncrRefCounter(psf);
-                psMetadataAddArray(config->arguments, PS_LIST_TAIL, "PSF.FILENAMES", PS_META_REPLACE,
-                                   "Filenames of PSF files", psfFiles);
-                psFree(psfFiles);
-
-                bool status;
-                pmFPAfile *psfFile = pmFPAfileBindFromArgs(&status, imageFile, config, "PPSTACK.INPUT.PSF",
-                                                           "PSF.FILENAMES");
-                if (!status) {
-                    psError(PS_ERR_UNKNOWN, false, "Unable to define file from psf %d (%s)", i, psf);
+
+            if (variance && strlen(variance) > 0) {
+                haveVariances = true;
+                if (!defineFile(config, imageFile, "PPSTACK.INPUT.VARIANCE", variance,
+                                PM_FPA_FILE_VARIANCE)) {
+                    psError(PS_ERR_UNKNOWN, false,
+                            "Unable to define file from variance %d (%s)", i, variance);
                     return false;
                 }
-                if (psfFile->type != PM_FPA_FILE_PSF) {
-                    psError(PS_ERR_IO, true, "PPSTACK.INPUT.PSF is not of type PSF");
-                    return false;
+            }
+
+            if (psf && strlen(psf) > 0) {
+                if (i != 0 && !havePSFs) {
+                    psWarning("PSF not provided for all inputs --- ignoring.");
+                } else {
+                    havePSFs = true;
+                    if (!defineFile(config, imageFile, "PPSTACK.INPUT.PSF", psf, PM_FPA_FILE_PSF)) {
+                        psError(PS_ERR_UNKNOWN, false, "Unable to define file from psf %d (%s)", i, psf);
+                        return false;
+                    }
                 }
-                havePSFs = true;
-            }
-        }
-
-        // Add the sources file
-        {
-            psArray *sourcesFiles = psArrayAlloc(1); // Array of filenames for this FPA
-            sourcesFiles->data[0] = psMemIncrRefCounter(sources);
-            psMetadataAddArray(config->arguments, PS_LIST_TAIL, "SOURCES.FILENAMES", PS_META_REPLACE,
-                               "Filenames of SOURCES files", sourcesFiles);
-            psFree(sourcesFiles);
-
-            bool status;
-            pmFPAfile *sourcesFile = pmFPAfileBindFromArgs(&status, imageFile, config,
-                                                           "PPSTACK.INPUT.SOURCES", "SOURCES.FILENAMES");
-            if (!status) {
+            } else if (havePSFs) {
+                psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find PSF %d", i);
+                return false;
+            }
+
+            if (!sources || strlen(sources) == 0) {
+                psError(PS_ERR_UNEXPECTED_NULL, true, "SOURCES not provided for file %d", i);
+                return false;
+            }
+            if (!defineFile(config, imageFile, "PPSTACK.INPUT.SOURCES", sources, PM_FPA_FILE_CMF)) {
                 psError(PS_ERR_UNKNOWN, false, "Unable to define file from sources %d (%s)",
                         i, sources);
                 return false;
             }
-            if (sourcesFile->type != PM_FPA_FILE_CMF) {
-                psError(PS_ERR_IO, true, "PPSTACK.INPUT.SOURCES is not of type CMF");
-                return false;
-            }
-        }
-
-#if 0
-        // Output convolved files
-        pmFPAfile *outconvImage    = defineOutputConvolved("PPSTACK.OUTCONV", imageFile->fpa, config,
-                                                           PM_FPA_FILE_IMAGE);
-        pmFPAfile *outconvMask     = defineOutputConvolved("PPSTACK.OUTCONV.MASK", imageFile->fpa, config,
-                                                           PM_FPA_FILE_MASK);
-        pmFPAfile *outconvVariance = defineOutputConvolved("PPSTACK.OUTCONV.VARIANCE", imageFile->fpa, config,
-                                                           PM_FPA_FILE_VARIANCE);
-        if (!outconvImage || !outconvMask || !outconvVariance) {
-            return false;
-        }
-
-        // Input convolved files
-        pmFPAfile *inconvImage    = defineInputConvolved("PPSTACK.INCONV", outconvImage, config,
-                                                         PM_FPA_FILE_IMAGE);
-        pmFPAfile *inconvMask     = defineInputConvolved("PPSTACK.INCONV.MASK", outconvMask, config,
-                                                         PM_FPA_FILE_MASK);
-        pmFPAfile *inconvVariance = defineInputConvolved("PPSTACK.INCONV.VARIANCE", outconvVariance, config,
-                                                         PM_FPA_FILE_VARIANCE);
-        if (!inconvImage || !inconvMask || !inconvVariance) {
-            return false;
-        }
-#endif
-
-        i++;
-    }
-    psFree(iter);
-    psMetadataRemoveKey(config->arguments, "IMAGE.FILENAMES");
-    if (psMetadataLookup(config->arguments, "MASK.FILENAMES")) {
-        psMetadataRemoveKey(config->arguments, "MASK.FILENAMES");
-    }
-    if (psMetadataLookup(config->arguments, "VARIANCE.FILENAMES")) {
-        psMetadataRemoveKey(config->arguments, "VARIANCE.FILENAMES");
-    }
-    if (psMetadataLookup(config->arguments, "PSF.FILENAMES")) {
-        psMetadataRemoveKey(config->arguments, "PSF.FILENAMES");
-    }
-    if (psMetadataLookup(config->arguments, "SOURCES.FILENAMES")) {
-        psMetadataRemoveKey(config->arguments, "SOURCES.FILENAMES");
-    }
-
-    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INPUTS.NUM", 0, "Number of input files", i);
+
+            pmFPAfile *kernel = pmFPAfileDefineOutput(config, imageFile->fpa, "PPSTACK.CONV.KERNEL");
+            if (!kernel) {
+                psError(PS_ERR_IO, false, _("Unable to generate output file from PPSTACK.CONV.KERNEL"));
+                return false;
+            }
+
+            i++;
+        }
+        psFree(iter);
+        psMetadataRemoveKey(config->arguments, "FILENAMES");
+        num = i;
+    }
+    psMetadataAddS32(config->arguments, PS_LIST_TAIL, "INPUTS.NUM", 0, "Number of input files", num);
     psMetadataAddBool(config->arguments, PS_LIST_TAIL, "HAVE.PSF", 0, "Have PSFs available?", havePSFs);
 
