Index: branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConcepts.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConcepts.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConcepts.c	(revision 28796)
@@ -350,4 +350,5 @@
         conceptRegisterS32("CHIP.YSIZE", "Size of chip (pixels)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CHIP);
         conceptRegisterF32("CHIP.TEMP", "Temperature of chip", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
+        conceptRegisterF32("CHIP.TEMPERATURE", "Temperature of chip", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
         conceptRegisterStr("CHIP.ID", "Chip identifier", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
         conceptRegisterF32("CHIP.SEEING", "Seeing FWHM (pixels)", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
Index: branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConceptsStandard.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/concepts/pmConceptsStandard.c	(revision 28796)
@@ -449,4 +449,6 @@
             int big, medium;
             float small;
+            bool negative =  *((char *)concept->data.V) == '-'; // check for sign explicitly since -0 is not less than 0
+
             // XXX: Upgrade path is to allow dd:mm.mmm
             if (sscanf(concept->data.V, "%d:%d:%f", &big, &medium, &small) != 3 &&
@@ -457,5 +459,5 @@
             }
             coords = abs(big) + (float)medium/60.0 + small/3600.0;
-            if (big < 0)
+            if (negative)
             {
                 coords *= -1.0;
Index: branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.c	(revision 28796)
@@ -15,8 +15,12 @@
     } else if (!strcmp(stageString, "chip")) {
         return IPP_STAGE_CHIP;
+    } else if (!strcmp(stageString, "chip_bg")) {
+        return IPP_STAGE_CHIP_BG;
     } else if (!strcmp(stageString, "camera")) {
         return IPP_STAGE_CAMERA;
     } else if (!strcmp(stageString, "warp")) {
         return IPP_STAGE_WARP;
+    } else if (!strcmp(stageString, "warp_bg")) {
+        return IPP_STAGE_WARP_BG;
     } else if (!strcmp(stageString, "fake")) {
         return IPP_STAGE_FAKE;
Index: branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.h
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.h	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/extras/ippStages.h	(revision 28796)
@@ -13,7 +13,9 @@
     IPP_STAGE_RAW = 0,
     IPP_STAGE_CHIP,
+    IPP_STAGE_CHIP_BG,
     IPP_STAGE_CAMERA,
     IPP_STAGE_FAKE,
     IPP_STAGE_WARP,
+    IPP_STAGE_WARP_BG,
     IPP_STAGE_DIFF,
     IPP_STAGE_STACK,
Index: branches/eam_branches/ipp-20100621/psModules/src/imcombine/pmSubtraction.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/imcombine/pmSubtraction.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/imcombine/pmSubtraction.c	(revision 28796)
@@ -52,15 +52,9 @@
 
     // Take the square of the normal kernel
-    double sumVariance = 0.0; // Sum of the variance kernels
     for (int v = yMin; v <= yMax; v++) {
         for (int u = xMin; u <= xMax; u++) {
-            sumVariance += out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]);
-        }
-    }
-
-    // Normalise so that the sum of the variance kernel is the square of the sum of the normal kernel
-    // This is required to keep the relative scaling between the image and the variance map
-    psBinaryOp(out->image, out->image, "*", psScalarAlloc(1.0 / sumVariance, PS_TYPE_F32));
-
+            out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]);
+        }
+    }
     return out;
 }
