Beispiel #1
0
    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
Beispiel #2
0
    def testRefactorDeltaLinearCombinationKernel(self):
        """Test LinearCombinationKernel.refactor with delta function basis kernels
        """
        kWidth = 4
        kHeight = 3

        for spOrder in (0, 1, 2):
            spFunc = afwMath.PolynomialFunction2D(spOrder)
            numSpParams = spFunc.getNParameters()

            basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight)
            kernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)

            numBasisKernels = kernel.getNKernelParameters()
            maxVal = 1.01 + ((numSpParams - 1) * 0.1)
            sParamList = [
                numpy.arange(kInd + 1.0, kInd + maxVal, 0.1)
                for kInd in range(numBasisKernels)
            ]
            kernel.setSpatialParameters(sParamList)

            refKernel = kernel.refactor()
            self.assert_(refKernel)
            errStr = self.compareKernels(kernel,
                                         refKernel,
                                         compareParams=False)
            if errStr:
                self.fail("failed with %s for spOrder=%s (numSpCoeff=%s)" %
                          (errStr, spOrder, numSpParams))
Beispiel #3
0
    def testSpatiallyVaryingDeltaFunctionLinearCombination(self):
        """Test convolution with a spatially varying LinearCombinationKernel of delta function basis kernels.
        """
        kWidth = 2
        kHeight = 2

        # create spatially model
        sFunc = 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, -0.5 / self.width, -0.5 / self.height),
            (0.0, 1.0 / self.width, 0.0 / self.height),
            (0.0, 0.0 / self.width, 1.0 / self.height),
            (0.5, 0.0, 0.0),
        )

        basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight)
        kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc)
        kernel.setSpatialParameters(sParams)

        for maxInterpDist, rtol, methodStr in (
            (0, 1.0e-5, "brute force"),
            (10, 1.0e-3, "interpolation over 10 x 10 pixels"),
        ):
            self.runStdTest(
                kernel,
                kernelDescr=
                "Spatially varying LinearCombinationKernel of delta function kernels using %s"
                % (methodStr, ),
                maxInterpDist=maxInterpDist,
                rtol=rtol)
Beispiel #4
0
    def testLinearCombinationKernelDelta(self):
        """Test LinearCombinationKernel using a set of delta basis functions
        """
        kWidth = 3
        kHeight = 2

        # create list of kernels
        basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight)
        basisImArrList = []
        for basisKernel in basisKernelList:
            basisImage = afwImage.ImageD(basisKernel.getDimensions())
            basisKernel.computeImage(basisImage, True)
            basisImArrList.append(basisImage.getArray())

        kParams = [0.0] * len(basisKernelList)
        kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams)
        self.assert_(kernel.isDeltaFunctionBasis())
        self.basicTests(kernel, len(kParams))
        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 numpy.allclose(kImArr, basisImArrList[ii]):
                self.fail("%s = %s != %s for the %s'th basis kernel" % \
                    (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii))

        kernelClone = kernel.clone()
        errStr = self.compareKernels(kernel, kernelClone)
        if errStr:
            self.fail(errStr)

        self.verifyCache(kernel, hasCache=False)
Beispiel #5
0
    def testRefactorGaussianLinearCombinationKernel(self):
        """Test LinearCombinationKernel.refactor with Gaussian basis kernels
        """
        kWidth = 4
        kHeight = 3

        for spOrder in (0, 1, 2):
            spFunc = afwMath.PolynomialFunction2D(spOrder)
            numSpParams = spFunc.getNParameters()

            gaussParamsList = [
                (1.5, 1.5, 0.0),
                (2.5, 1.5, 0.0),
                (2.5, 1.5, math.pi / 2.0),
            ]
            gaussBasisKernelList = makeGaussianKernelList(
                kWidth, kHeight, gaussParamsList)
            kernel = afwMath.LinearCombinationKernel(
                gaussBasisKernelList, spFunc)

            numBasisKernels = kernel.getNKernelParameters()
            maxVal = 1.01 + ((numSpParams - 1) * 0.1)
            sParamList = [np.arange(kInd + 1.0, kInd + maxVal, 0.1)
                          for kInd in range(numBasisKernels)]
            kernel.setSpatialParameters(sParamList)

            refKernel = kernel.refactor()
            self.assertTrue(refKernel)
            errStr = self.compareKernels(
                kernel, refKernel, compareParams=False)
            if errStr:
                self.fail(f"failed with {errStr} for spOrder={spOrder}, numSpParams={numSpParams}")
Beispiel #6
0
    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
Beispiel #7
0
    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 = []
        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))

        kernelResized = self.verifyResized(kernel)
        self.basicTests(kernelResized, 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(f"{kernel.__class__.__name__} = {kImArr} != "
                          f"{basisImArrList[ii]} for the {ii}'th basis kernel")
            if np.allclose(kImArr, modBasisImArrList[ii]):
                self.fail(f"{kernel.__class__.__name__} = {kImArr} != "
                          f"{modBasisImArrList[ii]} for *modified* {ii}'th basis kernel")

        kernelClone = kernel.clone()
        errStr = self.compareKernels(kernel, kernelClone)
        if errStr:
            self.fail(errStr)

        self.verifyCache(kernel, hasCache=False)
    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
Beispiel #9
0
    def testSVLinearCombinationKernel(self):
        """Test a spatially varying LinearCombinationKernel
        """
        kWidth = 3
        kHeight = 2

        # create image arrays for the basis kernels
        basisImArrList = []
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.1
        imArr[kWidth // 2, :] = 0.9
        basisImArrList.append(imArr)
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.2
        imArr[:, kHeight // 2] = 0.8
        basisImArrList.append(imArr)

        # create a list of basis kernels from the images
        kVec = []
        for basisImArr in basisImArrList:
            basisImage = afwImage.makeImageFromArray(
                basisImArr.transpose().copy())
            kernel = afwMath.FixedKernel(basisImage)
            kVec.append(kernel)

        # create spatially varying linear combination kernel
        spFunc = afwMath.PolynomialFunction2D(1)

        # spatial parameters are a list of entries, one per kernel parameter;
        # each entry is a list of spatial parameters
        sParams = (
            (0.0, 1.0, 0.0),
            (0.0, 0.0, 1.0),
        )

        k = afwMath.LinearCombinationKernel(kVec, spFunc)
        k.setSpatialParameters(sParams)

        with lsst.utils.tests.getTempFilePath(".fits") as filename:
            k.writeFits(filename)
            k2 = afwMath.LinearCombinationKernel.readFits(filename)

        self.kernelCheck(k, k2)

        kImage = afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight))
        for colPos, rowPos, coeff0, coeff1 in [
            (0.0, 0.0, 0.0, 0.0),
            (1.0, 0.0, 1.0, 0.0),
            (0.0, 1.0, 0.0, 1.0),
            (1.0, 1.0, 1.0, 1.0),
            (0.5, 0.5, 0.5, 0.5),
        ]:
            k2.computeImage(kImage, False, colPos, rowPos)
            kImArr = kImage.getArray().transpose()
            refKImArr = (basisImArrList[0] * coeff0) + \
                (basisImArrList[1] * coeff1)
            if not np.allclose(kImArr, refKImArr):
                self.fail(f"{k2.__class__.__name__} = {kImArr} != {refKImArr} "
                          f"at colPos={colPos}, rowPos={rowPos}")
Beispiel #10
0
    def testLinearCombinationKernel(self):
        """Test LinearCombinationKernel using a set of delta basis functions
        """
        kWidth = 3
        kHeight = 2

        pol = pexPolicy.Policy()
        additionalData = dafBase.PropertySet()
        loc = dafPersist.LogicalLocation(
            os.path.join(testPath, "data", "kernel5.boost"))
        persistence = dafPersist.Persistence.getPersistence(pol)

        # create list of kernels
        basisImArrList = []
        kVec = afwMath.KernelList()
        for row in range(kHeight):
            for col in range(kWidth):
                kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight,
                                                     afwGeom.Point2I(col, row))
                basisImage = afwImage.ImageD(kernel.getDimensions())
                kernel.computeImage(basisImage, True)
                basisImArrList.append(basisImage.getArray().transpose().copy())
                kVec.append(kernel)

        kParams = [0.0] * len(kVec)
        k = afwMath.LinearCombinationKernel(kVec, kParams)
        for ii in range(len(kVec)):
            kParams = [0.0] * len(kVec)
            kParams[ii] = 1.0
            k.setKernelParameters(kParams)

            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("LinearCombinationKernel",
                                           storageList2, additionalData)
            k2 = afwMath.LinearCombinationKernel.swigConvert(x)

            self.kernelCheck(k, k2)

            kIm = afwImage.ImageD(k2.getDimensions())
            k2.computeImage(kIm, True)
            kImArr = kIm.getArray().transpose()
            if not np.allclose(kImArr, basisImArrList[ii]):
                self.fail(
                    "%s = %s != %s for the %s'th basis kernel" %
                    (k2.__class__.__name__, kImArr, basisImArrList[ii], ii))
