Index: trunk/psModules/src/imcombine/pmSubtractionMatch.c
===================================================================
--- trunk/psModules/src/imcombine/pmSubtractionMatch.c	(revision 23307)
+++ trunk/psModules/src/imcombine/pmSubtractionMatch.c	(revision 23308)
@@ -160,31 +160,128 @@
 
 bool pmSubtractionMatchPrecalc(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2,
-                               pmSubtractionKernels *kernel, psRegion *region, int stride, float sysError,
+                               psMetadata *analysis, int stride, float sysError,
                                psImageMaskType maskVal, psImageMaskType maskBad, psImageMaskType maskPoor,
                                float poorFrac, float badFrac)
 {
-    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernel, false);
-    pmSubtractionMode subMode = kernel->mode; // Subtraction mode: which input to convolve
+    PS_ASSERT_METADATA_NON_NULL(analysis, false);
+
+    // Extract the kernels
+    pmSubtractionMode mode = PM_SUBTRACTION_MODE_UNSURE; // Subtraction mode: which image to convolve
+    int size = 0;                       // Size of kernel
+    psList *kernelList = psListAlloc(NULL); // List of kernels
+    {
+        psMetadataIterator *iter = psMetadataIteratorAlloc(analysis, PS_LIST_HEAD,
+                                                           "^" PM_SUBTRACTION_ANALYSIS_KERNEL "$");
+        psMetadataItem *item;               // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (item->type != PS_DATA_UNKNOWN) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unexpected type for kernel.");
+                psFree(iter);
+                psFree(kernelList);
+                return false;
+            }
+            pmSubtractionKernels *kernel = item->data.V; // Kernel
+            PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernel, false);
+            size = PS_MAX(size, kernel->size);
+            if (mode == PM_SUBTRACTION_MODE_UNSURE) {
+                mode = kernel->mode;
+            } else if (kernel->mode != mode) {
+                // There's some confusion, so let's set the mode to dual convolution.
+                // This is only used for the subtraction mask, so it's not a big deal.
+                mode = PM_SUBTRACTION_MODE_DUAL;
+            }
+            psListAdd(kernelList, PS_LIST_TAIL, kernel);
+        }
+        psFree(iter);
+    }
+    if (psListLength(kernelList) == 0) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find kernels");
+        psFree(kernelList);
+        return false;
+    }
+    psArray *kernels = psListToArray(kernelList); // Array of kernels
+    psFree(kernelList);
+
+    // Extract the regions
+    psArray *regions = psArrayAllocEmpty(kernels->n); // Array of regions
+    {
+        psMetadataIterator *iter = psMetadataIteratorAlloc(analysis, PS_LIST_HEAD,
+                                                           "^" PM_SUBTRACTION_ANALYSIS_REGION "$");
+        psMetadataItem *item;               // Item from iteration
+        while ((item = psMetadataGetAndIncrement(iter))) {
+            if (item->type != PS_DATA_REGION) {
+                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unexpected type for region.");
+                psFree(iter);
+                psFree(kernels);
+                psFree(regions);
+                return false;
+            }
+            psRegion *region = item->data.V; // Region
+            psArrayAdd(regions, regions->n, region);
+        }
+        psFree(iter);
+    }
+    if (regions->n != kernels->n) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Differing number of kernels (%ld) and regions (%ld)",
+                kernels->n, regions->n);
+        psFree(regions);
+        psFree(kernels);
+        return false;
+    }
+
     if (!subtractionMatchCheck(conv1, conv2, ro1, ro2, stride, sysError, maskVal, maskBad, maskPoor,
-                               poorFrac, badFrac, subMode)) {
+                               poorFrac, badFrac, mode)) {
+        psFree(kernels);
+        psFree(regions);
         return false;
     }
 
-    psImage *subMask = pmSubtractionMask(ro1->mask, ro2 ? ro2->mask : NULL, maskVal, kernel->size, 0,
+    psImage *subMask = pmSubtractionMask(ro1->mask, ro2 ? ro2->mask : NULL, maskVal, size, 0,
                                          badFrac, useFFT); // Subtraction mask
     if (!subMask) {
         psError(PS_ERR_UNKNOWN, false, "Unable to generate subtraction mask.");
+        psFree(kernels);
+        psFree(regions);
         return false;
     }
 
+    psMetadata *outAnalysis = psMetadataAlloc(); // Output analysis values
+
     psTrace("psModules.imcombine", 2, "Convolving...\n");
-    if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, stride, maskBad, maskPoor, poorFrac,
-                               sysError, region, kernel, true, useFFT)) {
-        psError(PS_ERR_UNKNOWN, false, "Unable to convolve image.");
-        psFree(subMask);
-        return false;
+    for (int i = 0; i < kernels->n; i++) {
+        pmSubtractionKernels *kernel = kernels->data[i]; // Kernel of interest
+        psRegion *region = regions->data[i]; // Region of interest
+
+        if (!pmSubtractionAnalysis(outAnalysis, kernel, region, ro1->image->numCols, ro1->image->numRows)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to generate QA data");
+            psFree(outAnalysis);
+            psFree(subMask);
+            psFree(kernels);
+            psFree(regions);
+            return false;
+        }
+
+        if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, stride, maskBad, maskPoor, poorFrac,
+                                   sysError, region, kernel, true, useFFT)) {
+            psError(PS_ERR_UNKNOWN, false, "Unable to convolve image.");
+            psFree(outAnalysis);
+            psFree(subMask);
+            psFree(kernels);
+            psFree(regions);
+            return false;
+        }
     }
 
     psFree(subMask);
+    psFree(kernels);
+    psFree(regions);
+
+    if (conv1) {
+        psMetadataCopy(conv1->analysis, outAnalysis);
+    }
+    if (conv2) {
+        psMetadataCopy(conv2->analysis, outAnalysis);
+    }
+    psFree(outAnalysis);
 
     return true;
Index: trunk/psModules/src/imcombine/pmSubtractionMatch.h
===================================================================
--- trunk/psModules/src/imcombine/pmSubtractionMatch.h	(revision 23307)
+++ trunk/psModules/src/imcombine/pmSubtractionMatch.h	(revision 23308)
@@ -53,6 +53,5 @@
                                const pmReadout *ro1, ///< Image 1
                                const pmReadout *ro2, ///< Image 2
-                               pmSubtractionKernels *kernels, ///< Pre-calculated matching kernel
-                               psRegion *region, ///< Region of applicability for kernel
+                               psMetadata *analysis, ///< Analysis metadata with pre-calculated kernel, region
                                int stride, ///< Size for convolution patches
                                float sysError, ///< Relative systematic error