@@ -271,12 +265,12 @@
 // Convolve an image using FFT
 static void convolveVarianceFFT(psImage *target,// Place the result in here
-                              psImage *variance, // Variance map to convolve
-                              psImage *kernelErr, // Kernel error image
-                              psImage *mask, // Mask image
-                              psImageMaskType maskVal, // Value to mask
-                              const psKernel *kernel, // Kernel by which to convolve
-                              psRegion region,// Region of interest
-                              int size        // Size of (square) kernel
-                              )
+                                psImage *variance, // Variance map to convolve
+                                psImage *kernelErr, // Kernel error image
+                                psImage *mask, // Mask image
+                                psImageMaskType maskVal, // Value to mask
+                                const psKernel *kernel, // Kernel by which to convolve
+                                psRegion region,// Region of interest
+                                int size        // Size of (square) kernel
+                                )
 {
     psRegion border = psRegionSet(region.x0 - size, region.x1 + size,
@@ -348,4 +342,5 @@
                                   psImage *image, // Image to convolve
                                   psImage *variance, // Variance map to convolve, or NULL
+                                  const psKernel *covar,               // Covariance, or NULL
                                   psImage *kernelErr, // Kernel error image, or NULL
                                   psImage *subMask, // Subtraction mask
@@ -393,4 +388,14 @@
         if (variance) {
             convolveDirect(convVariance, variance, *kernelVariance, region, 0.0, kernels->size);
+        }
+    }
+
+    if (variance && covar) {
+        // Apply covariance factor to variance map, to allow for spatial variation
+        float factor = psImageCovarianceCalculateFactor(*kernelImage, covar); // Factor to apply
+        for (int y = region.y0; y < region.y1; y++) {
+            for (int x = region.x0; x < region.x1; x++) {
+                convVariance->data.F32[y][x] *= factor;
+            }
         }
     }
@@ -1085,11 +1090,11 @@
     if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
         convolveRegion(out1->image, out1->variance, out1->mask, &kernelImage, &kernelVariance,
-                       ro1->image, ro1->variance, kernelErr1, subMask, kernels, polyValues, background,
-                       *region, maskBad, maskPoor, poorFrac, useFFT, false);
+                       ro1->image, ro1->variance, ro1->covariance, kernelErr1, subMask, kernels,
+                       polyValues, background, *region, maskBad, maskPoor, poorFrac, useFFT, false);
     }
     if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
         convolveRegion(out2->image, out2->variance, out2->mask, &kernelImage, &kernelVariance,
-                       ro2->image, ro2->variance, kernelErr2, subMask, kernels, polyValues, background,
-                       *region, maskBad, maskPoor, poorFrac, useFFT,
+                       ro2->image, ro2->variance, ro2->covariance, kernelErr2, subMask, kernels,
+                       polyValues, background, *region, maskBad, maskPoor, poorFrac, useFFT,
                        kernels->mode == PM_SUBTRACTION_MODE_DUAL);
     }
@@ -1325,7 +1330,7 @@
 
     // Calculate covariances
-    // This can be fairly involved, so we only do it for a single instance
-    // Enable threads for covariance calculation, since we're not threading on top of it.
+    // This can be fairly involved, so we only do it for a small number of instances
     float position[NUM_COVAR_POS] = { -1.0, -0.5, 0.0, +0.5, +1.0 }; // Positions for covariance calculations
+    // Enable threads for covariance calculation, since we're not threading on top of it
     oldThreads = psImageCovarianceSetThreads(true);
     if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
@@ -1342,4 +1347,7 @@
         out1->covariance = psImageCovarianceAverage(covars);
         psFree(covars);
+        // Remove covariance factor from covariance, since we've put it in the variance map already
+        float factor = psImageCovarianceFactor(out1->covariance);
+        psBinaryOp(out1->covariance->image, out1->covariance->image, "/", psScalarAlloc(factor, PS_TYPE_F32));
     }
     if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
@@ -1356,4 +1364,7 @@
         out2->covariance = psImageCovarianceAverage(covars);
         psFree(covars);
+        // Remove covariance factor from covariance, since we've put it in the variance map already
+        float factor = psImageCovarianceFactor(out2->covariance);
+        psBinaryOp(out2->covariance->image, out2->covariance->image, "/", psScalarAlloc(factor, PS_TYPE_F32));
     }
     psImageCovarianceSetThreads(oldThreads);
Index: branches/eam_branches/ipp-20100621/psModules/src/objects/pmPSF_IO.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/objects/pmPSF_IO.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/objects/pmPSF_IO.c	(revision 28796)
@@ -191,7 +191,6 @@
     pmReadout *ro = pmFPAviewThisReadout(roView, chip->parent); // Readout with analysis data
     psFree(roView);