Beispiel #11
0
    def testTicket873(self):
        """Demonstrate ticket 873: convolution of a MaskedImage with a spatially varying
        LinearCombinationKernel of basis kernels with low covariance gives incorrect variance.
        """
        # create spatial model
        sFunc = 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, -0.5/self.width, -0.5/self.height),
            (0.0, 1.0/self.width, 0.0/self.height),
            (0.0, 0.0/self.width, 1.0/self.height),
        )

        # create three kernels with some non-overlapping pixels
        # (non-zero pixels in one kernel vs. zero pixels in other kernels);
        # note: the extreme example of this is delta function kernels, but this
        # is less extreme
        basisKernelList = []
        kImArr = numpy.zeros([5, 5], dtype=float)
        kImArr[1:4, 1:4] = 0.5
        kImArr[2, 2] = 1.0
        kImage = afwImage.makeImageFromArray(kImArr)
        basisKernelList.append(afwMath.FixedKernel(kImage))
        kImArr[:, :] = 0.0
        kImArr[0:2, 0:2] = 0.125
        kImArr[3:5, 3:5] = 0.125
        kImage = afwImage.makeImageFromArray(kImArr)
        basisKernelList.append(afwMath.FixedKernel(kImage))
        kImArr[:, :] = 0.0
        kImArr[0:2, 3:5] = 0.125
        kImArr[3:5, 0:2] = 0.125
        kImage = afwImage.makeImageFromArray(kImArr)
        basisKernelList.append(afwMath.FixedKernel(kImage))

        kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc)
        kernel.setSpatialParameters(sParams)

        for maxInterpDist, rtol, methodStr in (
            (0, 1.0e-5, "brute force"),
            (10, 3.0e-3, "interpolation over 10 x 10 pixels"),
        ):
            self.runStdTest(
                kernel,
                kernelDescr="Spatially varying LinearCombinationKernel of basis "
                            "kernels with low covariance, using %s" % (
                                methodStr,),
                maxInterpDist=maxInterpDist,
                rtol=rtol)
def getDeltaLinearCombinationKernel(kSize, imSize, spOrder):
    """Return a LinearCombinationKernel of delta functions

    @param kSize: kernel size (scalar; height = width)
    @param x, y imSize: image size
    """
    kernelList = afwMath.KernelList()
    for ctrX in range(kSize):
        for ctrY in range(kSize):
            kernelList.append(afwMath.DeltaFunctionKernel(kSize, kSize, afwGeom.Point2I(ctrX, ctrY)))
            
    polyFunc = afwMath.PolynomialFunction2D(spOrder)
    kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc)
    
    spParams = getSpatialParameters(len(kernelList), polyFunc)
    kernel.setSpatialParameters(spParams);
    return kernel
Beispiel #13
0
 def testZeroWidthKernel(self):
     """Convolution by a 0x0 kernel should raise an exception.
     
     The only way to produce a 0x0 kernel is to use the default constructor
     (which exists only to support persistence; it does not produce a useful kernel).
     """
     kernelList = [
         afwMath.FixedKernel(),
         afwMath.AnalyticKernel(),
         afwMath.SeparableKernel(),
         #            afwMath.DeltaFunctionKernel(),  # DeltaFunctionKernel has no default constructor
         afwMath.LinearCombinationKernel(),
     ]
     convolutionControl = afwMath.ConvolutionControl()
     for kernel in kernelList:
         self.assertRaises(Exception, afwMath.convolve, self.cnvMaskedImage,
                           self.maskedImage, kernel, convolutionControl)
    def testBad(self):
        ti = afwImage.MaskedImageF(geom.Extent2I(100, 100))
        ti.getVariance().set(0.1)
        ti[50, 50, afwImage.LOCAL] = (1., 0x0, 1.)
        sKernel = self.makeSpatialKernel(2)
        si = afwImage.MaskedImageF(ti.getDimensions())
        convolutionControl = afwMath.ConvolutionControl()
        convolutionControl.setDoNormalize(True)
        afwMath.convolve(si, ti, sKernel, convolutionControl)

        bbox = geom.Box2I(geom.Point2I(25, 25), geom.Point2I(75, 75))
        si = afwImage.MaskedImageF(si, bbox, origin=afwImage.LOCAL)
        ti = afwImage.MaskedImageF(ti, bbox, origin=afwImage.LOCAL)
        kc = ipDiffim.KernelCandidateF(50., 50., ti, si, self.ps)

        badGaussian = afwMath.GaussianFunction2D(1., 1., 0.)
        badKernel = afwMath.AnalyticKernel(self.ksize, self.ksize, badGaussian)
        basisList = []
        basisList.append(badKernel)
        badSpatialKernelFunction = afwMath.PolynomialFunction2D(0)
        badSpatialKernel = afwMath.LinearCombinationKernel(
            basisList, badSpatialKernelFunction)
        badSpatialKernel.setSpatialParameters([[
            1,
        ]])

        sBg = afwMath.PolynomialFunction2D(1)
        bgCoeffs = [10., 10., 10.]
        sBg.setParameters(bgCoeffs)

        # must be initialized
        bskv = ipDiffim.BuildSingleKernelVisitorF(self.kList, self.ps)
        bskv.processCandidate(kc)
        self.assertEqual(kc.isInitialized(), True)

        askv = ipDiffim.AssessSpatialKernelVisitorF(badSpatialKernel, sBg,
                                                    self.ps)
        askv.processCandidate(kc)

        self.assertEqual(askv.getNProcessed(), 1)
        self.assertEqual(askv.getNRejected(), 1)
        self.assertEqual(kc.getStatus(), afwMath.SpatialCellCandidate.BAD)
Beispiel #15
0
    def testSpatiallyVaryingGaussianLinerCombination(self):
        """Test convolution with a spatially varying LinearCombinationKernel of two Gaussian basis kernels.
        """
        kWidth = 5
        kHeight = 5

        # create spatial model
        for nBasisKernels in (3, 4):
            # at 3 the kernel will not be refactored, at 4 it will be
            sFunc = 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, -0.01 / self.width, -0.01 / self.height),
                (0.0, 0.01 / self.width, 0.0 / self.height),
                (0.0, 0.0 / self.width, 0.01 / self.height),
                (0.5, 0.005 / self.width, -0.005 / self.height),
            )[:nBasisKernels]

            gaussParamsList = (
                (1.5, 1.5, 0.0),
                (2.5, 1.5, 0.0),
                (2.5, 1.5, math.pi / 2.0),
                (2.5, 2.5, 0.0),
            )[:nBasisKernels]
            basisKernelList = makeGaussianKernelList(kWidth, kHeight,
                                                     gaussParamsList)
            kernel = afwMath.LinearCombinationKernel(basisKernelList, 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="%s with %d basis kernels convolved using %s" %
                    ("Spatially Varying Gaussian Analytic Kernel",
                     nBasisKernels, methodStr),
                    maxInterpDist=maxInterpDist,
                    rtol=rtol)
Beispiel #16
0
 def testCast(self):
     instances = []
     kVec = makeGaussianKernelList(9, 9, [(2.0, 2.0, 0.0)])
     kParams = [0.0] * len(kVec)
     instances.append(afwMath.LinearCombinationKernel(kVec, kParams))
     instances.append(
         afwMath.AnalyticKernel(7, 7,
                                afwMath.GaussianFunction2D(2.0, 2.0, 0.0)))
     instances.append(
         afwMath.DeltaFunctionKernel(5, 5, afwGeom.Point2I(1, 1)))
     instances.append(
         afwMath.FixedKernel(afwImage.ImageD(afwGeom.Extent2I(7, 7))))
     instances.append(
         afwMath.SeparableKernel(3, 3, afwMath.PolynomialFunction1D(0),
                                 afwMath.PolynomialFunction1D(0)))
     for instance in instances:
         Class = type(instance)
         base = instance.clone()
         self.assertEqual(type(base), afwMath.Kernel)
         derived = Class.cast(base)
         self.assertEqual(type(derived), Class)
