def testSimAlRefNotModified(self): "Image differencing should not modify the original template image." refPsf = 2. sciPsfBase = 2. sciNoise = 5. refNoise = 1.5 seed = 37 fluxLevel = 500 rng = np.random.RandomState(seed) alConfig = ImagePsfMatchConfig() sciPsf = sciPsfBase + rng.random() * 2. refOriginal, _ = self.makeTestImages(seed=seed, nSrc=20, psfSize=refPsf, noiseLevel=refNoise, fluxLevel=fluxLevel) sciOriginal, src = self.makeTestImages(seed=seed, nSrc=20, psfSize=sciPsf, noiseLevel=sciNoise, fluxLevel=fluxLevel) # Make a deep copy of the images first sciTest1 = sciOriginal.clone() refTest1 = refOriginal.clone() # Basic AL, but we don't care about the result. self.wrapAlDiffim(alConfig, refTest1, sciTest1, convolveTemplate=False) self.assertMaskedImagesEqual(refOriginal.maskedImage, refTest1.maskedImage) # Basic AL, but we don't care about the result. self.wrapAlDiffim(alConfig, refTest1, sciTest1, convolveTemplate=True) self.assertMaskedImagesEqual(refOriginal.maskedImage, refTest1.maskedImage)
def testSimAlDecorr(self): refPsf = 2. sciPsfBase = 2. sciNoise = 5. refNoise = 1.5 seed = 37 metricSigma = 0 fluxLevel = 500 rng = np.random.RandomState(seed) decorrelateConfig = DecorrelateALKernelConfig() decorrelate = DecorrelateALKernelTask(config=decorrelateConfig) alConfig = ImagePsfMatchConfig() for s in range(self.nRandIter): sciPsf = sciPsfBase + rng.random() * 2. ref, _ = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=refPsf, noiseLevel=refNoise, fluxLevel=fluxLevel) sci, src = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=sciPsf, noiseLevel=sciNoise, fluxLevel=fluxLevel) # The diffim tasks can modify the images, so make a deep copy to make sure they are independent sci2 = sci.clone() ref2 = ref.clone() # Basic AL res = self.wrapAlDiffim(alConfig, ref, sci, convolveTemplate=True) # Decorrelated AL mKernel = self.wrapAlDiffim(alConfig, ref, sci, convolveTemplate=True, returnKernel=True) resD = decorrelate.run(sci, ref, res, mKernel).correctedExposure metricD = self.diffimMetricBasic(resD, src, sigma=metricSigma) # Swap the "science" and "reference" images, and alse swap which image is convolved. # The result is that the same image should be convolved as above resR = self.wrapAlDiffim(alConfig, sci2, ref2, convolveTemplate=False) # Swap the images as above, and also decorrelate. mKernelR = self.wrapAlDiffim(alConfig, sci2, ref2, convolveTemplate=False, returnKernel=True) resDR = decorrelate.run(ref2, sci2, resR, mKernelR).correctedExposure metricDR = self.diffimMetricBasic(resDR, src, sigma=metricSigma) self.assertFloatsAlmostEqual(metricD, -metricDR, atol=.1, rtol=0.1)
def testSimAlSciNotModified(self): "Image differencing should not modify the original science image." refPsf = 2. sciPsfBase = 2. sciNoise = 5. refNoise = 1.5 seed = 37 fluxLevel = 500 rng = np.random.RandomState(seed) alConfig = ImagePsfMatchConfig() sciPsf = sciPsfBase + rng.random() * 2. refOriginal, _ = self.makeTestImages(seed=seed, nSrc=20, psfSize=refPsf, noiseLevel=refNoise, fluxLevel=fluxLevel) sciOriginal, src = self.makeTestImages(seed=seed, nSrc=20, psfSize=sciPsf, noiseLevel=sciNoise, fluxLevel=fluxLevel) # Make a deep copy of the images first sciTest1 = sciOriginal.clone() refTest1 = refOriginal.clone() # Basic AL, but we don't care about the result. # Note that selecting KernelCandidates *does* change the science image slightly # because a background is subtracted before detection, then added back in. # For this test, we separate out that known modification by precomputing the # kernel candidates in wrapAlDiffim and using a deep copy of the science image. # This test is therefore checking that there are no other, unknown, modifications # of the science image. self.wrapAlDiffim(alConfig, refTest1, sciTest1, convolveTemplate=True, precomputeKernelCandidates=True) self.assertMaskedImagesEqual(sciOriginal.maskedImage, sciTest1.maskedImage) # Basic AL, but we don't care about the result. self.wrapAlDiffim(alConfig, refTest1, sciTest1, convolveTemplate=False, precomputeKernelCandidates=True) self.assertMaskedImagesEqual(sciOriginal.maskedImage, sciTest1.maskedImage)
def testSimDiffim(self): "Basic smoke test to verify that the test code itself can run." refPsf = 2.4 sciPsfBase = 2. sciNoise = 5. refNoise = 1.5 seed = 8 fluxLevel = 500 decorrelate = DecorrelateALKernelTask() zogyConfig = ZogyConfig() alConfig = ImagePsfMatchConfig() for s in range(self.nRandIter): sciPsf = sciPsfBase + s * 0.2 ref, _ = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=refPsf, noiseLevel=refNoise, fluxLevel=fluxLevel) sci, src = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=sciPsf, noiseLevel=sciNoise, fluxLevel=fluxLevel) # The diffim tasks might modify the images, # so make a deep copy to make sure they are independent sci2 = sci.clone() ref2 = ref.clone() resAl = self.wrapAlDiffim(alConfig, ref, sci) resZogy = self.wrapZogyDiffim(zogyConfig, ref2, sci2) metricZogy = self.diffimMetricBasic(resZogy, src, sigma=3) metricAl = self.diffimMetricBasic(resAl, src, sigma=3) mKernel = self.wrapAlDiffim(alConfig, ref, sci, returnKernel=True) resDecorr = decorrelate.run(sci, ref, resAl, mKernel).correctedExposure metricDecorr = self.diffimMetricBasic(resDecorr, src, sigma=3) self.assertGreaterEqual(metricZogy, -1) self.assertGreaterEqual(metricAl, -1) self.assertGreaterEqual(metricDecorr, -1)
def testSimReverseAlNoDecorrUnequalNoise(self): refPsf = 2. sciPsfBase = 2. sciNoise = 5. refNoise = 1.5 seed = 37 metricSigma = 0 fluxLevel = 500 rng = np.random.RandomState(seed) alConfig = ImagePsfMatchConfig() for s in range(self.nRandIter): sciPsf = sciPsfBase + rng.random() * 2. ref, _ = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=refPsf, noiseLevel=refNoise, fluxLevel=fluxLevel) sci, src = self.makeTestImages(seed=seed + s, nSrc=20, psfSize=sciPsf, noiseLevel=sciNoise, fluxLevel=fluxLevel) res = self.wrapAlDiffim(alConfig, ref, sci, convolveTemplate=True) resR = self.wrapAlDiffim(alConfig, sci, ref, convolveTemplate=False) metric = self.diffimMetricBasic(res, src, sigma=metricSigma) metricR = self.diffimMetricBasic(resR, src, sigma=metricSigma) # Alard&Lupton is not fully reversable, but the answers should be close. # Partly this needs the decorrelation afterburner # It might also be a difference in background subtraction self.assertFloatsAlmostEqual(metric, -metricR, atol=.1, rtol=.1)
def makeTestImages(self, seed=5, nSrc=5, psfSize=2., noiseLevel=5., fluxLevel=500., fluxRange=2.): """Make reproduceable PSF-convolved masked images for testing. Parameters ---------- seed : `int`, optional Seed value to initialize the random number generator. nSrc : `int`, optional Number of sources to simulate. psfSize : `float`, optional Width of the PSF of the simulated sources, in pixels. noiseLevel : `float`, optional Standard deviation of the noise to add to each pixel. fluxLevel : `float`, optional Reference flux of the simulated sources. fluxRange : `float`, optional Range in flux amplitude of the simulated sources. Returns ------- modelImages : `lsst.afw.image.ExposureF` The model image, with the mask and variance planes. sourceCat : `lsst.afw.table.SourceCatalog` Catalog of sources detected on the model image. """ rng = np.random.RandomState(seed) x0, y0 = self.bbox.getBegin() xSize, ySize = self.bbox.getDimensions() xLoc = rng.rand(nSrc) * (xSize - 2 * self.bufferSize) + self.bufferSize + x0 yLoc = rng.rand(nSrc) * (ySize - 2 * self.bufferSize) + self.bufferSize + y0 flux = (rng.rand(nSrc) * (fluxRange - 1.) + 1.) * fluxLevel sigmas = [psfSize for src in range(nSrc)] coordList = list(zip(xLoc, yLoc, flux, sigmas)) kernelSize = int( xSize / 2) # Need a careful explanation of this kernel size choice skyLevel = 0 # Don't use the built in poisson noise: it modifies the global state of numpy random model = plantSources(self.bbox, kernelSize, skyLevel, coordList, addPoissonNoise=False) noise = rng.rand(ySize, xSize) * noiseLevel model.image.array += noise model.variance.array = (np.sqrt(np.abs(model.image.array)) + noiseLevel - np.mean(np.sqrt(np.abs(noise)))) # Run source detection to set up the mask plane psfMatchTask = ImagePsfMatchTask(config=ImagePsfMatchConfig()) sourceCat = psfMatchTask.getSelectSources(model) model.setWcs(self._makeWcs()) return model, sourceCat