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 convolveImage(self, maskedImage, psf, doSmooth=True): """Convolve the image with the PSF We convolve the image with a Gaussian approximation to the PSF, because this is separable and therefore fast. It's technically a correlation rather than a convolution, but since we use a symmetric Gaussian there's no difference. The convolution can be disabled with ``doSmooth=False``. If we do convolve, we mask the edges as ``EDGE`` and return the convolved image with the edges removed. This is because we can't convolve the edges because the kernel would extend off the image. Parameters ---------- maskedImage : `lsst.afw.image.MaskedImage` Image to convolve. psf : `lsst.afw.detection.Psf` PSF to convolve with (actually with a Gaussian approximation to it). doSmooth : `bool` Actually do the convolution? Set to False when running on e.g. a pre-convolved image, or a mask plane. Return Struct contents ---------------------- middle : `lsst.afw.image.MaskedImage` Convolved image, without the edges. sigma : `float` Gaussian sigma used for the convolution. """ self.metadata.set("doSmooth", doSmooth) sigma = psf.computeShape().getDeterminantRadius() self.metadata.set("sigma", sigma) if not doSmooth: middle = maskedImage.Factory(maskedImage) return pipeBase.Struct(middle=middle, sigma=sigma) # Smooth using a Gaussian (which is separable, hence fast) of width sigma # Make a SingleGaussian (separable) kernel with the 'sigma' kWidth = self.calculateKernelSize(sigma) self.metadata.set("smoothingKernelWidth", kWidth) gaussFunc = afwMath.GaussianFunction1D(sigma) gaussKernel = afwMath.SeparableKernel(kWidth, kWidth, gaussFunc, gaussFunc) convolvedImage = maskedImage.Factory(maskedImage.getBBox()) afwMath.convolve(convolvedImage, maskedImage, gaussKernel, afwMath.ConvolutionControl()) # # Only search psf-smoothed part of frame # goodBBox = gaussKernel.shrinkBBox(convolvedImage.getBBox()) middle = convolvedImage.Factory(convolvedImage, goodBBox, afwImage.PARENT, False) # # Mark the parts of the image outside goodBBox as EDGE # self.setEdgeBits(maskedImage, goodBBox, maskedImage.getMask().getPlaneBitMask("EDGE")) return pipeBase.Struct(middle=middle, sigma=sigma)