Beispiel #17
0
    def testComputeImageRaise(self):
        """Test Kernel.computeImage raises OverflowException iff doNormalize True and kernel sum exactly 0
        """
        kWidth = 4
        kHeight = 3

        polyFunc1 = afwMath.PolynomialFunction1D(0)
        polyFunc2 = afwMath.PolynomialFunction2D(0)
        analKernel = afwMath.AnalyticKernel(kWidth, kHeight, polyFunc2)
        kImage = afwImage.ImageD(analKernel.getDimensions())
        for coeff in (-1, -1e-99, 0, 1e99, 1):
            analKernel.setKernelParameters([coeff])

            analKernel.computeImage(kImage, False)
            fixedKernel = afwMath.FixedKernel(kImage)

            sepKernel = afwMath.SeparableKernel(
                kWidth, kHeight, polyFunc1, polyFunc1)
            sepKernel.setKernelParameters([coeff, coeff])

            kernelList = []
            kernelList.append(analKernel)
            lcKernel = afwMath.LinearCombinationKernel(kernelList, [1])
            self.assertFalse(lcKernel.isDeltaFunctionBasis())

            doRaise = (coeff == 0)
            self.basicTestComputeImageRaise(
                analKernel, doRaise, "AnalyticKernel")
            self.basicTestComputeImageRaise(
                fixedKernel, doRaise, "FixedKernel")
            self.basicTestComputeImageRaise(
                sepKernel, doRaise, "SeparableKernel")
            self.basicTestComputeImageRaise(
                lcKernel, doRaise, "LinearCombinationKernel")

        lcKernel.setKernelParameters([0])
        self.basicTestComputeImageRaise(
            lcKernel, True, "LinearCombinationKernel")
Beispiel #18
0
    def testLinearCombinationKernel(self):
        """Test LinearCombinationKernel using a set of delta basis functions
        """
        kWidth = 3
        kHeight = 2

        # create list of kernels
        basisImArrList = []
        kVec = []
        for row in range(kHeight):
            for col in range(kWidth):
                kernel = afwMath.DeltaFunctionKernel(
                    kWidth, kHeight, lsst.geom.Point2I(col, row))
                basisImage = afwImage.ImageD(kernel.getDimensions())
                kernel.computeImage(basisImage, True)
                basisImArrList.append(basisImage.getArray().transpose().copy())
                kVec.append(kernel)

        kParams = [0.0] * len(kVec)
        k = afwMath.LinearCombinationKernel(kVec, kParams)
        for ii in range(len(kVec)):
            kParams = [0.0] * len(kVec)
            kParams[ii] = 1.0
            k.setKernelParameters(kParams)

            with lsst.utils.tests.getTempFilePath(".fits") as filename:
                k.writeFits(filename)
                k2 = afwMath.LinearCombinationKernel.readFits(filename)

            self.kernelCheck(k, k2)

            kIm = afwImage.ImageD(k2.getDimensions())
            k2.computeImage(kIm, True)
            kImArr = kIm.getArray().transpose()
            if not np.allclose(kImArr, basisImArrList[ii]):
                self.fail(
                    f"{k2.__class__.__name__} = {kImArr} != {basisImArrList[ii]} "
                    f"for the {ii}'th basis kernel")
def getGaussianLinearCombinationKernel(kSize, imSize, spOrder):
    """Return a LinearCombinationKernel with 5 bases, each a Gaussian

    @param kSize: kernel size (scalar; height = width)
    @param x, y imSize: image size
    """
    kernelList = afwMath.KernelList()
    for fwhmX, fwhmY, angle in (
        (2.0, 2.0, 0.0),
        (0.5, 4.0, 0.0),
        (0.5, 4.0, math.pi / 4.0),
        (0.5, 4.0, math.pi / 2.0),
        (4.0, 4.0, 0.0),
    ):
        gaussFunc = afwMath.GaussianFunction2D(fwhmX, fwhmY, angle)
        kernelList.append(afwMath.AnalyticKernel(kSize, kSize, gaussFunc))

    polyFunc = afwMath.PolynomialFunction2D(spOrder)
    kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc)
    
    spParams = getSpatialParameters(len(kernelList), polyFunc)
    kernel.setSpatialParameters(spParams);
    return kernel
Beispiel #20
0
    def testSVLinearCombinationKernel(self):
        """Test a spatially varying LinearCombinationKernel
        """
        kWidth = 3
        kHeight = 2

        pol = pexPolicy.Policy()
        additionalData = dafBase.PropertySet()
        loc = dafPersist.LogicalLocation(
            os.path.join(testPath, "data", "kernel6.boost"))
        persistence = dafPersist.Persistence.getPersistence(pol)

        # create image arrays for the basis kernels
        basisImArrList = []
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.1
        imArr[kWidth // 2, :] = 0.9
        basisImArrList.append(imArr)
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.2
        imArr[:, kHeight // 2] = 0.8
        basisImArrList.append(imArr)

        # create a list of basis kernels from the images
        kVec = []
        for basisImArr in basisImArrList:
            basisImage = afwImage.makeImageFromArray(
                basisImArr.transpose().copy())
            kernel = afwMath.FixedKernel(basisImage)
            kVec.append(kernel)

        # create spatially varying linear combination kernel
        spFunc = afwMath.PolynomialFunction2D(1)

        # spatial parameters are a list of entries, one per kernel parameter;
        # each entry is a list of spatial parameters
        sParams = (
            (0.0, 1.0, 0.0),
            (0.0, 0.0, 1.0),
        )

        k = afwMath.LinearCombinationKernel(kVec, spFunc)
        k.setSpatialParameters(sParams)

        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)
        k2 = persistence.unsafeRetrieve("LinearCombinationKernel",
                                        storageList2, additionalData)

        self.kernelCheck(k, k2)

        kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight))
        for colPos, rowPos, coeff0, coeff1 in [
            (0.0, 0.0, 0.0, 0.0),
            (1.0, 0.0, 1.0, 0.0),
            (0.0, 1.0, 0.0, 1.0),
            (1.0, 1.0, 1.0, 1.0),
            (0.5, 0.5, 0.5, 0.5),
        ]:
            k2.computeImage(kImage, False, colPos, rowPos)
            kImArr = kImage.getArray().transpose()
            refKImArr = (basisImArrList[0] * coeff0) + \
                (basisImArrList[1] * coeff1)
            if not np.allclose(kImArr, refKImArr):
                self.fail(
                    "%s = %s != %s at colPos=%s, rowPos=%s" %
                    (k2.__class__.__name__, kImArr, refKImArr, colPos, rowPos))