-    PM_ASSERT_READOUT_NON_NULL(ro, false);
-
-    if (!pmPSFmodelWrite(chip->analysis, ro->analysis, view, file, config)) {
+
+    if (!pmPSFmodelWrite(chip->analysis, ro ? ro->analysis : NULL, view, file, config)) {
         psError(psErrorCodeLast(), false, "Failed to write PSF for chip");
         return false;
@@ -222,6 +221,5 @@
     }
     if (!roAnalysis) {
-        psError(PM_ERR_PROG, true, "No analysis metadata for readout.");
-        return false;
+        psWarning("No analysis metadata for PSF, clump parameters cannot be saved.");
     }
 
@@ -369,25 +367,27 @@
 
         // we now save clump parameters for each region : need to save all of those
-        int nRegions = psMetadataLookupS32 (&status, roAnalysis, "PSF.CLUMP.NREGIONS");
-        psMetadataAddS32 (header, PS_LIST_TAIL, "PSF_CLN", PS_META_REPLACE, "number of psf clump regions", nRegions);
-        for (int i = 0; i < nRegions; i++) {
-            char regionName[64];
-            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
-            psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
-
-            psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");   assert (status);
-            psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   assert (status);
-            psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  assert (status);
-            psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  assert (status);
-
-            char key[16];
-            snprintf (key, 9, "CLX_%03d", i);
-            psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump center", psfClump.X);
-            snprintf (key, 9, "CLY_%03d", i);
-            psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump center", psfClump.Y);
-            snprintf (key, 9, "CLDX_%03d", i);
-            psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump size", psfClump.dX);
-            snprintf (key, 9, "CLDY_%03d", i);
-            psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump size", psfClump.dY);
+        if (roAnalysis) {
+            int nRegions = psMetadataLookupS32 (&status, roAnalysis, "PSF.CLUMP.NREGIONS");
+            psMetadataAddS32 (header, PS_LIST_TAIL, "PSF_CLN", PS_META_REPLACE, "number of psf clump regions", nRegions);
+            for (int i = 0; i < nRegions; i++) {
+                char regionName[64];
+                snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
+                psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
+
+                psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");   assert (status);
+                psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   assert (status);
+                psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  assert (status);
+                psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  assert (status);
+
+                char key[16];
+                snprintf (key, 9, "CLX_%03d", i);
+                psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump center", psfClump.X);
+                snprintf (key, 9, "CLY_%03d", i);
+                psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump center", psfClump.Y);
+                snprintf (key, 9, "CLDX_%03d", i);
+                psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump size", psfClump.dX);
+                snprintf (key, 9, "CLDY_%03d", i);
+                psMetadataAddF32 (header, PS_LIST_TAIL, key, PS_META_REPLACE, "psf clump size", psfClump.dY);
+            }
         }
 
@@ -787,5 +787,4 @@
 {
     PS_ASSERT_METADATA_NON_NULL(chipAnalysis, false);
-    PS_ASSERT_METADATA_NON_NULL(roAnalysis, false);
     PS_ASSERT_PTR_NON_NULL(view, false);
     PS_ASSERT_PTR_NON_NULL(file, false);
@@ -852,38 +851,12 @@
 
     // read the psf clump data for each region
-    int nRegions = psMetadataLookupS32 (&status, header, "PSF_CLN");
-    if (!status) {
-        // read old-style psf clump data
-
-        char regionName[64];
-        snprintf (regionName, 64, "PSF.CLUMP.REGION.000");
-        psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 1);
-
-        psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
-        if (!regionMD) {
-            regionMD = psMetadataAlloc();
-            psMetadataAddMetadata (roAnalysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
-            psFree (regionMD);
-        }
-
-        // psf clump data
-        pmPSFClump psfClump;
-
-        psfClump.X  = psMetadataLookupF32 (&status, header, "PSF_CLX" );  assert(status);
-        psfClump.Y  = psMetadataLookupF32 (&status, header, "PSF_CLY" );  assert(status);
-        psfClump.dX = psMetadataLookupF32 (&status, header, "PSF_CLDX");  assert(status);
-        psfClump.dY = psMetadataLookupF32 (&status, header, "PSF_CLDY");  assert(status);
-
-        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
-        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
-        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
-        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
-    } else {
-        psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegions);
-
-        for (int i = 0; i < nRegions; i++) {
-            char key[10];
+    if (roAnalysis) {
+        int nRegions = psMetadataLookupS32 (&status, header, "PSF_CLN");
+        if (!status) {
+            // read old-style psf clump data
+
             char regionName[64];
-            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
+            snprintf (regionName, 64, "PSF.CLUMP.REGION.000");
+            psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", 1);
 
             psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
@@ -897,12 +870,8 @@
             pmPSFClump psfClump;
 
-            snprintf (key, 9, "CLX_%03d", i);
-            psfClump.X  = psMetadataLookupF32 (&status, header, key);  assert(status);
-            snprintf (key, 9, "CLY_%03d", i);
-            psfClump.Y  = psMetadataLookupF32 (&status, header, key);  assert(status);
-            snprintf (key, 9, "CLDX_%03d", i);
-            psfClump.dX = psMetadataLookupF32 (&status, header, key);  assert(status);
-            snprintf (key, 9, "CLDY_%03d", i);
-            psfClump.dY = psMetadataLookupF32 (&status, header, key);  assert(status);
+            psfClump.X  = psMetadataLookupF32 (&status, header, "PSF_CLX" );  assert(status);
+            psfClump.Y  = psMetadataLookupF32 (&status, header, "PSF_CLY" );  assert(status);
+            psfClump.dX = psMetadataLookupF32 (&status, header, "PSF_CLDX");  assert(status);
+            psfClump.dY = psMetadataLookupF32 (&status, header, "PSF_CLDY");  assert(status);
 
             psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
@@ -910,4 +879,36 @@
             psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
             psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+        } else {
+            psMetadataAddS32 (roAnalysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegions);
+
+            for (int i = 0; i < nRegions; i++) {
+                char key[10];
+                char regionName[64];
+                snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
+
+                psMetadata *regionMD = psMetadataLookupPtr (&status, roAnalysis, regionName);
+                if (!regionMD) {
+                    regionMD = psMetadataAlloc();
+                    psMetadataAddMetadata (roAnalysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
+                    psFree (regionMD);
+                }
+
+                // psf clump data
+                pmPSFClump psfClump;
+
+                snprintf (key, 9, "CLX_%03d", i);
+                psfClump.X  = psMetadataLookupF32 (&status, header, key);  assert(status);
+                snprintf (key, 9, "CLY_%03d", i);
+                psfClump.Y  = psMetadataLookupF32 (&status, header, key);  assert(status);
+                snprintf (key, 9, "CLDX_%03d", i);
+                psfClump.dX = psMetadataLookupF32 (&status, header, key);  assert(status);
+                snprintf (key, 9, "CLDY_%03d", i);
+                psfClump.dY = psMetadataLookupF32 (&status, header, key);  assert(status);
+
+                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
+                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
+                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
+                psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
+            }
         }
     }
Index: branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourceMatch.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourceMatch.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourceMatch.c	(revision 28796)
@@ -249,4 +249,5 @@
             }
 
+            numMaster = size;
             xMaster->n = size;
             yMaster->n = size;
Index: branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourcePhotometry.c
===================================================================
--- branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourcePhotometry.c	(revision 28781)
+++ branches/eam_branches/ipp-20100621/psModules/src/objects/pmSourcePhotometry.c	(revision 28796)
@@ -409,4 +409,8 @@
     psImage *mask     = source->maskObj;
 
+    if (!flux || !variance || !mask) {
+        return false;
+    }
+
     for (int iy = 0; iy < flux->numRows; iy++) {
         for (int ix = 0; ix < flux->numCols; ix++) {
