def _testZogyScorr(self, varAst=0.): """Compute Zogy likelihood images (Scorr) using Fourier- and Real-space methods. Compare the images. They are not identical but should be similar (within ~2%). """ config = ZogyConfig() task = ZogyTask(templateExposure=self.im2ex, scienceExposure=self.im1ex, config=config) D_F = task.computeScorr(inImageSpace=False, xVarAst=varAst, yVarAst=varAst) D_R = task.computeScorr(inImageSpace=True, xVarAst=varAst, yVarAst=varAst) self._compareExposures(D_F.S, D_R.S, Scorr=True)
def testPixelOffset(self): """ Test whether the peak position is at [300][300]. """ self._setUpImages() config = ZogyConfig(scaleByCalibration=False) task = ZogyTask(config=config) D_F = task.run(self.imnex, self.imrex, calculateScore=False) max_loc = PixelOffsetTest._find_max(D_F.diffExp.image.array) self.assertEqual(max_loc, (300, 300))
def testWholeImageGrid(self): """Test that a 1-cell `grid` is actually the whole image""" config = ZogyConfig() task = ZogyTask(config=config) bb = geom.Box2I(geom.Point2I(5, 10), geom.Extent2I(200, 300)) D = afwImage.ImageI(bb) grid = task.generateGrid(bb, geom.Extent2I(15, 15), bb.getDimensions()) self.assertTrue(len(grid) == 1, "Grid length is not 1") x = grid[0] D[x.innerBox] += 1 self.assertTrue(np.all(D.array == 1), "Single cell does not cover the original image.")
def testZogyDiffim(self): """Compute Zogy diffims using Fourier- and Real-space methods. Compare the images. They are not identical but should be similar (within ~2%). """ self._setUpImages() config = ZogyConfig() task = ZogyTask(templateExposure=self.im2ex, scienceExposure=self.im1ex, config=config) D_F = task.computeDiffim(inImageSpace=False) D_R = task.computeDiffim(inImageSpace=True) # Fourier-space and image-space versions are not identical, so up the tolerance. # This is a known issue with the image-space version. self._compareExposures(D_F.D, D_R.D, tol=0.03)
def testZogyDiffim(self): """Compute Zogy diffims using Fourier- and Real-space methods. Compare the images. They are not identical but should be similar (within ~2%). """ self._setUpImages() config = ZogyConfig() task = ZogyTask(templateExposure=self.im2ex, scienceExposure=self.im1ex, config=config) D_F = task.computeDiffim(inImageSpace=False) D_R = task.computeDiffim(inImageSpace=True) self._compareExposures(D_F, D_R)
def testSplitBorder(self): """Test outer border box splitting around an inner box""" config = ZogyConfig() task = ZogyTask(config=config) bb = geom.Box2I(geom.Point2I(5, 10), geom.Extent2I(20, 30)) D = afwImage.ImageI(bb) innerbox = bb.erodedBy(geom.Extent2I(3, 4)) D[innerbox] = 1 borderboxes = task.splitBorder(innerbox, bb) for x in borderboxes: D[x] += 1 # The splitting should cover all border pixels exactly once self.assertTrue(np.all(D.array == 1), "Border does not cover all pixels exactly once.")
def _testZogyDiffimMapReduced(self, inImageSpace=False, doScorr=False, **kwargs): """Test running Zogy using ImageMapReduceTask framework. Compare map-reduced version with non-map-reduced version. Do it for pure Fourier-based calc. and also for real-space. Also for computing pure diffim D and corrected likelihood image Scorr. """ config = ZogyMapReduceConfig() config.gridStepX = config.gridStepY = 9 config.borderSizeX = config.borderSizeY = 3 if inImageSpace: config.gridStepX = config.gridStepY = 8 config.borderSizeX = config.borderSizeY = 6 # need larger border size for image-space run config.reducer.reduceOperation = 'average' task = ImageMapReduceTask(config=config) D_mapReduced = task.run(self.im1ex, template=self.im2ex, inImageSpace=inImageSpace, doScorr=doScorr, forceEvenSized=False, **kwargs).exposure config = ZogyConfig() task = ZogyTask(templateExposure=self.im2ex, scienceExposure=self.im1ex, config=config) if not doScorr: D = task.computeDiffim(inImageSpace=inImageSpace, **kwargs).D else: D = task.computeScorr(inImageSpace=inImageSpace, **kwargs).S self._compareExposures(D_mapReduced, D, tol=0.04, Scorr=doScorr)
def _testZogyImagePsfMatchTask(self, spatiallyVarying=False, inImageSpace=False, doScorr=False, **kwargs): """Test running Zogy using ZogyImagePsfMatchTask framework. Compare resulting diffim version with original, non-spatially-varying version. """ config = ZogyImagePsfMatchConfig() config.zogyMapReduceConfig.gridStepX = config.zogyMapReduceConfig.gridStepY = 9 config.zogyMapReduceConfig.borderSizeX = config.zogyMapReduceConfig.borderSizeY = 3 if inImageSpace: # need larger border size for image-space run config.zogyMapReduceConfig.gridStepX = config.zogyMapReduceConfig.gridStepY = 8 config.zogyMapReduceConfig.borderSizeX = config.zogyMapReduceConfig.borderSizeY = 6 task = ZogyImagePsfMatchTask(config=config) result = task.subtractExposures(self.im2ex, self.im1ex, inImageSpace=inImageSpace, doWarping=False, spatiallyVarying=spatiallyVarying) D_fromTask = result.subtractedExposure config = ZogyConfig() task = ZogyTask(templateExposure=self.im2ex, scienceExposure=self.im1ex, config=config) D = task.computeDiffim(inImageSpace=inImageSpace, **kwargs).D self._compareExposures(D_fromTask, D, tol=0.04, Scorr=doScorr)
def testGenerateGrid(self): """Test that the generated grid covers the whole image""" config = ZogyConfig() task = ZogyTask(config=config) bb = geom.Box2I(geom.Point2I(5, 10), geom.Extent2I(200, 300)) D = afwImage.ImageI(bb) grid = task.generateGrid(bb, geom.Extent2I(15, 15), geom.Extent2I(20, 30), powerOfTwo=True) for x in grid: h = x.outerBox.getHeight() w = x.outerBox.getWidth() self.assertTrue(isPowerOfTwo(h), "Box height is not power of two") self.assertTrue(isPowerOfTwo(w), "Box width is not power of two") D[x.innerBox] += 1 self.assertTrue( np.all(D.array == 1), "Grid inner boxes do not cover all pixels exactly once.")
def wrapZogyDiffim(config, templateExposure, scienceExposure): """Prepare and run ZOGY-style image differencing. Parameters ---------- config : `lsst.pex.config.Config` The image differencing Task configuration settings. templateExposure : `lsst.afw.image.ExposureF` The reference image to subtract from the science image. scienceExposure : `lsst.afw.image.ExposureF` The science image. Returns ------- `lsst.afw.image.ExposureF` The image difference. """ config.scaleByCalibration = False zogyTask = ZogyTask(config=config) result = zogyTask.run(scienceExposure, templateExposure) return result.diffExp
def testZogyNewImplementation(self): """DM-25115 implementation test. Notes ----- See diffimTests: tickets/DM-25115_zogy_implementation/DM-25115_zogy_unit_test_development.ipynb """ # self.svar = svar # variance of noise in science image # self.tvar = tvar # variance of noise in template image # Sourceless case self.im1ex, self.im2ex \ = makeFakeImages(size=(256, 256), svar=100., tvar=100., psf1=self.psf1_sigma, psf2=self.psf2_sigma, n_sources=0, psf_yvary_factor=0, varSourceChange=0.1, seed=1, verbose=False) config = ZogyConfig() config.scaleByCalibration = False task = ZogyTask(config=config) res = task.run(self.im1ex, self.im2ex) bbox = res.diffExp.getBBox() subBbox = bbox.erodedBy(lsst.geom.Extent2I(25, 25)) subExp = res.diffExp[subBbox] pixvar = self._computePixelVariance(subExp.maskedImage) varmean = self._computeVarianceMean(subExp.maskedImage) # Due to 3 sigma clipping, this is not so precise self.assertFloatsAlmostEqual(pixvar, 200, rtol=0.1, atol=None) self.assertFloatsAlmostEqual(varmean, 200, rtol=0.05, atol=None) S = res.scoreExp.image.array / np.sqrt(res.scoreExp.variance.array) self.assertLess(np.amax(S), 5.) # Source not detected # ========== self.im1ex, self.im2ex \ = makeFakeImages(size=(256, 256), svar=10., tvar=10., psf1=self.psf1_sigma, psf2=self.psf2_sigma, n_sources=10, psf_yvary_factor=0, varSourceChange=0.1, seed=1, verbose=False) task = ZogyTask(config=config) res = task.run(self.im1ex, self.im2ex) S = res.scoreExp.image.array / np.sqrt(res.scoreExp.variance.array) self.assertGreater(np.amax(S), 5.) # Source detected