Beispiel #21
0
def showPsfCandidates(exposure, psfCellSet, psf=None, frame=None, normalize=True, showBadCandidates=True,
                      variance=None, chi=None):
    """Display the PSF candidates.
If psf is provided include PSF model and residuals;  if normalize is true normalize the PSFs (and residuals)
If chi is True, generate a plot of residuals/sqrt(variance), i.e. chi
"""
    if chi is None:
        if variance is not None:        # old name for chi
            chi = variance
    #
    # Show us the ccandidates
    #
    mos = displayUtils.Mosaic()
    #
    candidateCenters = []
    candidateCentersBad = []
    candidateIndex = 0

    for cell in psfCellSet.getCellList():
        for cand in cell.begin(False): # include bad candidates
            cand = algorithmsLib.cast_PsfCandidateF(cand)

            rchi2 = cand.getChi2()
            if rchi2 > 1e100:
                rchi2 = numpy.nan

            if not showBadCandidates and cand.isBad():
                continue

            if psf:
                im_resid = displayUtils.Mosaic(gutter=0, background=-5, mode="x")

                try:
                    im = cand.getMaskedImage() # copy of this object's image
                    xc, yc = cand.getXCenter(), cand.getYCenter()

                    margin = 0 if True else 5
                    w, h = im.getDimensions()
                    bbox = afwGeom.BoxI(afwGeom.PointI(margin, margin), im.getDimensions())

                    if margin > 0:
                        bim = im.Factory(w + 2*margin, h + 2*margin)

                        stdev = numpy.sqrt(afwMath.makeStatistics(im.getVariance(), afwMath.MEAN).getValue())
                        afwMath.randomGaussianImage(bim.getImage(), afwMath.Random())
                        bim *= stdev
                        var = bim.getVariance(); var.set(stdev**2); del var

                        sbim = im.Factory(bim, bbox)
                        sbim <<= im
                        del sbim
                        im = bim
                        xc += margin; yc += margin

                    im = im.Factory(im, True)
                    im.setXY0(cand.getMaskedImage().getXY0())
                except:
                    continue

                if not variance:
                    im_resid.append(im.Factory(im, True))

                # residuals using spatial model
                chi2 = algorithmsLib.subtractPsf(psf, im, xc, yc)
                
                resid = im
                if variance:
                    resid = resid.getImage()
                    var = im.getVariance()
                    var = var.Factory(var, True)
                    numpy.sqrt(var.getArray(), var.getArray()) # inplace sqrt
                    resid /= var
                    
                im_resid.append(resid)

                # Fit the PSF components directly to the data (i.e. ignoring the spatial model)
                im = cand.getMaskedImage()

                im = im.Factory(im, True)
                im.setXY0(cand.getMaskedImage().getXY0())

                noSpatialKernel = afwMath.cast_LinearCombinationKernel(psf.getKernel())
                candCenter = afwGeom.PointD(cand.getXCenter(), cand.getYCenter())
                fit = algorithmsLib.fitKernelParamsToImage(noSpatialKernel, im, candCenter)
                params = fit[0]
                kernels = afwMath.KernelList(fit[1])
                outputKernel = afwMath.LinearCombinationKernel(kernels, params)

                outImage = afwImage.ImageD(outputKernel.getDimensions())
                outputKernel.computeImage(outImage, False)

                im -= outImage.convertF()
                resid = im

                if margin > 0:
                    bim = im.Factory(w + 2*margin, h + 2*margin)
                    afwMath.randomGaussianImage(bim.getImage(), afwMath.Random())
                    bim *= stdev

                    sbim = im.Factory(bim, bbox)
                    sbim <<= resid
                    del sbim
                    resid = bim

                if variance:
                    resid = resid.getImage()
                    resid /= var
                    
                im_resid.append(resid)

                im = im_resid.makeMosaic()
            else:
                im = cand.getMaskedImage()

            if normalize:
                im /= afwMath.makeStatistics(im, afwMath.MAX).getValue()

            objId = splitId(cand.getSource().getId(), True)["objId"]
            if psf:
                lab = "%d chi^2 %.1f" % (objId, rchi2)
                ctype = ds9.RED if cand.isBad() else ds9.GREEN
            else:
                lab = "%d flux %8.3g" % (objId, cand.getSource().getPsfFlux())
                ctype = ds9.GREEN

            mos.append(im, lab, ctype)

            if False and numpy.isnan(rchi2):
                ds9.mtv(cand.getMaskedImage().getImage(), title="candidate", frame=1)
                print "amp",  cand.getAmplitude()

            im = cand.getMaskedImage()
            center = (candidateIndex, xc - im.getX0(), yc - im.getY0())
            candidateIndex += 1
            if cand.isBad():
                candidateCentersBad.append(center)
            else:
                candidateCenters.append(center)

    if variance:
        title = "chi(Psf fit)"
    else:
        title = "Stars & residuals"
    mosaicImage = mos.makeMosaic(frame=frame, title=title)

    with ds9.Buffering():
        for centers, color in ((candidateCenters, ds9.GREEN), (candidateCentersBad, ds9.RED)):
            for cen in centers:
                bbox = mos.getBBox(cen[0])
                ds9.dot("+", cen[1] + bbox.getMinX(), cen[2] + bbox.getMinY(), frame=frame, ctype=color)

    return mosaicImage
