def testSetCtr(self): """Test setCtrCol/Row""" kWidth = 3 kHeight = 4 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel7.boost") persistence = dafPersist.Persistence.getPersistence(pol) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) for xCtr in range(kWidth): k.setCtrX(xCtr) for yCtr in range(kHeight): k.setCtrY(yCtr) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("AnalyticKernel", storageList2, additionalData) k2 = afwMath.AnalyticKernel.swigConvert(x) self.kernelCheck(k, k2) self.assertEqual(k2.getCtrX(), xCtr) self.assertEqual(k2.getCtrY(), yCtr)
def testZeroSizeKernel(self): """Creating a kernel with width or height < 1 should raise an exception. Note: this ignores the default constructors, which produce kernels with height = width = 0. The default constructors are only intended to support persistence, not to produce useful kernels. """ gaussFunc2D = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) gaussFunc1D = afwMath.GaussianFunction1D(1.0) zeroPoint = lsst.geom.Point2I(0, 0) for kWidth in (-1, 0, 1): for kHeight in (-1, 0, 1): if (kHeight > 0) and (kWidth > 0): continue if (kHeight >= 0) and (kWidth >= 0): # don't try to create an image with negative dimensions blankImage = afwImage.ImageF( lsst.geom.Extent2I(kWidth, kHeight)) self.assertRaises(Exception, afwMath.FixedKernel, blankImage) self.assertRaises(Exception, afwMath.AnalyticKernel, kWidth, kHeight, gaussFunc2D) self.assertRaises(Exception, afwMath.SeparableKernel, kWidth, kHeight, gaussFunc1D, gaussFunc1D) self.assertRaises(Exception, afwMath.DeltaFunctionKernel, kWidth, kHeight, zeroPoint)
def makeKernel(self): kCols = 7 kRows = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 0.1 maxSigma = 3.0 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters xSlope = (maxSigma - minSigma) / self.bbox.getWidth() ySlope = (maxSigma - minSigma) / self.bbox.getHeight() xOrigin = minSigma - (self.xy0[0] * xSlope) yOrigin = minSigma - (self.xy0[1] * ySlope) sParams = ( (xOrigin, xSlope, 0.0), (yOrigin, 0.0, ySlope), (0.0, 0.0, 0.0), ) kFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kCols, kRows, kFunc, sFunc) kernel.setSpatialParameters(sParams) return kernel
def testSpatiallyVaryingAnalyticConvolve(self): """Test in-place convolution with a spatially varying AnalyticKernel """ kWidth = 7 kHeight = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 1.5 maxSigma = 1.501 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (minSigma, (maxSigma - minSigma) / self.width, 0.0), (minSigma, 0.0, (maxSigma - minSigma) / self.height), (0.0, 0.0, 0.0), ) kFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 1.0e-5, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr="Spatially Varying Gaussian Analytic Kernel using %s" % (methodStr,), maxInterpDist=maxInterpDist, rtol=rtol)
def testSpatiallyVaryingSeparableConvolve(self): """Test convolution with a spatially varying SeparableKernel """ kWidth = 7 kHeight = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 0.1 maxSigma = 3.0 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (minSigma, (maxSigma - minSigma) / self.width, 0.0), (minSigma, 0.0, (maxSigma - minSigma) / self.height), (0.0, 0.0, 0.0), ) gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) separableKernel = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1, sFunc) analyticKernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2, sFunc) separableKernel.setSpatialParameters(sParams[0:2]) analyticKernel.setSpatialParameters(sParams) self.runStdTest(separableKernel, refKernel=analyticKernel, kernelDescr="Spatially Varying Gaussian Separable Kernel")
def addStar(image, center, flux, fwhm): """Add a perfect single Gaussian star to an image @warning uses Python to iterate over all pixels (because there is no C++ function that computes a Gaussian offset by a non-integral amount). @param[in,out] image: Image to which to add star @param[in] center: position of center of star on image (pair of float) @param[in] flux: flux of Gaussian star, in counts @param[in] fwhm: FWHM of Gaussian star, in pixels """ sigma = fwhm / FwhmPerSigma func = afwMath.GaussianFunction2D(sigma, sigma, 0) starImage = afwImage.ImageF(image.getBBox()) # The flux in the region of the image will not be exactly the desired flux because the Gaussian # does not extend to infinity, so keep track of the actual flux and correct for it actFlux = 0 # No function exists that has a fractional x and y offset, so set the image the slow way for i in range(image.getWidth()): x = center[0] - i for j in range(image.getHeight()): y = center[1] - j pixVal = flux * func(x, y) actFlux += pixVal starImage[i, j] += pixVal starImage *= flux / actFlux image += starImage
def _computeVaryingPsf(self): """Compute a varying PSF as a linear combination of PCA (== Karhunen-Loeve) basis functions We simply desire a PSF that is not constant across the image, so the precise choice of parameters (e.g., sigmas, setSpatialParameters) are not crucial. """ kernelSize = 31 sigma1 = 1.75 sigma2 = 2.0 * sigma1 basisKernelList = [] for sigma in (sigma1, sigma2): basisKernel = afwMath.AnalyticKernel( kernelSize, kernelSize, afwMath.GaussianFunction2D(sigma, sigma)) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImage /= np.sum(basisImage.getArray()) if sigma == sigma1: basisImage0 = basisImage else: basisImage -= basisImage0 basisKernelList.append(afwMath.FixedKernel(basisImage)) order = 1 spFunc = afwMath.PolynomialFunction2D(order) exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) exactKernel.setSpatialParameters([[1.0, 0, 0], [0.0, 0.5E-2, 0.2E-2]]) exactPsf = measAlg.PcaPsf(exactKernel) return exactPsf
def testAnalyticKernel(self): """Test AnalyticKernel using a Gaussian function """ kWidth = 5 kHeight = 8 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) fArr = np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) for xsigma in (0.1, 1.0, 3.0): for ysigma in (0.1, 1.0, 3.0): for angle in (0.0, 0.4, 1.1): gaussFunc.setParameters((xsigma, ysigma, angle)) # compute array of function values and normalize for row in range(k.getHeight()): y = row - k.getCtrY() for col in range(k.getWidth()): x = col - k.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() k.setKernelParameters((xsigma, ysigma, angle)) with lsst.utils.tests.getTempFilePath(".fits") as filename: k.writeFits(filename) k2 = afwMath.AnalyticKernel.readFits(filename) self.kernelCheck(k, k2) kImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not np.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % (k2.__class__.__name__, kArr, fArr, xsigma, ysigma))
def testSVAnalyticKernel(self): """Test spatially varying AnalyticKernel using a Gaussian function Just tests cloning. """ kWidth = 5 kHeight = 8 # spatial model spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, 1.0, 0.0), (1.0, 0.0, 1.0), (0.5, 0.5, 0.5), ) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc, spFunc) kernel.setSpatialParameters(sParams) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) newSParams = ( (0.1, 0.2, 0.5), (0.1, 0.5, 0.2), (0.2, 0.3, 0.3), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail( "Clone was modified by changing original's spatial parameters") # # check that we can construct a FixedKernel from a LinearCombinationKernel # x, y = 100, 200 kernel2 = afwMath.FixedKernel(kernel, lsst.geom.PointD(x, y)) self.assertTrue(re.search("AnalyticKernel", kernel.toString())) self.assertFalse(kernel2.isSpatiallyVarying()) self.assertTrue(re.search("FixedKernel", kernel2.toString())) self.assertTrue(kernel.isSpatiallyVarying()) kim = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kim, True, x, y) kim2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(kim2, True) assert_allclose(kim.getArray(), kim2.getArray())
def testLinearCombinationKernelAnalytic(self): """Test LinearCombinationKernel using analytic basis kernels. The basis kernels are mutable so that we can verify that the LinearCombinationKernel has private copies of the basis kernels. """ kWidth = 5 kHeight = 8 # create list of kernels basisImArrList = [] basisKernelList = afwMath.KernelList() for basisKernelParams in [(1.2, 0.3, 1.570796), (1.0, 0.2, 0.0)]: basisKernelFunction = afwMath.GaussianFunction2D( *basisKernelParams) basisKernel = afwMath.AnalyticKernel(kWidth, kHeight, basisKernelFunction) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray()) basisKernelList.append(basisKernel) kParams = [0.0] * len(basisKernelList) kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams) self.assertTrue(not kernel.isDeltaFunctionBasis()) self.basicTests(kernel, len(kParams)) # make sure the linear combination kernel has private copies of its basis kernels # by altering the local basis kernels and making sure the new images do NOT match modBasisImArrList = [] for basisKernel in basisKernelList: basisKernel.setKernelParameters((0.4, 0.5, 0.6)) modBasisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(modBasisImage, True) modBasisImArrList.append(modBasisImage.getArray()) for ii in range(len(basisKernelList)): kParams = [0.0] * len(basisKernelList) kParams[ii] = 1.0 kernel.setKernelParameters(kParams) kIm = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kIm, True) kImArr = kIm.getArray() if not np.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii)) if np.allclose(kImArr, modBasisImArrList[ii]): self.fail("%s = %s == %s for *modified* %s'th basis kernel" % (kernel.__class__.__name__, kImArr, modBasisImArrList[ii], ii)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False)
def testMakeBadKernels(self): """Attempt to make various invalid kernels; make sure the constructor shows an exception """ kWidth = 4 kHeight = 3 gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) spFunc = afwMath.PolynomialFunction2D(1) kernelList = [] kernelList.append(afwMath.FixedKernel( afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight), 0.1))) kernelList.append(afwMath.FixedKernel( afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight), 0.2))) for numKernelParams in (2, 4): spFuncList = [] for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2, spFuncList) self.fail("Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass for numKernelParams in (1, 3): spFuncList = [] for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.LinearCombinationKernel(kernelList, spFuncList) self.fail("Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass kParamList = [0.2]*numKernelParams try: afwMath.LinearCombinationKernel(kernelList, kParamList) self.fail("Should have failed with wrong # of kernel parameters") except pexExcept.Exception: pass try: afwMath.SeparableKernel( kWidth, kHeight, gaussFunc1, gaussFunc1, spFuncList) self.fail("Should have failed with wrong # of spatial functions") except pexExcept.Exception: pass for pointX in range(-1, kWidth+2): for pointY in range(-1, kHeight+2): if (0 <= pointX < kWidth) and (0 <= pointY < kHeight): continue try: afwMath.DeltaFunctionKernel( kWidth, kHeight, lsst.geom.Point2I(pointX, pointY)) self.fail("Should have failed with point not on kernel") except pexExcept.Exception: pass
def makeSpatialKernel(self, order): basicGaussian1 = afwMath.GaussianFunction2D(2., 2., 0.) basicKernel1 = afwMath.AnalyticKernel(self.ksize, self.ksize, basicGaussian1) basicGaussian2 = afwMath.GaussianFunction2D(5., 3., 0.5 * num.pi) basicKernel2 = afwMath.AnalyticKernel(self.ksize, self.ksize, basicGaussian2) basisList = [] basisList.append(basicKernel1) basisList.append(basicKernel2) basisList = ipDiffim.renormalizeKernelList(basisList) spatialKernelFunction = afwMath.PolynomialFunction2D(order) spatialKernel = afwMath.LinearCombinationKernel(basisList, spatialKernelFunction) kCoeffs = [[0.0 for x in range(1, spatialKernelFunction.getNParameters()+1)], [0.01 * x for x in range(1, spatialKernelFunction.getNParameters()+1)]] kCoeffs[0][0] = 1.0 # it does not vary spatially; constant across image spatialKernel.setSpatialParameters(kCoeffs) return spatialKernel
def testSpatiallyInvariantConvolve(self): """Test convolution with a spatially invariant Gaussian function """ kWidth = 6 kHeight = 7 kFunc = afwMath.GaussianFunction2D(2.5, 1.5, 0.5) kernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc) self.runStdTest(kernel, kernelDescr="Gaussian Analytic Kernel")
def testDoubleGaussianFunction2D(self): """Note: Assumes GaussianFunction2D is correct (tested elsewhere).""" errMsg = "{} = {} != {} for x={}, y={}, sigma1={}, sigma2={}, b={}" areaMsg = "{} area = {} != 1.0 for sigma1={}, sigma2={}" f = afwMath.DoubleGaussianFunction2D(1.0, 1.0) f1 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) f2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for sigma1 in (1.0,): for sigma2 in (0.5, 2.0): for b in (0.0, 0.2, 2.0): f.setParameters((sigma1, sigma2, b)) g = f.clone() f1.setParameters((sigma1, sigma1, 0.0)) f2.setParameters((sigma2, sigma2, 0.0)) sigma1Sq = sigma1**2 sigma2Sq = sigma2**2 f1Mult = b * sigma2Sq / sigma1Sq allMult = sigma1Sq / (sigma1Sq + (b * sigma2Sq)) fSum = 0.0 maxsigma = max(sigma1, sigma2) minsigma = min(sigma1, sigma2) delta = minsigma / 5.0 for y in np.arange(-maxsigma * 5, maxsigma * 5.01, delta): for x in np.arange(-maxsigma * 5.0, maxsigma * 5.01, delta): predVal = ( f1(x, y) + (f1Mult * f2(x, y))) * allMult fSum += predVal msg = errMsg.format( type(f).__name__, f(x, y), predVal, x, y, sigma1, sigma2, b) self.assertFloatsAlmostEqual( f(x, y), predVal, msg=msg, atol=self.atol, rtol=None) msg = errMsg.format(type(g).__name__, g(x, y), predVal, x, y, sigma1, sigma2, b) + "; clone" self.assertFloatsAlmostEqual( g(x, y), predVal, msg=msg, atol=self.atol, rtol=None) approxArea = fSum * delta**2 msg = areaMsg.format( type(f).__name__, approxArea, sigma1, sigma2) # approxArea is very approximate, so we need a high # tolerance threshold. self.assertFloatsAlmostEqual( approxArea, 1.0, msg=msg, atol=1e-6, rtol=None)
def testGaussian(self, imsize=50): # Convolve a delta function with a known gaussian; try to # recover using delta-function basis gsize = self.ps["kernelSize"] tsize = imsize + gsize gaussFunction = afwMath.GaussianFunction2D(2, 3) gaussKernel = afwMath.AnalyticKernel(gsize, gsize, gaussFunction) kImageIn = afwImage.ImageD(geom.Extent2I(gsize, gsize)) gaussKernel.computeImage(kImageIn, False) # template image with a single hot pixel in the exact center tmi = afwImage.MaskedImageF(geom.Extent2I(tsize, tsize)) tmi.set(0, 0x0, 1e-4) cpix = tsize // 2 tmi[cpix, cpix, afwImage.LOCAL] = (1, 0x0, 1) # science image smi = afwImage.MaskedImageF(tmi.getDimensions()) convolutionControl = afwMath.ConvolutionControl() convolutionControl.setDoNormalize(False) afwMath.convolve(smi, tmi, gaussKernel, convolutionControl) # get the actual kernel sum (since the image is not infinite) gscaling = afwMath.makeStatistics(smi, afwMath.SUM).getValue(afwMath.SUM) # grab only the non-masked subregion bbox = gaussKernel.shrinkBBox(smi.getBBox(afwImage.LOCAL)) tmi2 = afwImage.MaskedImageF(tmi, bbox, origin=afwImage.LOCAL) smi2 = afwImage.MaskedImageF(smi, bbox, origin=afwImage.LOCAL) # make sure its a valid subregion! for j in range(tmi2.getHeight()): for i in range(tmi2.getWidth()): self.assertEqual(tmi2.mask[i, j, afwImage.LOCAL], 0) self.assertEqual(smi2.mask[i, j, afwImage.LOCAL], 0) kc = ipDiffim.KernelCandidateF(0.0, 0.0, tmi2, smi2, self.ps) kList = ipDiffim.makeKernelBasisList(self.subconfig) kc.build(kList) self.assertEqual(kc.isInitialized(), True) kImageOut = kc.getImage() soln = kc.getKernelSolution(ipDiffim.KernelCandidateF.RECENT) self.assertAlmostEqual(soln.getKsum(), gscaling) self.assertAlmostEqual(soln.getBackground(), 0.0) for j in range(kImageOut.getHeight()): for i in range(kImageOut.getWidth()): self.assertAlmostEqual( kImageOut[i, j, afwImage.LOCAL] / kImageIn[i, j, afwImage.LOCAL], 1.0, 5)
def testSetCtr(self): """Test setCtrCol/Row""" kWidth = 3 kHeight = 4 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) for xCtr in range(kWidth): for yCtr in range(kHeight): center = lsst.geom.Point2I(xCtr, yCtr) kernel.setCtr(center) self.assertEqual(kernel.getCtr(), center)
def makeTest3(doAddNoise): gaussian1 = afwMath.GaussianFunction2D(1. * gScale, 1. * gScale, 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, doNorm) image1 *= scaling # total counts = scaling image1 = image1.convertF() mask1 = afwImage.MaskU(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) gaussian2 = afwMath.GaussianFunction2D(2. * gScale, 1.5 * gScale, 0.5 * num.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, doNorm) image2 *= scaling # total counts = scaling image2 = image2.convertF() mask2 = afwImage.MaskU(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) image3 = afwImage.ImageF(image1, True) for y in range(imSize): for x in range(imSize // 2): image3.set(x, y, image2.get(x, y)) counts = afwMath.makeStatistics(image3, afwMath.SUM).getValue() image3 /= counts image3 *= scaling mask3 = afwImage.MaskU(image3.getDimensions()) var3 = afwImage.ImageF(image3, True) mi3 = afwImage.MaskedImageF(image3, mask3, var3) if doAddNoise: addNoise(mi1) addNoise(mi2) addNoise(mi3) return mi1, mi2, mi3
def testSeparableKernel(self): """Test SeparableKernel using a Gaussian function """ kWidth = 5 kHeight = 8 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation( os.path.join(testPath, "data", "kernel4.boost")) persistence = dafPersist.Persistence.getPersistence(pol) gaussFunc1 = afwMath.GaussianFunction1D(1.0) k = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1) fArr = np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) np.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for xsigma in (0.1, 1.0, 3.0): gaussFunc1.setParameters((xsigma, )) for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(k.getHeight()): y = row - k.getCtrY() for col in range(k.getWidth()): x = col - k.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() k.setKernelParameters((xsigma, ysigma)) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("SeparableKernel", storageList2, additionalData) k2 = afwMath.SeparableKernel.swigConvert(x) self.kernelCheck(k, k2) kImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not np.allclose(fArr, kArr): self.fail( "%s = %s != %s for xsigma=%s, ysigma=%s" % (k2.__class__.__name__, kArr, fArr, xsigma, ysigma))
def testGaussianFunction2D(self): """Note: Assumes GaussianFunction1D is correct (tested elsewhere).""" errMsg = "{} = {} != {} for pos1={}, pos2={}, x={}, y={}, sigma1={}, sigma2={}, angle={}" areaMsg = "%s area = %s != 1.0 for sigma1=%s, sigma2=%s" f = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) f1 = afwMath.GaussianFunction1D(1.0) f2 = afwMath.GaussianFunction1D(1.0) for sigma1 in (0.1, 1.0, 3.0): for sigma2 in (0.1, 1.0, 3.0): for angle in (0.0, 0.4, 1.1): sinNegAngle = math.sin(-angle) cosNegAngle = math.cos(-angle) f.setParameters((sigma1, sigma2, angle)) g = f.clone() f1.setParameters((sigma1, )) f2.setParameters((sigma2, )) fSum = 0.0 delta1 = sigma1 / 5.0 delta2 = sigma2 / 5.0 for pos1 in np.arange(-sigma1 * 5, sigma1 * 5.01, delta1): for pos2 in np.arange(-sigma2 * 5.0, sigma2 * 5.01, delta2): x = (cosNegAngle * pos1) + (sinNegAngle * pos2) y = (-sinNegAngle * pos1) + (cosNegAngle * pos2) predVal = f1(pos1) * f2(pos2) fSum += predVal msg = errMsg.format( type(f).__name__, f(x, y), predVal, pos1, pos2, x, y, sigma1, sigma2, angle) self.assertFloatsAlmostEqual(f(x, y), predVal, msg=msg, atol=self.atol, rtol=None) msg = errMsg.format( type(g).__name__, g(x, y), predVal, pos1, pos2, x, y, sigma1, sigma2, angle) + "; clone" self.assertFloatsAlmostEqual(g(x, y), predVal, msg=msg, atol=self.atol, rtol=None) approxArea = fSum * delta1 * delta2 msg = areaMsg % (type(f).__name__, approxArea, sigma1, sigma2) # approxArea is very approximate, so we need a high # tolerance threshold. self.assertFloatsAlmostEqual(approxArea, 1.0, msg=msg, atol=1e-6, rtol=None)
def makeTest2(doAddNoise, shiftX=int(2.0 * gScale), shiftY=int(1.0 * gScale)): gaussian1 = afwMath.GaussianFunction2D(1. * gScale, 1. * gScale, 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, doNorm) image1 = image1.convertF() #### boxA = afwGeom.Box2I(afwGeom.PointI(0, 0), afwGeom.ExtentI(imSize - shiftX, imSize - shiftY)) boxB = afwGeom.Box2I(afwGeom.PointI(shiftX, shiftY), afwGeom.ExtentI(imSize - shiftX, imSize - shiftY)) subregA = afwImage.ImageF(image1, boxA, afwImage.LOCAL) subregB = afwImage.ImageF(image1, boxB, afwImage.LOCAL, True) subregA += subregB # this messes up the total counts so rescale counts = afwMath.makeStatistics(image1, afwMath.SUM).getValue() image1 /= counts image1 *= scaling ### mask1 = afwImage.Mask(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2. * gScale, 1.5 * gScale, 0.5 * np.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, doNorm) image2 *= scaling # total counts = scaling image2 = image2.convertF() mask2 = afwImage.Mask(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2
def testFixedKernelConvolve(self): """Test convolve with a fixed kernel """ kWidth = 6 kHeight = 7 kFunc = afwMath.GaussianFunction2D(2.5, 1.5, 0.5) analyticKernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc) kernelImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) analyticKernel.computeImage(kernelImage, False) fixedKernel = afwMath.FixedKernel(kernelImage) self.runStdTest(fixedKernel, kernelDescr="Gaussian FixedKernel")
def testSetCtr(self): """Test setCtrCol/Row""" kWidth = 3 kHeight = 4 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) for xCtr in range(kWidth): kernel.setCtrX(xCtr) for yCtr in range(kHeight): kernel.setCtrY(yCtr) self.assertEqual(kernel.getCtrX(), xCtr) self.assertEqual(kernel.getCtrY(), yCtr)
def testRenormalize(self): # inputs gauss1 = afwMath.GaussianFunction2D(2, 2) gauss2 = afwMath.GaussianFunction2D(3, 4) gauss3 = afwMath.GaussianFunction2D(0.2, 0.25) gaussKernel1 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss1) gaussKernel2 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss2) gaussKernel3 = afwMath.AnalyticKernel(self.kSize, self.kSize, gauss3) kimage1 = afwImage.ImageD(gaussKernel1.getDimensions()) ksum1 = gaussKernel1.computeImage(kimage1, False) kimage2 = afwImage.ImageD(gaussKernel2.getDimensions()) ksum2 = gaussKernel2.computeImage(kimage2, False) kimage3 = afwImage.ImageD(gaussKernel3.getDimensions()) ksum3 = gaussKernel3.computeImage(kimage3, False) self.assertNotEqual(ksum1, 1.) self.assertNotEqual(ksum2, 1.) self.assertNotEqual(ksum3, 1.) # no constraints on first kernels norm self.assertNotEqual(num.sum(num.ravel(kimage2.getArray())**2), 1.) self.assertNotEqual(num.sum(num.ravel(kimage3.getArray())**2), 1.) basisListIn = [] basisListIn.append(gaussKernel1) basisListIn.append(gaussKernel2) basisListIn.append(gaussKernel3) # outputs basisListOut = ipDiffim.renormalizeKernelList(basisListIn) gaussKernel1 = basisListOut[0] gaussKernel2 = basisListOut[1] gaussKernel3 = basisListOut[2] ksum1 = gaussKernel1.computeImage(kimage1, False) ksum2 = gaussKernel2.computeImage(kimage2, False) ksum3 = gaussKernel3.computeImage(kimage3, False) self.assertAlmostEqual(ksum1, 1.) self.assertAlmostEqual(ksum2, 0.) self.assertAlmostEqual(ksum3, 0.) # no constraints on first kernels norm self.assertAlmostEqual(num.sum(num.ravel(kimage2.getArray())**2), 1.) self.assertAlmostEqual(num.sum(num.ravel(kimage3.getArray())**2), 1.)
def testDoubleGaussianFunction2D(self): """A test for DoubleGaussianFunction2D Assumes GaussianFunction2D is correct (tested elsewhere) """ f = afwMath.DoubleGaussianFunction2D(1.0, 1.0) f1 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) f2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for sigma1 in (1.0, ): for sigma2 in (0.5, 2.0): for b in (0.0, 0.2, 2.0): f.setParameters((sigma1, sigma2, b)) g = f.clone() f1.setParameters((sigma1, sigma1, 0.0)) f2.setParameters((sigma2, sigma2, 0.0)) sigma1Sq = sigma1**2 sigma2Sq = sigma2**2 f1Mult = b * sigma2Sq / sigma1Sq allMult = sigma1Sq / (sigma1Sq + (b * sigma2Sq)) fSum = 0.0 maxsigma = max(sigma1, sigma2) minsigma = min(sigma1, sigma2) delta = minsigma / 5.0 for y in numpy.arange(-maxsigma * 5, maxsigma * 5.01, delta): for x in numpy.arange(-maxsigma * 5.0, maxsigma * 5.01, delta): predVal = (f1(x, y) + (f1Mult * f2(x, y))) * allMult fSum += predVal if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, sigma1=%s, sigma2=%s, b=%s" % \ (type(f).__name__, f(x, y), predVal, x, y, sigma1, sigma2, b)) if not numpy.allclose(predVal, g(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, sigma1=%s, sigma2=%s, b=%s; clone" %\ (type(g).__name__, g(x, y), predVal, x, y, sigma1, sigma2, b)) approxArea = fSum * delta**2 if not numpy.allclose(approxArea, 1.0): self.fail("%s area = %s != 1.0 for sigma1=%s, sigma2=%s" % \ (type(f).__name__, approxArea, sigma1, sigma2))
def createImageAndKernel(sigma, psfSize, image): function = afwMath.GaussianFunction2D(sigma, sigma) kernel = afwMath.AnalyticKernel(psfSize, psfSize, function) psf = measAlg.KernelPsf(kernel) cim = afwImage.ImageF(image.getDimensions()) afwMath.convolve(cim, image, kernel, True) # Trim off the border pixels bbox = kernel.shrinkBBox(cim.getBBox(afwImage.LOCAL)) cim = afwImage.ImageF(cim, bbox, afwImage.LOCAL) cim.setXY0(0, 0) return cim, psf
def testAnalyticKernel(self): """Test AnalyticKernel using a Gaussian function """ kWidth = 5 kHeight = 8 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) self.basicTests(kernel, 3, dimMustMatch=False) kernelResized = self.verifyResized(kernel) self.basicTests(kernelResized, 3, dimMustMatch=False) fArr = np.zeros(shape=[kernel.getWidth(), kernel.getHeight()], dtype=float) for xsigma in (0.1, 1.0, 3.0): for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(kernel.getHeight()): y = row - kernel.getCtrY() for col in range(kernel.getWidth()): x = col - kernel.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() kernel.setKernelParameters((xsigma, ysigma, 0.0)) kImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not np.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % (kernel.__class__.__name__, kArr, fArr, xsigma, ysigma)) kernel.setKernelParameters((0.5, 1.1, 0.3)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) kernel.setKernelParameters((1.5, 0.2, 0.7)) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail( "Clone was modified by changing original's kernel parameters") self.verifyCache(kernel, hasCache=False)
def makeTest1(doAddNoise): gaussian1 = afwMath.GaussianFunction2D(1., 1., 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, False) image1 *= 10000 image1 = image1.convertF() mask1 = afwImage.MaskU(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2., 1.5, 0.5 * num.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, False) image2 *= 10000 image2 = image2.convertF() mask2 = afwImage.MaskU(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2
def makeGaussianKernelList(kWidth, kHeight, gaussParamsList): """Create a list of gaussian kernels. This is useful for constructing a LinearCombinationKernel. Inputs: - kWidth, kHeight: width and height of kernel - gaussParamsList: a list of parameters for GaussianFunction2D (each a 3-tuple of floats) """ kVec = [] for majorSigma, minorSigma, angle in gaussParamsList: kFunc = afwMath.GaussianFunction2D(majorSigma, minorSigma, angle) kVec.append(afwMath.AnalyticKernel(kWidth, kHeight, kFunc)) return kVec
def testSeparableKernel(self): """Test SeparableKernel using a Gaussian function """ kWidth = 5 kHeight = 8 gaussFunc1 = afwMath.GaussianFunction1D(1.0) kernel = afwMath.SeparableKernel( kWidth, kHeight, gaussFunc1, gaussFunc1) center = kernel.getCtr() self.basicTests(kernel, 2) kernelResized = self.verifyResized(kernel) self.basicTests(kernelResized, 2) fArr = np.zeros( shape=[kernel.getWidth(), kernel.getHeight()], dtype=float) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for xsigma in (0.1, 1.0, 3.0): gaussFunc1.setParameters((xsigma,)) for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(kernel.getHeight()): y = row - center.getY() for col in range(kernel.getWidth()): x = col - center.getX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() kernel.setKernelParameters((xsigma, ysigma)) kImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not np.allclose(fArr, kArr): self.fail(f"{kernel.__class__.__name__} = {kArr} != " f"{fArr} for xsigma={xsigma}, ysigma={ysigma}") kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) kernel.setKernelParameters((1.2, 0.6)) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail( "Clone was modified by changing original's kernel parameters") self.verifyCache(kernel, hasCache=True)
def makeTest2(doAddNoise, shiftX=5, shiftY=3): gaussian1 = afwMath.GaussianFunction2D(1., 1., 0.) kernel1 = afwMath.AnalyticKernel(imSize, imSize, gaussian1) image1 = afwImage.ImageD(kernel1.getDimensions()) kernel1.computeImage(image1, False) image1 *= 10000 image1 = image1.convertF() #### boxA = afwGeom.Box2I(afwGeom.PointI(imSize // 2, imSize // 2), afwGeom.ExtentI(imSize // 2, imSize // 2)) boxB = afwGeom.Box2I( afwGeom.PointI(imSize // 2 - shiftX, imSize // 2 - shiftY), afwGeom.ExtentI(imSize // 2, imSize // 2)) subregA = afwImage.ImageF(image1, boxA, afwImage.PARENT) subregB = afwImage.ImageF(image1, boxB, afwImage.PARENT, True) subregA += subregB ### mask1 = afwImage.Mask(kernel1.getDimensions()) var1 = afwImage.ImageF(image1, True) mi1 = afwImage.MaskedImageF(image1, mask1, var1) if doAddNoise: addNoise(mi1) gaussian2 = afwMath.GaussianFunction2D(2., 1.5, 0.5 * num.pi) kernel2 = afwMath.AnalyticKernel(imSize, imSize, gaussian2) image2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(image2, False) image2 *= 10000 image2 = image2.convertF() mask2 = afwImage.Mask(kernel2.getDimensions()) var2 = afwImage.ImageF(image2, True) mi2 = afwImage.MaskedImageF(image2, mask2, var2) if doAddNoise: addNoise(mi2) return mi1, mi2