Coverage for tests/test_kernelPca.py: 12%
170 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-29 03:45 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-29 03:45 -0700
1import unittest
3import numpy as np
5import lsst.utils.tests
6import lsst.afw.image as afwImage
7import lsst.afw.math as afwMath
8import lsst.geom as geom
9import lsst.ip.diffim as ipDiffim
10import lsst.utils.logging as logUtils
11import lsst.pex.config as pexConfig
13logUtils.trace_set_at("lsst.ip.diffim", 4)
16def makePoissonNoiseImage(image):
17 """Return a Poisson noise image based on image
19 Parameters
20 ----------
21 image : `lsst.afw.image.Image`
22 image; the output image has the same dtype, dimensions, and shape
23 and its expectation value is the value of ``image`` at each pixel
25 Returns
26 -------
27 noiseIm : `lsst.afw.image.Image`
28 Newly constructed image instance, same type as ``image``.
30 Notes
31 -----
32 - Warning: This uses an undocumented numpy API (the documented API
33 uses a single float expectation value instead of an array).
35 - Uses numpy.random; you may wish to call numpy.random.seed first.
36 """
37 import numpy.random as rand
38 imArr = image.array
39 noiseIm = image.Factory(image.getBBox())
40 noiseArr = noiseIm.array
42 intNoiseArr = rand.poisson(np.where(np.isfinite(imArr), imArr, 0.0))
44 noiseArr[:, :] = intNoiseArr.astype(noiseArr.dtype)
45 return noiseIm
48class DiffimTestCases(lsst.utils.tests.TestCase):
50 def setUp(self):
51 self.config = ipDiffim.PsfMatchConfigDF()
53 self.kList = ipDiffim.makeKernelBasisList(self.config)
54 self.ps = pexConfig.makePropertySet(self.config)
55 self.ps["useRegularization"] = False
57 def makeCandidate(self, kSum, x, y, size=51):
58 mi1 = afwImage.MaskedImageF(geom.Extent2I(size, size))
59 mi1.getVariance().set(1.0) # avoid NaNs
60 mi1[size//2, size//2, afwImage.LOCAL] = (1, 0x0, 1)
61 mi2 = afwImage.MaskedImageF(geom.Extent2I(size, size))
62 mi2.getVariance().set(1.0) # avoid NaNs
63 mi2[size//2, size//2, afwImage.LOCAL] = (kSum, 0x0, kSum)
64 kc = ipDiffim.makeKernelCandidate(x, y, mi1, mi2, self.ps)
65 return kc
67 def testGaussian(self, size=51):
68 gaussFunction = afwMath.GaussianFunction2D(2, 3)
69 gaussKernel = afwMath.AnalyticKernel(size, size, gaussFunction)
71 imagePca1 = ipDiffim.KernelPcaD() # mean subtract
72 imagePca2 = ipDiffim.KernelPcaD() # don't mean subtract
73 kpv1 = ipDiffim.KernelPcaVisitorF(imagePca1)
74 kpv2 = ipDiffim.KernelPcaVisitorF(imagePca2)
76 kRefIm = None
78 for i in range(100):
79 kImage1 = afwImage.ImageD(gaussKernel.getDimensions())
80 gaussKernel.computeImage(kImage1, False)
81 kImage1 *= 10000 # to get some decent peak source counts
82 kImage1 += 10 # to get some sky background noise
84 if kRefIm is None:
85 kRefIm = kImage1
87 kImage1 = makePoissonNoiseImage(kImage1)
88 kImage2 = afwImage.ImageD(kImage1, True)
90 imagePca1.addImage(kImage1, 1.0)
91 imagePca2.addImage(kImage2, 1.0)
93 kpv1.subtractMean()
95 imagePca1.analyze()
96 imagePca2.analyze()
98 pcaBasisList1 = kpv1.getEigenKernels()
99 pcaBasisList2 = kpv2.getEigenKernels()
101 eVal1 = imagePca1.getEigenValues()
102 eVal2 = imagePca2.getEigenValues()
104 # First term is far more signficant without mean subtraction
105 self.assertGreater(eVal2[0], eVal1[0])
107 # Last term basically zero with mean subtraction
108 self.assertAlmostEqual(eVal1[-1], 0.0)
110 # Extra image with mean subtraction
111 self.assertEqual(len(pcaBasisList1), (len(eVal1) + 1))
113 # Same shape
114 self.assertEqual(len(pcaBasisList2), len(eVal2))
116 # Mean kernel close to kRefIm
117 kImageM = afwImage.ImageD(gaussKernel.getDimensions())
118 pcaBasisList1[0].computeImage(kImageM, False)
119 for y in range(kRefIm.getHeight()):
120 for x in range(kRefIm.getWidth()):
121 self.assertLess(abs(kRefIm[x, y, afwImage.LOCAL] - kImageM[x, y, afwImage.LOCAL])
122 / kRefIm[x, y, afwImage.LOCAL], 0.2)
124 # First mean-unsubtracted Pca kernel close to kRefIm (normalized to peak of 1.0)
125 kImage0 = afwImage.ImageD(gaussKernel.getDimensions())
126 pcaBasisList2[0].computeImage(kImage0, False)
127 maxVal = afwMath.makeStatistics(kRefIm, afwMath.MAX).getValue(afwMath.MAX)
128 kRefIm /= maxVal
129 for y in range(kRefIm.getHeight()):
130 for x in range(kRefIm.getWidth()):
131 self.assertLess(abs(kRefIm[x, y, afwImage.LOCAL] - kImage0[x, y, afwImage.LOCAL])
132 / kRefIm[x, y, afwImage.LOCAL], 0.2)
134 def testImagePca(self):
135 # Test out the ImagePca behavior
136 kc1 = self.makeCandidate(1, 0.0, 0.0)
137 kc1.build(self.kList)
138 kc2 = self.makeCandidate(2, 0.0, 0.0)
139 kc2.build(self.kList)
140 kc3 = self.makeCandidate(3, 0.0, 0.0)
141 kc3.build(self.kList)
143 imagePca = ipDiffim.KernelPcaD()
144 kpv = ipDiffim.KernelPcaVisitorF(imagePca)
145 kpv.processCandidate(kc1)
146 kpv.processCandidate(kc2)
147 kpv.processCandidate(kc3)
149 imagePca.analyze()
150 eigenImages = imagePca.getEigenImages()
151 # NOTE : this needs to be changed once ticket #1649 is resolved
152 for i in range(len(eigenImages)):
153 for j in range(i, len(eigenImages)):
154 print(i, j, afwImage.innerProduct(eigenImages[i], eigenImages[j]))
156 def testEigenValues(self):
157 kc1 = self.makeCandidate(1, 0.0, 0.0)
158 kc1.build(self.kList)
160 kc2 = self.makeCandidate(2, 0.0, 0.0)
161 kc2.build(self.kList)
163 kc3 = self.makeCandidate(3, 0.0, 0.0)
164 kc3.build(self.kList)
166 imagePca = ipDiffim.KernelPcaD()
167 kpv = ipDiffim.KernelPcaVisitorF(imagePca)
168 kpv.processCandidate(kc1)
169 kpv.processCandidate(kc2)
170 kpv.processCandidate(kc3)
172 imagePca.analyze()
173 eigenImages = imagePca.getEigenImages()
174 eigenValues = imagePca.getEigenValues()
176 # took in 3 images
177 self.assertEqual(len(eigenImages), 3)
178 self.assertEqual(len(eigenValues), 3)
180 # all the same shape, only 1 eigenvalue
181 self.assertAlmostEqual(eigenValues[0], 1.0)
182 self.assertAlmostEqual(eigenValues[1], 0.0)
183 self.assertAlmostEqual(eigenValues[2], 0.0)
185 def testMeanSubtraction(self):
186 kc1 = self.makeCandidate(1, 0.0, 0.0)
187 kc1.build(self.kList)
189 kc2 = self.makeCandidate(2, 0.0, 0.0)
190 kc2.build(self.kList)
192 kc3 = self.makeCandidate(3, 0.0, 0.0)
193 kc3.build(self.kList)
195 imagePca = ipDiffim.KernelPcaD()
196 kpv = ipDiffim.KernelPcaVisitorF(imagePca)
197 kpv.processCandidate(kc1)
198 kpv.processCandidate(kc2)
199 kpv.processCandidate(kc3)
200 kpv.subtractMean() # subtract it *from* imagePca
202 imagePca.analyze()
203 eigenImages = imagePca.getEigenImages()
204 eigenValues = imagePca.getEigenValues()
206 # took in 3 images
207 self.assertEqual(len(eigenImages), 3)
208 self.assertEqual(len(eigenValues), 3)
210 # all the same shape, mean subtracted, so *no* eigenvalues
211 self.assertAlmostEqual(eigenValues[0], 0.0)
212 self.assertAlmostEqual(eigenValues[1], 0.0)
213 self.assertAlmostEqual(eigenValues[2], 0.0)
215 # finally, since imagePca normalizes by the sum, this should
216 # have central pixel value 1.0 and the rest 0.0
217 imageMean = kpv.returnMean()
218 rows = imageMean.getHeight()
219 cols = imageMean.getWidth()
220 for y in range(rows):
221 for x in range(cols):
222 if x == cols // 2 and y == rows // 2:
223 self.assertAlmostEqual(imageMean[x, y, afwImage.LOCAL], 1.0)
224 else:
225 self.assertAlmostEqual(imageMean[x, y, afwImage.LOCAL], 0.0)
227 def testVisit(self, nCell=3):
228 imagePca = ipDiffim.KernelPcaD()
229 kpv = ipDiffim.makeKernelPcaVisitor(imagePca)
231 sizeCellX = self.ps["sizeCellX"]
232 sizeCellY = self.ps["sizeCellY"]
234 kernelCellSet = afwMath.SpatialCellSet(geom.Box2I(geom.Point2I(0, 0),
235 geom.Extent2I(sizeCellX * nCell,
236 sizeCellY * nCell)),
237 sizeCellX,
238 sizeCellY)
240 for candX in range(nCell):
241 for candY in range(nCell):
242 if candX == nCell // 2 and candY == nCell // 2:
243 kc = self.makeCandidate(100.0,
244 candX * sizeCellX + sizeCellX // 2,
245 candY * sizeCellY + sizeCellY // 2)
246 else:
247 kc = self.makeCandidate(1.0,
248 candX * sizeCellX + sizeCellX // 2,
249 candY * sizeCellY + sizeCellY // 2)
250 kc.build(self.kList)
251 kernelCellSet.insertCandidate(kc)
253 kernelCellSet.visitCandidates(kpv, 1)
254 imagePca.analyze()
255 eigenImages = imagePca.getEigenImages()
256 eigenValues = imagePca.getEigenValues()
258 # took in 3 images
259 self.assertEqual(len(eigenImages), nCell * nCell)
260 self.assertEqual(len(eigenValues), nCell * nCell)
262 # all the same shape, only 1 eigenvalue
263 self.assertAlmostEqual(eigenValues[0], 1.0)
264 self.assertAlmostEqual(eigenValues[1], 0.0)
265 self.assertAlmostEqual(eigenValues[2], 0.0)
267#####
270class TestMemory(lsst.utils.tests.MemoryTestCase):
271 pass
274def setup_module(module):
275 lsst.utils.tests.init()
278if __name__ == "__main__": 278 ↛ 279line 278 didn't jump to line 279, because the condition on line 278 was never true
279 lsst.utils.tests.init()
280 unittest.main()