Beispiel #22
0
def showPsfCandidates(exposure, psfCellSet, psf=None, display=None, normalize=True, showBadCandidates=True,
                      fitBasisComponents=False, variance=None, chi=None):
    """Display the PSF candidates.

    If psf is provided include PSF model and residuals;  if normalize is true normalize the PSFs
    (and residuals)

    If chi is True, generate a plot of residuals/sqrt(variance), i.e. chi

    If fitBasisComponents is true, also find the best linear combination of the PSF's components
    (if they exist)
    """
    if not display:
        display = afwDisplay.Display()

    if chi is None:
        if variance is not None:        # old name for chi
            chi = variance
    #
    # Show us the ccandidates
    #
    mos = displayUtils.Mosaic()
    #
    candidateCenters = []
    candidateCentersBad = []
    candidateIndex = 0

    for cell in psfCellSet.getCellList():
        for cand in cell.begin(False):  # include bad candidates
            rchi2 = cand.getChi2()
            if rchi2 > 1e100:
                rchi2 = numpy.nan

            if not showBadCandidates and cand.isBad():
                continue

            if psf:
                im_resid = displayUtils.Mosaic(gutter=0, background=-5, mode="x")

                try:
                    im = cand.getMaskedImage()  # copy of this object's image
                    xc, yc = cand.getXCenter(), cand.getYCenter()

                    margin = 0 if True else 5
                    w, h = im.getDimensions()
                    bbox = lsst.geom.BoxI(lsst.geom.PointI(margin, margin), im.getDimensions())

                    if margin > 0:
                        bim = im.Factory(w + 2*margin, h + 2*margin)

                        stdev = numpy.sqrt(afwMath.makeStatistics(im.getVariance(), afwMath.MEAN).getValue())
                        afwMath.randomGaussianImage(bim.getImage(), afwMath.Random())
                        bim.getVariance().set(stdev**2)

                        bim.assign(im, bbox)
                        im = bim
                        xc += margin
                        yc += margin

                    im = im.Factory(im, True)
                    im.setXY0(cand.getMaskedImage().getXY0())
                except Exception:
                    continue

                if not variance:
                    im_resid.append(im.Factory(im, True))

                if True:                # tweak up centroids
                    mi = im
                    psfIm = mi.getImage()
                    config = measBase.SingleFrameMeasurementTask.ConfigClass()
                    config.slots.centroid = "base_SdssCentroid"

                    schema = afwTable.SourceTable.makeMinimalSchema()
                    measureSources = measBase.SingleFrameMeasurementTask(schema, config=config)
                    catalog = afwTable.SourceCatalog(schema)

                    extra = 10          # enough margin to run the sdss centroider
                    miBig = mi.Factory(im.getWidth() + 2*extra, im.getHeight() + 2*extra)
                    miBig[extra:-extra, extra:-extra, afwImage.LOCAL] = mi
                    miBig.setXY0(mi.getX0() - extra, mi.getY0() - extra)
                    mi = miBig
                    del miBig

                    exp = afwImage.makeExposure(mi)
                    exp.setPsf(psf)

                    footprintSet = afwDet.FootprintSet(mi,
                                                       afwDet.Threshold(0.5*numpy.max(psfIm.getArray())),
                                                       "DETECTED")
                    footprintSet.makeSources(catalog)

                    if len(catalog) == 0:
                        raise RuntimeError("Failed to detect any objects")

                    measureSources.run(catalog, exp)
                    if len(catalog) == 1:
                        source = catalog[0]
                    else:               # more than one source; find the once closest to (xc, yc)
                        dmin = None  # an invalid value to catch logic errors
                        for i, s in enumerate(catalog):
                            d = numpy.hypot(xc - s.getX(), yc - s.getY())
                            if i == 0 or d < dmin:
                                source, dmin = s, d
                    xc, yc = source.getCentroid()

                # residuals using spatial model
                try:
                    subtractPsf(psf, im, xc, yc)
                except Exception:
                    continue

                resid = im
                if variance:
                    resid = resid.getImage()
                    var = im.getVariance()
                    var = var.Factory(var, True)
                    numpy.sqrt(var.getArray(), var.getArray())  # inplace sqrt
                    resid /= var

                im_resid.append(resid)

                # Fit the PSF components directly to the data (i.e. ignoring the spatial model)
                if fitBasisComponents:
                    im = cand.getMaskedImage()

                    im = im.Factory(im, True)
                    im.setXY0(cand.getMaskedImage().getXY0())

                    try:
                        noSpatialKernel = psf.getKernel()
                    except Exception:
                        noSpatialKernel = None

                    if noSpatialKernel:
                        candCenter = lsst.geom.PointD(cand.getXCenter(), cand.getYCenter())
                        fit = fitKernelParamsToImage(noSpatialKernel, im, candCenter)
                        params = fit[0]
                        kernels = afwMath.KernelList(fit[1])
                        outputKernel = afwMath.LinearCombinationKernel(kernels, params)

                        outImage = afwImage.ImageD(outputKernel.getDimensions())
                        outputKernel.computeImage(outImage, False)

                        im -= outImage.convertF()
                        resid = im

                        if margin > 0:
                            bim = im.Factory(w + 2*margin, h + 2*margin)
                            afwMath.randomGaussianImage(bim.getImage(), afwMath.Random())
                            bim *= stdev

                            bim.assign(resid, bbox)
                            resid = bim

                        if variance:
                            resid = resid.getImage()
                            resid /= var

                        im_resid.append(resid)

                im = im_resid.makeMosaic()
            else:
                im = cand.getMaskedImage()

            if normalize:
                im /= afwMath.makeStatistics(im, afwMath.MAX).getValue()

            objId = splitId(cand.getSource().getId(), True)["objId"]
            if psf:
                lab = "%d chi^2 %.1f" % (objId, rchi2)
                ctype = afwDisplay.RED if cand.isBad() else afwDisplay.GREEN
            else:
                lab = "%d flux %8.3g" % (objId, cand.getSource().getPsfInstFlux())
                ctype = afwDisplay.GREEN

            mos.append(im, lab, ctype)

            if False and numpy.isnan(rchi2):
                display.mtv(cand.getMaskedImage().getImage(), title="showPsfCandidates: candidate")
                print("amp", cand.getAmplitude())

            im = cand.getMaskedImage()
            center = (candidateIndex, xc - im.getX0(), yc - im.getY0())
            candidateIndex += 1
            if cand.isBad():
                candidateCentersBad.append(center)
            else:
                candidateCenters.append(center)

    if variance:
        title = "chi(Psf fit)"
    else:
        title = "Stars & residuals"
    mosaicImage = mos.makeMosaic(display=display, title=title)

    with display.Buffering():
        for centers, color in ((candidateCenters, afwDisplay.GREEN), (candidateCentersBad, afwDisplay.RED)):
            for cen in centers:
                bbox = mos.getBBox(cen[0])
                display.dot("+", cen[1] + bbox.getMinX(), cen[2] + bbox.getMinY(), ctype=color)

    return mosaicImage
    def setUp(self):

        self.schema = afwTable.SourceTable.makeMinimalSchema()
        config = measBase.SingleFrameMeasurementConfig()
        config.algorithms.names = [
            "base_PixelFlags",
            "base_SdssCentroid",
            "base_GaussianFlux",
            "base_SdssShape",
            "base_CircularApertureFlux",
            "base_PsfFlux",
        ]
        config.algorithms["base_CircularApertureFlux"].radii = [3.0]
        config.slots.centroid = "base_SdssCentroid"
        config.slots.psfFlux = "base_PsfFlux"
        config.slots.apFlux = "base_CircularApertureFlux_3_0"
        config.slots.modelFlux = None
        config.slots.instFlux = None
        config.slots.calibFlux = None
        config.slots.shape = "base_SdssShape"

        self.measureTask = measBase.SingleFrameMeasurementTask(self.schema,
                                                               config=config)

        width, height = 110, 301

        self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height))
        self.mi.set(0)
        sd = 3  # standard deviation of image
        self.mi.getVariance().set(sd * sd)
        self.mi.getMask().addMaskPlane("DETECTED")

        self.FWHM = 5
        self.ksize = 31  # size of desired kernel

        sigma1 = 1.75
        sigma2 = 2 * sigma1

        self.exposure = afwImage.makeExposure(self.mi)
        self.exposure.setPsf(
            measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5 * sigma1, 1,
                                      0.1))
        self.exposure.setDetector(DetectorWrapper().detector)

        #
        # Make a kernel with the exactly correct basis functions.  Useful for debugging
        #
        basisKernelList = []
        for sigma in (sigma1, sigma2):
            basisKernel = afwMath.AnalyticKernel(
                self.ksize, self.ksize,
                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  # 1 => up to linear
        spFunc = afwMath.PolynomialFunction2D(order)

        exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)
        exactKernel.setSpatialParameters([[1.0, 0, 0],
                                          [0.0, 0.5 * 1e-2, 0.2e-2]])
        self.exactPsf = measAlg.PcaPsf(exactKernel)

        rand = afwMath.Random()  # make these tests repeatable by setting seed

        addNoise = True

        if addNoise:
            im = self.mi.getImage()
            afwMath.randomGaussianImage(im, rand)  # N(0, 1)
            im *= sd  # N(0, sd^2)
            del im

        xarr, yarr = [], []

        for x, y in [
            (20, 20),
            (60, 20),
            (30, 35),
            (50, 50),
            (20, 90),
            (70, 160),
            (25, 265),
            (75, 275),
            (85, 30),
            (50, 120),
            (70, 80),
            (60, 210),
            (20, 210),
        ]:
            xarr.append(x)
            yarr.append(y)

        for x, y in zip(xarr, yarr):
            dx = rand.uniform() - 0.5  # random (centered) offsets
            dy = rand.uniform() - 0.5

            k = exactKernel.getSpatialFunction(1)(
                x, y)  # functional variation of Kernel ...
            b = (k * sigma1**2 / ((1 - k) * sigma2**2)
                 )  # ... converted double Gaussian's "b"

            # flux = 80000 - 20*x - 10*(y/float(height))**2
            flux = 80000 * (1 + 0.1 * (rand.uniform() - 0.5))
            I0 = flux * (1 + b) / (2 * np.pi * (sigma1**2 + b * sigma2**2))
            for iy in range(y - self.ksize // 2, y + self.ksize // 2 + 1):
                if iy < 0 or iy >= self.mi.getHeight():
                    continue

                for ix in range(x - self.ksize // 2, x + self.ksize // 2 + 1):
                    if ix < 0 or ix >= self.mi.getWidth():
                        continue

                    intensity = I0 * psfVal(ix, iy, x + dx, y + dy, sigma1,
                                            sigma2, b)
                    Isample = rand.poisson(
                        intensity) if addNoise else intensity
                    self.mi.getImage().set(
                        ix, iy,
                        self.mi.getImage().get(ix, iy) + Isample)
                    self.mi.getVariance().set(
                        ix, iy,
                        self.mi.getVariance().get(ix, iy) + intensity)
        #
        bbox = afwGeom.BoxI(afwGeom.PointI(0, 0),
                            afwGeom.ExtentI(width, height))
        self.cellSet = afwMath.SpatialCellSet(bbox, 100)

        self.footprintSet = afwDetection.FootprintSet(
            self.mi, afwDetection.Threshold(100), "DETECTED")
        self.catalog = self.measure(self.footprintSet, self.exposure)

        for source in self.catalog:
            try:
                cand = measAlg.makePsfCandidate(source, self.exposure)
                self.cellSet.insertCandidate(cand)

            except Exception as e:
                print(e)
                continue
def convertpsField(infile, filt, trim=True, rcscale=0.001, MAX_ORDER_B=5, LSST_ORDER=4):
    if filt not in filtToHdu:
        print("INVALID FILTER", filt)
        sys.exit(1)

    buff = open(infile, "rb")
    pstruct = fits.getdata(buff, ext=filtToHdu[filt])

    spaParList = [[]]*len(pstruct)
    kernelList = []
    for i in range(len(pstruct)):
        nrow_b = pstruct[i][0]  # ny
        ncol_b = pstruct[i][1]  # nx
        cmat = pstruct[i][2].reshape((MAX_ORDER_B, MAX_ORDER_B))
        krow = pstruct[i][4]  # RNROW
        kcol = pstruct[i][5]  # RNCOL
        # This is *not* transposed
        karr = pstruct[i][7].reshape((krow, kcol)).astype(num.float64)

        if trim:
            karr = karr[10:41, 10:41]

        kim = afwImage.ImageD(karr)
        kern = afwMath.FixedKernel(kim)
        kernelList.append(kern)

        # NOTES:

        # Afw has the polynomial terms like:
        #
        # * f(x,y) =   c0                                                      (0th order)
        # *          + c1 x    + c2 y                                          (1st order)
        # *          + c3 x^2  + c4 x y    + c5 y^2                            (2nd order)
        # *          + c6 x^3  + c7 x^2 y  + c8 x y^2    + c9 y^3              (3rd order)
        # *          + c10 x^4 + c11 x^3 y + c12 x^2 y^2 + c13 x y^3 + c14 y^4 (4th order)
        #
        # So, ordered: x^0,y^0 x^1,y^0 x^0,y^1 x^2,y^0 x^1,y^1 x^0,y^2

        # SDSS has the terms ordered like, after reshape():
        #
        # x^0,y^0 x^0,y^1 x^0,y^2
        # x^1,y^0 x^1,y^1 x^1,y^2
        # x^2,y^0 x^2,y^1 x^2,y^2
        #
        # So, it technically goes up to fourth order in LSST-speak.  OK, that is the trick.
        #
        # Mapping:
        # cmat[0][0] = c0  x^0y^0
        # cmat[1][0] = c2  x^0y^1
        # cmat[2][0] = c5  x^0y^2
        # cmat[0][1] = c1  x^1y^0
        # cmat[1][1] = c4  x^1y^1
        # cmat[2][1] = c8  x^1y^2
        # cmat[0][2] = c3  x^2y^0
        # cmat[1][2] = c7  x^2y^1
        # cmat[2][2] = c12 x^2y^2
        #
        # This is quantified in skMatrixPos2TriSeqPosT

        spaParamsTri = num.zeros(MAX_ORDER_B * MAX_ORDER_B)
        for k in range(nrow_b * ncol_b):
            row = k % nrow_b
            col = k // nrow_b
            coeff = cmat[row, col]
            scale = pow(rcscale, row) * pow(rcscale, col)
            scaledCoeff = coeff * scale

            # Was originally written like this, but the SDSS code
            # takes inputs as y,x instead of x,y meaning it was
            # originally transposed
            #
            # idx         = row * MAX_ORDER_B + col

            idx = col * MAX_ORDER_B + row
            spaParamsTri[skMatrixPos2TriSeqPosT[idx]] = scaledCoeff

            # print "%d y=%d x=%d %10.3e %2d %2d %10.3e" % \
            # (i, row, col, cmat[row,col], idx, skMatrixPos2TriSeqPosT[idx], scaledCoeff)

        # print spaParamsTri
        nTerms = (LSST_ORDER + 1) * (LSST_ORDER + 2) // 2
        spaParamsTri = spaParamsTri[:nTerms]
        spaParList[i] = spaParamsTri

    buff.close()
    spaFun = afwMath.PolynomialFunction2D(LSST_ORDER)
    spatialKernel = afwMath.LinearCombinationKernel(kernelList, spaFun)
    spatialKernel.setSpatialParameters(spaParList)
    spatialPsf = measAlg.PcaPsf(spatialKernel)
    return spatialPsf
Beispiel #25
0
    def setUp(self):
        config = SingleFrameMeasurementTask.ConfigClass()
        config.slots.apFlux = 'base_CircularApertureFlux_12_0'
        self.schema = afwTable.SourceTable.makeMinimalSchema()

        self.measureSources = SingleFrameMeasurementTask(self.schema,
                                                         config=config)

        width, height = 110, 301

        self.mi = afwImage.MaskedImageF(geom.ExtentI(width, height))
        self.mi.set(0)
        sd = 3  # standard deviation of image
        self.mi.getVariance().set(sd * sd)
        self.mi.getMask().addMaskPlane("DETECTED")

        self.ksize = 31  # size of desired kernel

        sigma1 = 1.75
        sigma2 = 2 * sigma1

        self.exposure = afwImage.makeExposure(self.mi)
        self.exposure.setPsf(
            measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5 * sigma1, 1,
                                      0.1))
        cdMatrix = np.array([1.0, 0.0, 0.0, 1.0])
        cdMatrix.shape = (2, 2)
        wcs = afwGeom.makeSkyWcs(crpix=geom.PointD(0, 0),
                                 crval=geom.SpherePoint(
                                     0.0, 0.0, geom.degrees),
                                 cdMatrix=cdMatrix)
        self.exposure.setWcs(wcs)

        #
        # Make a kernel with the exactly correct basis functions.
        # Useful for debugging
        #
        basisKernelList = []
        for sigma in (sigma1, sigma2):
            basisKernel = afwMath.AnalyticKernel(
                self.ksize, self.ksize,
                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  # 1 => up to linear
        spFunc = afwMath.PolynomialFunction2D(order)

        exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)
        exactKernel.setSpatialParameters([[1.0, 0, 0],
                                          [0.0, 0.5 * 1e-2, 0.2e-2]])

        rand = afwMath.Random()  # make these tests repeatable by setting seed

        addNoise = True

        if addNoise:
            im = self.mi.getImage()
            afwMath.randomGaussianImage(im, rand)  # N(0, 1)
            im *= sd  # N(0, sd^2)
            del im

        xarr, yarr = [], []

        for x, y in [
            (20, 20),
            (60, 20),
            (30, 35),
            (50, 50),
            (20, 90),
            (70, 160),
            (25, 265),
            (75, 275),
            (85, 30),
            (50, 120),
            (70, 80),
            (60, 210),
            (20, 210),
        ]:
            xarr.append(x)
            yarr.append(y)

        for x, y in zip(xarr, yarr):
            dx = rand.uniform() - 0.5  # random (centered) offsets
            dy = rand.uniform() - 0.5

            k = exactKernel.getSpatialFunction(1)(
                x, y)  # functional variation of Kernel ...
            b = (k * sigma1**2 / ((1 - k) * sigma2**2)
                 )  # ... converted double Gaussian's "b"

            # flux = 80000 - 20*x - 10*(y/float(height))**2
            flux = 80000 * (1 + 0.1 * (rand.uniform() - 0.5))
            I0 = flux * (1 + b) / (2 * np.pi * (sigma1**2 + b * sigma2**2))
            for iy in range(y - self.ksize // 2, y + self.ksize // 2 + 1):
                if iy < 0 or iy >= self.mi.getHeight():
                    continue

                for ix in range(x - self.ksize // 2, x + self.ksize // 2 + 1):
                    if ix < 0 or ix >= self.mi.getWidth():
                        continue

                    II = I0 * psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b)
                    Isample = rand.poisson(II) if addNoise else II
                    self.mi.image[ix, iy, afwImage.LOCAL] += Isample
                    self.mi.variance[ix, iy, afwImage.LOCAL] += II

        bbox = geom.BoxI(geom.PointI(0, 0), geom.ExtentI(width, height))
        self.cellSet = afwMath.SpatialCellSet(bbox, 100)

        self.footprintSet = afwDetection.FootprintSet(
            self.mi, afwDetection.Threshold(100), "DETECTED")

        self.catalog = self.measure(self.footprintSet, self.exposure)

        for source in self.catalog:
            try:
                cand = measAlg.makePsfCandidate(source, self.exposure)
                self.cellSet.insertCandidate(cand)

            except Exception as e:
                print(e)
                continue
def testAutoCorrelation(orderMake, orderFit, inMi=None, display=False):
    config = ipDiffim.ImagePsfMatchTask.ConfigClass()
    config.kernel.name = "AL"
    subconfig = config.kernel.active

    subconfig.fitForBackground = True

    stride = 100

    if inMi == None:
        width = 512
        height = 2048
        inMi = afwImage.MaskedImageF(afwGeom.Extent2I(width, height))
        for j in num.arange(stride // 2, height, stride):
            j = int(j)
            for i in num.arange(stride // 2, width, stride):
                i = int(i)
                inMi.set(i - 1, j - 1, (100., 0x0, 1.))
                inMi.set(i - 1, j + 0, (100., 0x0, 1.))
                inMi.set(i - 1, j + 1, (100., 0x0, 1.))
                inMi.set(i + 0, j - 1, (100., 0x0, 1.))
                inMi.set(i + 0, j + 0, (100., 0x0, 1.))
                inMi.set(i + 0, j + 1, (100., 0x0, 1.))
                inMi.set(i + 1, j - 1, (100., 0x0, 1.))
                inMi.set(i + 1, j + 0, (100., 0x0, 1.))
                inMi.set(i + 1, j + 1, (100., 0x0, 1.))

    addNoise(inMi)

    kSize = subconfig.kernelSize

    basicGaussian1 = afwMath.GaussianFunction2D(2., 2., 0.)
    basicKernel1 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian1)

    basicGaussian2 = afwMath.GaussianFunction2D(5., 3., 0.5 * num.pi)
    basicKernel2 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian2)

    basisList = []
    basisList.append(basicKernel1)
    basisList.append(basicKernel2)

    spatialKernelFunction = afwMath.PolynomialFunction2D(orderMake)
    spatialKernel = afwMath.LinearCombinationKernel(basisList,
                                                    spatialKernelFunction)
    kCoeffs = [[
        1.0 for x in range(1,
                           spatialKernelFunction.getNParameters() + 1)
    ], [
        0.01 * x for x in range(1,
                                spatialKernelFunction.getNParameters() + 1)
    ]]
    spatialKernel.setSpatialParameters(kCoeffs)

    cMi = afwImage.MaskedImageF(inMi.getDimensions())
    afwMath.convolve(cMi, inMi, spatialKernel, True)

    if display:
        ds9.mtv(inMi.getImage(), frame=1)
        ds9.mtv(inMi.getVariance(), frame=2)

        ds9.mtv(cMi.getImage(), frame=3)
        ds9.mtv(cMi.getVariance(), frame=4)

    subconfig.spatialKernelOrder = orderFit
    subconfig.sizeCellX = stride
    subconfig.sizeCellY = stride
    psfmatch = ipDiffim.ImagePsfMatchTask(config=config)
    result = psfmatch.run(inMi, cMi, "subtractMaskedImages")

    differenceMaskedImage = result.subtractedImage
    spatialKernel = result.psfMatchingKernel
    spatialBg = result.backgroundModel
    kernelCellSet = result.kernelCellSet
    makeAutoCorrelation(kernelCellSet, spatialKernel, makePlot=True)
Beispiel #27
0
def testAutoCorrelation(orderMake, orderFit, inMi=None, display=False):
    config = ipDiffim.ImagePsfMatchTask.ConfigClass()
    config.kernel.name = "AL"
    subconfig = config.kernel.active

    subconfig.fitForBackground = True

    stride = 100

    if inMi is None:
        width = 512
        height = 2048
        inMi = afwImage.MaskedImageF(afwGeom.Extent2I(width, height))
        for j in num.arange(stride // 2, height, stride):
            j = int(j)
            for i in num.arange(stride // 2, width, stride):
                i = int(i)
                inMi._set((i - 1, j - 1), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i - 1, j + 0), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i - 1, j + 1), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 0, j - 1), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 0, j + 0), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 0, j + 1), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 1, j - 1), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 1, j + 0), (100., 0x0, 1.), afwImage.LOCAL)
                inMi._set((i + 1, j + 1), (100., 0x0, 1.), afwImage.LOCAL)

    addNoise(inMi)

    kSize = subconfig.kernelSize

    basicGaussian1 = afwMath.GaussianFunction2D(2., 2., 0.)
    basicKernel1 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian1)

    basicGaussian2 = afwMath.GaussianFunction2D(5., 3., 0.5 * num.pi)
    basicKernel2 = afwMath.AnalyticKernel(kSize, kSize, basicGaussian2)

    basisList = []
    basisList.append(basicKernel1)
    basisList.append(basicKernel2)

    spatialKernelFunction = afwMath.PolynomialFunction2D(orderMake)
    spatialKernel = afwMath.LinearCombinationKernel(basisList,
                                                    spatialKernelFunction)
    kCoeffs = [[
        1.0 for x in range(1,
                           spatialKernelFunction.getNParameters() + 1)
    ], [
        0.01 * x for x in range(1,
                                spatialKernelFunction.getNParameters() + 1)
    ]]
    spatialKernel.setSpatialParameters(kCoeffs)

    cMi = afwImage.MaskedImageF(inMi.getDimensions())
    convolutionControl = afwMath.ConvolutionControl()
    convolutionControl.setDoNormalize(True)
    afwMath.convolve(cMi, inMi, spatialKernel, convolutionControl)

    if display:
        afwDisplay.Display(frame=1).mtv(inMi.getImage())
        afwDisplay.Display(frame=2).mtv(inMi.getVariance())

        afwDisplay.Display(frame=3).mtv(cMi.getImage())
        afwDisplay.Display(frame=4).mtv(cMi.getVariance())

    subconfig.spatialKernelOrder = orderFit
    subconfig.sizeCellX = stride
    subconfig.sizeCellY = stride
    psfmatch = ipDiffim.ImagePsfMatchTask(config=config)
    candList = psfmatch.makeCandidateList(afwImage.ExposureF(inMi),
                                          afwImage.ExposureF(cMi), kSize)
    result = psfmatch.subtractMaskedImages(inMi, cMi, candList)

    spatialKernel = result.psfMatchingKernel
    kernelCellSet = result.kernelCellSet
    makeAutoCorrelation(kernelCellSet, spatialKernel, makePlot=True)
Beispiel #28
0
    def setUp(self):
        width, height = 110, 301

        self.mi = afwImage.MaskedImageF(afwGeom.ExtentI(width, height))
        self.mi.set(0)
        sd = 3                          # standard deviation of image
        self.mi.getVariance().set(sd*sd)
        self.mi.getMask().addMaskPlane("DETECTED")

        self.FWHM = 5
        self.ksize = 31                      # size of desired kernel

        sigma1 = 1.75
        sigma2 = 2*sigma1

        self.exposure = afwImage.makeExposure(self.mi)
        self.exposure.setPsf(measAlg.DoubleGaussianPsf(self.ksize, self.ksize,
                                                    1.5*sigma1, 1, 0.1))
        crval = afwCoord.makeCoord(afwCoord.ICRS, 0.0*afwGeom.degrees, 0.0*afwGeom.degrees)
        wcs = afwImage.makeWcs(crval, afwGeom.PointD(0, 0), 1.0, 0, 0, 1.0)
        self.exposure.setWcs(wcs)

        ccd = cameraGeom.Ccd(cameraGeom.Id(1))
        ccd.addAmp(cameraGeom.Amp(cameraGeom.Id(0),
                                  afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()),
                                  afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(0,0)),
                                  afwGeom.BoxI(afwGeom.PointI(0,0), self.exposure.getDimensions()),
                                  cameraGeom.ElectronicParams(1.0, 100.0, 65535)))
        self.exposure.setDetector(ccd)
        self.exposure.getDetector().setDistortion(None)        
        #
        # Make a kernel with the exactly correct basis functions.  Useful for debugging
        #
        basisKernelList = afwMath.KernelList()
        for sigma in (sigma1, sigma2):
            basisKernel = afwMath.AnalyticKernel(self.ksize, self.ksize,
                                                 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                                # 1 => up to linear
        spFunc = afwMath.PolynomialFunction2D(order)

        exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)
        exactKernel.setSpatialParameters([[1.0, 0,          0],
                                          [0.0, 0.5*1e-2, 0.2e-2]])

        rand = afwMath.Random()               # make these tests repeatable by setting seed

        addNoise = True

        if addNoise:
            im = self.mi.getImage()
            afwMath.randomGaussianImage(im, rand) # N(0, 1)
            im *= sd                              # N(0, sd^2)
            del im

        xarr, yarr = [], []

        for x, y in [(20, 20), (60, 20), 
                     (30, 35),
                     (50, 50),
                     (20, 90), (70, 160), (25, 265), (75, 275), (85, 30),
                     (50, 120), (70, 80),
                     (60, 210), (20, 210),
                     ]:
            xarr.append(x)
            yarr.append(y)

        for x, y in zip(xarr, yarr):
            dx = rand.uniform() - 0.5   # random (centered) offsets
            dy = rand.uniform() - 0.5

            k = exactKernel.getSpatialFunction(1)(x, y) # functional variation of Kernel ...
            b = (k*sigma1**2/((1 - k)*sigma2**2))       # ... converted double Gaussian's "b"

            #flux = 80000 - 20*x - 10*(y/float(height))**2
            flux = 80000*(1 + 0.1*(rand.uniform() - 0.5))
            I0 = flux*(1 + b)/(2*np.pi*(sigma1**2 + b*sigma2**2))
            for iy in range(y - self.ksize//2, y + self.ksize//2 + 1):
                if iy < 0 or iy >= self.mi.getHeight():
                    continue

                for ix in range(x - self.ksize//2, x + self.ksize//2 + 1):
                    if ix < 0 or ix >= self.mi.getWidth():
                        continue

                    I = I0*psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b)
                    Isample = rand.poisson(I) if addNoise else I
                    self.mi.getImage().set(ix, iy, self.mi.getImage().get(ix, iy) + Isample)
                    self.mi.getVariance().set(ix, iy, self.mi.getVariance().get(ix, iy) + I)
        # 
        bbox = afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(width, height))
        self.cellSet = afwMath.SpatialCellSet(bbox, 100)

        self.footprintSet = afwDetection.FootprintSet(self.mi, afwDetection.Threshold(100), "DETECTED")

        self.catalog = SpatialModelPsfTestCase.measure(self.footprintSet, self.exposure)

        for source in self.catalog:
            try:
                cand = measAlg.makePsfCandidate(source, self.exposure)
                self.cellSet.insertCandidate(cand)

            except Exception, e:
                print e
                continue
Beispiel #29
0
    def testSVLinearCombinationKernelFixed(self):
        """Test a spatially varying LinearCombinationKernel whose bases are FixedKernels"""
        kWidth = 3
        kHeight = 2

        # create image arrays for the basis kernels
        basisImArrList = []
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.1
        imArr[kWidth//2, :] = 0.9
        basisImArrList.append(imArr)
        imArr = np.zeros((kWidth, kHeight), dtype=float)
        imArr += 0.2
        imArr[:, kHeight//2] = 0.8
        basisImArrList.append(imArr)

        # create a list of basis kernels from the images
        basisKernelList = []
        for basisImArr in basisImArrList:
            basisImage = afwImage.makeImageFromArray(
                basisImArr.transpose().copy())
            kernel = afwMath.FixedKernel(basisImage)
            basisKernelList.append(kernel)

        # create spatially varying linear combination kernel
        spFunc = afwMath.PolynomialFunction2D(1)

        # spatial parameters are a list of entries, one per kernel parameter;
        # each entry is a list of spatial parameters
        sParams = (
            (0.0, 1.0, 0.0),
            (0.0, 0.0, 1.0),
        )

        kernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)
        self.assertFalse(kernel.isDeltaFunctionBasis())
        self.basicTests(kernel, 2, nSpatialParams=3)
        kernel.setSpatialParameters(sParams)
        kImage = afwImage.ImageD(lsst.geom.Extent2I(kWidth, kHeight))
        for colPos, rowPos, coeff0, coeff1 in [
            (0.0, 0.0, 0.0, 0.0),
            (1.0, 0.0, 1.0, 0.0),
            (0.0, 1.0, 0.0, 1.0),
            (1.0, 1.0, 1.0, 1.0),
            (0.5, 0.5, 0.5, 0.5),
        ]:
            kernel.computeImage(kImage, False, colPos, rowPos)
            kImArr = kImage.getArray().transpose()
            refKImArr = (basisImArrList[0] * coeff0) + \
                (basisImArrList[1] * coeff1)
            if not np.allclose(kImArr, refKImArr):
                self.fail(f"{kernel.__class__.__name__} = {kImArr} != "
                          f"{refKImArr} at colPos={colPos}, rowPos={rowPos}")

        sParams = (
            (0.1, 1.0, 0.0),
            (0.1, 0.0, 1.0),
        )
        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),
        )
        kernel.setSpatialParameters(newSParams)
        errStr = self.compareKernels(kernel, kernelClone)
        if not errStr:
            self.fail(
                "Clone was modified by changing original's spatial parameters")
Beispiel #30
0
def makeFakeKernelSet(sizeCell=128,
                      nCell=3,
                      deltaFunctionCounts=1.e4,
                      tGaussianWidth=1.0,
                      addNoise=True,
                      bgValue=100.,
                      display=False):
    """Generate test template and science images with sources.

    Parameters
    ----------
    sizeCell : `int`, optional
        Size of the square spatial cells in pixels.
    nCell : `int`, optional
        Number of adjacent spatial cells in both direction in both images.
    deltaFunctionCounts : `float`, optional
        Flux value for the template image sources.
    tGaussianWidth : `float`, optional
        Sigma of the generated Gaussian PSF sources in the template image.
    addNoise : `bool`, optional
        If `True`, Poisson noise is added to both the generated template
        and science images.
    bgValue : `float`, optional
        Background level to be added to the generated science image.
    display : `bool`, optional
        If `True` displays the generated template and science images by
        `lsst.afw.display.Display`.

    Notes
    -----
    - The generated images consist of adjacent ``nCell x nCell`` cells, each
      of pixel size ``sizeCell x sizeCell``.
    - The sources in the science image are generated by convolving the
      template by ``sKernel``. ``sKernel`` is a spatial `LinearCombinationKernel`
      of hard wired kernel bases functions. The linear combination has first
      order polynomial spatial dependence with polynomial parameters from ``fakeCoeffs()``.
    - The template image sources are generated in the center of each spatial
      cell from one pixel, set to `deltaFunctionCounts` counts, then convolved
      by a 2D Gaussian with sigma of `tGaussianWidth` along each axis.
    - The sources are also returned in ``kernelCellSet`` each source is "detected"
      exactly at the center of a cell.

    Returns
    -------
    tMi : `lsst.afw.image.MaskedImage`
        Generated template image.
    sMi : `lsst.afw.image.MaskedImage`
        Generated science image.
    sKernel : `lsst.afw.math.LinearCombinationKernel`
        The spatial kernel used to generate the sources in the science image.
    kernelCellSet : `lsst.afw.math.SpatialCellSet`
        Cell grid of `lsst.afw.math.SpatialCell` instances, containing
        `lsst.ip.diffim.KernelCandidate` instances around all the generated sources
        in the science image.
    configFake : `lsst.ip.diffim.ImagePsfMatchConfig`
        Config instance used in the image generation.
    """
    from . import imagePsfMatch
    configFake = imagePsfMatch.ImagePsfMatchConfig()
    configFake.kernel.name = "AL"
    subconfigFake = configFake.kernel.active
    subconfigFake.alardNGauss = 1
    subconfigFake.alardSigGauss = [
        2.5,
    ]
    subconfigFake.alardDegGauss = [
        2,
    ]
    subconfigFake.sizeCellX = sizeCell
    subconfigFake.sizeCellY = sizeCell
    subconfigFake.spatialKernelOrder = 1
    subconfigFake.spatialModelType = "polynomial"
    subconfigFake.singleKernelClipping = False  # variance is a hack
    subconfigFake.spatialKernelClipping = False  # variance is a hack
    if bgValue > 0.0:
        subconfigFake.fitForBackground = True

    psFake = pexConfig.makePropertySet(subconfigFake)

    basisList = makeKernelBasisList(subconfigFake)
    kSize = subconfigFake.kernelSize

    # This sets the final extent of each convolved delta function
    gaussKernelWidth = sizeCell // 2

    # This sets the scale over which pixels are correlated in the
    # spatial convolution; should be at least as big as the kernel you
    # are trying to fit for
    spatialKernelWidth = kSize

    # Number of bad pixels due to convolutions
    border = (gaussKernelWidth + spatialKernelWidth) // 2

    # Make a fake image with a matrix of delta functions
    totalSize = nCell * sizeCell + 2 * border
    tim = afwImage.ImageF(geom.Extent2I(totalSize, totalSize))
    for x in range(nCell):
        for y in range(nCell):
            tim[x * sizeCell + sizeCell // 2 + border - 1,
                y * sizeCell + sizeCell // 2 + border - 1,
                afwImage.LOCAL] = deltaFunctionCounts

    # Turn this into stars with a narrow width; conserve counts
    gaussFunction = afwMath.GaussianFunction2D(tGaussianWidth, tGaussianWidth)
    gaussKernel = afwMath.AnalyticKernel(gaussKernelWidth, gaussKernelWidth,
                                         gaussFunction)
    cim = afwImage.ImageF(tim.getDimensions())
    convolutionControl = afwMath.ConvolutionControl()
    convolutionControl.setDoNormalize(True)
    afwMath.convolve(cim, tim, gaussKernel, convolutionControl)
    tim = cim

    # Trim off border pixels
    bbox = gaussKernel.shrinkBBox(tim.getBBox(afwImage.LOCAL))
    tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)

    # Now make a science image which is this convolved with some
    # spatial function.  Use input basis list.
    polyFunc = afwMath.PolynomialFunction2D(1)
    kCoeffs = fakeCoeffs()
    nToUse = min(len(kCoeffs), len(basisList))

    # Make the full convolved science image
    sKernel = afwMath.LinearCombinationKernel(basisList[:nToUse], polyFunc)
    sKernel.setSpatialParameters(kCoeffs[:nToUse])
    sim = afwImage.ImageF(tim.getDimensions())
    convolutionControl = afwMath.ConvolutionControl()
    convolutionControl.setDoNormalize(True)
    afwMath.convolve(sim, tim, sKernel, convolutionControl)

    # Get the good subregion
    bbox = sKernel.shrinkBBox(sim.getBBox(afwImage.LOCAL))

    # Add background
    sim += bgValue

    # Watch out for negative values
    tim += 2 * np.abs(np.min(tim.getArray()))

    # Add noise?
    if addNoise:
        sim = makePoissonNoiseImage(sim)
        tim = makePoissonNoiseImage(tim)

    # And turn into MaskedImages
    sim = afwImage.ImageF(sim, bbox, afwImage.LOCAL)
    svar = afwImage.ImageF(sim, True)
    smask = afwImage.Mask(sim.getDimensions())
    smask.set(0x0)
    sMi = afwImage.MaskedImageF(sim, smask, svar)

    tim = afwImage.ImageF(tim, bbox, afwImage.LOCAL)
    tvar = afwImage.ImageF(tim, True)
    tmask = afwImage.Mask(tim.getDimensions())
    tmask.set(0x0)
    tMi = afwImage.MaskedImageF(tim, tmask, tvar)

    if display:
        import lsst.afw.display as afwDisplay
        afwDisplay.Display(frame=1).mtv(tMi)
        afwDisplay.Display(frame=2).mtv(sMi)

    # Finally, make a kernelSet from these 2 images
    kernelCellSet = afwMath.SpatialCellSet(
        geom.Box2I(geom.Point2I(0, 0),
                   geom.Extent2I(sizeCell * nCell, sizeCell * nCell)),
        sizeCell, sizeCell)
    stampHalfWidth = 2 * kSize
    for x in range(nCell):
        for y in range(nCell):
            xCoord = x * sizeCell + sizeCell // 2
            yCoord = y * sizeCell + sizeCell // 2
            p0 = geom.Point2I(xCoord - stampHalfWidth, yCoord - stampHalfWidth)
            p1 = geom.Point2I(xCoord + stampHalfWidth, yCoord + stampHalfWidth)
            bbox = geom.Box2I(p0, p1)
            tsi = afwImage.MaskedImageF(tMi, bbox, origin=afwImage.LOCAL)
            ssi = afwImage.MaskedImageF(sMi, bbox, origin=afwImage.LOCAL)

            kc = diffimLib.makeKernelCandidate(xCoord, yCoord, tsi, ssi,
                                               psFake)
            kernelCellSet.insertCandidate(kc)

    tMi.setXY0(0, 0)
    sMi.setXY0(0, 0)
    return tMi, sMi, sKernel, kernelCellSet, configFake