Coverage for tests/test_footprint2.py: 11%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of afw.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22"""
23Tests for Footprints, and FootprintSets
25Run with:
26 python test_footprint2.py
27or
28 pytest test_footprint2.py
29"""
31import unittest
33import lsst.utils.tests
34import lsst.geom
35import lsst.afw.image as afwImage
36import lsst.afw.geom as afwGeom
37import lsst.afw.detection as afwDetect
38import lsst.afw.display as afwDisplay
40afwDisplay.setDefaultMaskTransparency(75)
41try:
42 type(display)
43except NameError:
44 display = False
47def toString(*args):
48 """toString written in python"""
49 if len(args) == 1:
50 args = args[0]
52 y, x0, x1 = args
53 return f"{y}: {x0}..{x1}"
56def peakFromImage(im, pos):
57 """Function to extract the sort key of peak height. Sort by decreasing peak height."""
58 val = im[pos[0], pos[1], afwImage.LOCAL][0]
59 return -1.0*val
62class Object:
64 def __init__(self, val, spans):
65 self.val = val
66 self.spans = spans
68 def insert(self, im):
69 """Insert self into an image"""
70 for sp in self.spans:
71 y, x0, x1 = sp
72 for x in range(x0, x1 + 1):
73 im[x, y, afwImage.LOCAL] = self.val
75 def __eq__(self, other):
76 for osp, sp in zip(other.getSpans(), self.spans):
77 if osp.toString() != toString(sp):
78 return False
80 return True
83class FootprintSetTestCase(unittest.TestCase):
84 """A test case for FootprintSet"""
86 def setUp(self):
87 self.im = afwImage.ImageU(lsst.geom.Extent2I(12, 8))
88 #
89 # Objects that we should detect
90 #
91 self.objects = []
92 self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])]
93 self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])]
94 self.objects += [Object(20, [(6, 3, 3)])]
96 self.im.set(0) # clear image
97 for obj in self.objects:
98 obj.insert(self.im)
100 def tearDown(self):
101 del self.im
103 def testGC(self):
104 """Check that FootprintSets are automatically garbage collected (when MemoryTestCase runs)"""
106 afwDetect.FootprintSet(afwImage.ImageU(lsst.geom.Extent2I(10, 20)),
107 afwDetect.Threshold(10))
109 def testFootprints(self):
110 """Check that we found the correct number of objects and that they are correct"""
111 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
113 objects = ds.getFootprints()
115 self.assertEqual(len(objects), len(self.objects))
116 for i in range(len(objects)):
117 self.assertEqual(objects[i], self.objects[i])
119 def testFootprints2(self):
120 """Check that we found the correct number of objects using FootprintSet"""
121 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
123 objects = ds.getFootprints()
125 self.assertEqual(len(objects), len(self.objects))
126 for i in range(len(objects)):
127 self.assertEqual(objects[i], self.objects[i])
129 def testFootprintsImageId(self):
130 """Check that we can insert footprints into an Image"""
131 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
132 objects = ds.getFootprints()
134 idImage = afwImage.ImageU(self.im.getDimensions())
135 idImage.set(0)
137 for i, foot in enumerate(objects):
138 foot.spans.setImage(idImage, i + 1)
140 for i in range(len(objects)):
141 for sp in objects[i].getSpans():
142 for x in range(sp.getX0(), sp.getX1() + 1):
143 self.assertEqual(idImage[x, sp.getY(), afwImage.LOCAL], i + 1)
145 def testFootprintSetImageId(self):
146 """Check that we can insert a FootprintSet into an Image, setting relative IDs"""
147 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
148 objects = ds.getFootprints()
150 idImage = ds.insertIntoImage()
151 if display:
152 afwDisplay.Display(frame=2).mtv(idImage, title=self._testMethodName + " image")
154 for i in range(len(objects)):
155 for sp in objects[i].getSpans():
156 for x in range(sp.getX0(), sp.getX1() + 1):
157 self.assertEqual(idImage[x, sp.getY(), afwImage.LOCAL], i + 1)
159 def testFootprintsImage(self):
160 """Check that we can search Images as well as MaskedImages"""
161 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
163 objects = ds.getFootprints()
165 self.assertEqual(len(objects), len(self.objects))
166 for i in range(len(objects)):
167 self.assertEqual(objects[i], self.objects[i])
169 def testGrow2(self):
170 """Grow some more interesting shaped Footprints. Informative with display, but no numerical tests"""
171 # Can't set mask plane as the image is not a masked image.
172 ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
174 idImage = afwImage.ImageU(self.im.getDimensions())
175 idImage.set(0)
177 i = 1
178 for foot in ds.getFootprints()[0:1]:
179 foot.dilate(3, afwGeom.Stencil.MANHATTAN)
180 foot.spans.setImage(idImage, i, doClip=True)
181 i += 1
183 if display:
184 afwDisplay.Display(frame=1).mtv(idImage, title=self._testMethodName + " image")
186 def testGrow(self):
187 """Grow footprints using the FootprintSet constructor"""
188 fs = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
189 self.assertEqual(len(fs.getFootprints()), len(self.objects))
190 for isotropic in (True, False, afwDetect.FootprintControl(True),):
191 grown = afwDetect.FootprintSet(fs, 1, isotropic)
192 self.assertEqual(len(fs.getFootprints()), len(self.objects))
194 self.assertGreater(len(grown.getFootprints()), 0)
195 self.assertLessEqual(len(grown.getFootprints()),
196 len(fs.getFootprints()))
198 def testFootprintControl(self):
199 """Test the FootprintControl constructor"""
200 fctrl = afwDetect.FootprintControl()
201 self.assertFalse(fctrl.isCircular()[0]) # not set
202 self.assertFalse(fctrl.isIsotropic()[0]) # not set
204 fctrl.growIsotropic(False)
205 self.assertTrue(fctrl.isCircular()[0])
206 self.assertTrue(fctrl.isIsotropic()[0])
207 self.assertTrue(fctrl.isCircular()[1])
208 self.assertFalse(fctrl.isIsotropic()[1])
210 fctrl = afwDetect.FootprintControl()
211 fctrl.growLeft(False)
212 self.assertTrue(fctrl.isLeft()[0]) # it's now set
213 self.assertFalse(fctrl.isLeft()[1]) # ... but False
215 fctrl = afwDetect.FootprintControl(True, False, False, False)
216 self.assertTrue(fctrl.isLeft()[0])
217 self.assertTrue(fctrl.isRight()[0])
218 self.assertTrue(fctrl.isUp()[0])
219 self.assertTrue(fctrl.isDown()[0])
221 self.assertTrue(fctrl.isLeft()[1])
222 self.assertFalse(fctrl.isRight()[1])
224 def testGrowCircular(self):
225 """Grow footprints in all 4 directions using the FootprintSet/FootprintControl constructor """
226 im = afwImage.MaskedImageF(11, 11)
227 im[5, 5, afwImage.LOCAL] = (10, 0x0, 0.0)
228 fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10))
229 self.assertEqual(len(fs.getFootprints()), 1)
231 radius = 3 # How much to grow by
232 for fctrl in (afwDetect.FootprintControl(),
233 afwDetect.FootprintControl(True),
234 afwDetect.FootprintControl(True, True),
235 ):
236 grown = afwDetect.FootprintSet(fs, radius, fctrl)
237 afwDetect.setMaskFromFootprintList(
238 im.getMask(), grown.getFootprints(), 0x10)
240 if display:
241 afwDisplay.Display(frame=3).mtv(im, title=self._testMethodName + " image")
243 foot = grown.getFootprints()[0]
245 if not fctrl.isCircular()[0]:
246 self.assertEqual(foot.getArea(), 1)
247 elif fctrl.isCircular()[0]:
248 assert radius == 3
249 if fctrl.isIsotropic()[1]:
250 self.assertEqual(foot.getArea(), 29)
251 else:
252 self.assertEqual(foot.getArea(), 25)
254 def testGrowLRUD(self):
255 """Grow footprints in various directions using the FootprintSet/FootprintControl constructor """
256 im = afwImage.MaskedImageF(11, 11)
257 x0, y0, ny = 5, 5, 3
258 for y in range(y0 - ny//2, y0 + ny//2 + 1):
259 im[x0, y, afwImage.LOCAL] = (10, 0x0, 0.0)
260 fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10))
261 self.assertEqual(len(fs.getFootprints()), 1)
263 ngrow = 2 # How much to grow by
264 #
265 # Test growing to the left and/or right
266 #
267 for fctrl in (
268 afwDetect.FootprintControl(False, True, False, False),
269 afwDetect.FootprintControl(True, False, False, False),
270 afwDetect.FootprintControl(True, True, False, False),
271 ):
272 fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10))
273 grown = afwDetect.FootprintSet(fs, ngrow, fctrl)
274 im.getMask().set(0)
275 afwDetect.setMaskFromFootprintList(
276 im.getMask(), grown.getFootprints(), 0x10)
278 if display:
279 afwDisplay.Display(frame=3).mtv(im, title=self._testMethodName + " image")
281 foot = grown.getFootprints()[0]
282 nextra = 0
283 if fctrl.isLeft()[1]:
284 nextra += ngrow
285 for y in range(y0 - ny//2, y0 + ny//2 + 1):
286 self.assertNotEqual(im.getMask()[x0 - 1, y, afwImage.LOCAL], 0)
288 if fctrl.isRight()[1]:
289 nextra += ngrow
290 for y in range(y0 - ny//2, y0 + ny//2 + 1):
291 self.assertNotEqual(im.getMask()[x0 + 1, y, afwImage.LOCAL], 0)
293 self.assertEqual(foot.getArea(), (1 + nextra)*ny)
294 #
295 # Test growing to up and/or down
296 #
297 for fctrl in (
298 afwDetect.FootprintControl(False, False, True, False),
299 afwDetect.FootprintControl(False, False, False, True),
300 afwDetect.FootprintControl(False, False, True, True),
301 ):
302 grown = afwDetect.FootprintSet(fs, ngrow, fctrl)
303 im.getMask().set(0)
304 afwDetect.setMaskFromFootprintList(
305 im.getMask(), grown.getFootprints(), 0x10)
307 if display:
308 afwDisplay.Display(frame=2).mtv(im, title=self._testMethodName + " image")
310 foot = grown.getFootprints()[0]
311 nextra = 0
312 if fctrl.isUp()[1]:
313 nextra += ngrow
314 for y in range(y0 + ny//2 + 1, y0 + ny//2 + ngrow + 1):
315 self.assertNotEqual(im.getMask()[x0, y, afwImage.LOCAL], 0)
317 if fctrl.isDown()[1]:
318 nextra += ngrow
319 for y in range(y0 - ny//2 - 1, y0 - ny//2 - ngrow - 1):
320 self.assertNotEqual(im.getMask()[x0, y, afwImage.LOCAL], 0)
322 self.assertEqual(foot.getArea(), ny + nextra)
324 def testGrowLRUD2(self):
325 """Grow footprints in various directions using the FootprintSet/FootprintControl constructor
327 Check that overlapping grown Footprints give the expected answers
328 """
329 ngrow = 3 # How much to grow by
330 for fctrl, xy in [
331 (afwDetect.FootprintControl(True, True,
332 False, False), [(4, 5), (5, 6), (6, 5)]),
333 (afwDetect.FootprintControl(False, False,
334 True, True), [(5, 4), (6, 5), (5, 6)]),
335 ]:
336 im = afwImage.MaskedImageF(11, 11)
337 for x, y in xy:
338 im[x, y, afwImage.LOCAL] = (10, 0x0, 0.0)
339 fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10))
340 self.assertEqual(len(fs.getFootprints()), 1)
342 grown = afwDetect.FootprintSet(fs, ngrow, fctrl)
343 im.getMask().set(0)
344 afwDetect.setMaskFromFootprintList(
345 im.getMask(), grown.getFootprints(), 0x10)
347 if display:
348 afwDisplay.Display(frame=1).mtv(im, title=self._testMethodName + " image")
350 self.assertEqual(len(grown.getFootprints()), 1)
351 foot = grown.getFootprints()[0]
353 npix = 1 + 2*ngrow
354 npix += 3 + 2*ngrow # 3: distance between pair of set pixels 000X0X000
355 self.assertEqual(foot.getArea(), npix)
357 def testInf(self):
358 """Test detection for images with Infs"""
360 im = afwImage.MaskedImageF(lsst.geom.Extent2I(10, 20))
361 im.set(0)
363 import numpy
364 for x in range(im.getWidth()):
365 im[x, -1, afwImage.LOCAL] = (numpy.Inf, 0x0, 0)
367 ds = afwDetect.FootprintSet(im, afwDetect.createThreshold(100))
369 objects = ds.getFootprints()
370 afwDetect.setMaskFromFootprintList(im.getMask(), objects, 0x10)
372 if display:
373 afwDisplay.Display(frame=2).mtv(im, title=self._testMethodName + " image")
375 self.assertEqual(len(objects), 1)
378class PeaksInFootprintsTestCase(unittest.TestCase):
379 """A test case for detecting Peaks within Footprints"""
381 def doSetUp(self, dwidth=0, dheight=0, x0=0, y0=0):
382 width, height = 14 + x0 + dwidth, 10 + y0 + dheight
383 self.im = afwImage.MaskedImageF(lsst.geom.Extent2I(width, height))
384 #
385 # Objects that we should detect
386 #
387 self.objects, self.peaks = [], []
388 self.objects.append(
389 [[4, 1, 10], [3, 2, 10], [4, 2, 20], [5, 2, 10], [4, 3, 10], ])
390 self.peaks.append([[4, 2]])
391 self.objects.append(
392 [[9, 7, 30], [10, 7, 29], [12, 7, 25], [10, 8, 27], [11, 8, 26], ])
393 self.peaks.append([[9, 7]])
394 self.objects.append([[3, 8, 10], [4, 8, 10], ])
395 self.peaks.append([[3, 8], [4, 8], ])
397 for pp in self.peaks: # allow for x0, y0
398 for p in pp:
399 p[0] += x0
400 p[1] += y0
401 for oo in self.objects:
402 for o in oo:
403 o[0] += x0
404 o[1] += y0
406 self.im.set((0, 0x0, 0)) # clear image
407 for obj in self.objects:
408 for x, y, I in obj:
409 self.im.getImage()[x, y, afwImage.LOCAL] = I
411 def setUp(self):
412 self.im, self.fs = None, None
414 def tearDown(self):
415 del self.im
416 del self.fs
418 def doTestPeaks(self, dwidth=0, dheight=0, x0=0, y0=0, threshold=10, callback=None, polarity=True,
419 grow=0):
420 """Worker routine for tests
421 polarity: True if should search for +ve pixels"""
423 self.doSetUp(dwidth, dheight, x0, y0)
424 if not polarity:
425 self.im *= -1
427 if callback:
428 callback()
430 def peakDescending(p):
431 """Sort self.peaks in decreasing peak height to match Footprint.getPeaks()"""
432 return p[2]*-1.0
433 for i, peaks in enumerate(self.peaks):
434 self.peaks[i] = sorted([(x, y, self.im.getImage()[x, y, afwImage.LOCAL]) for x, y in peaks],
435 key=peakDescending)
437 threshold = afwDetect.Threshold(
438 threshold, afwDetect.Threshold.VALUE, polarity)
439 fs = afwDetect.FootprintSet(self.im, threshold, "BINNED1")
441 if grow:
442 fs = afwDetect.FootprintSet(fs, grow, True)
443 msk = self.im.getMask()
444 afwDetect.setMaskFromFootprintList(
445 msk, fs.getFootprints(), msk.getPlaneBitMask("DETECTED"))
446 del msk
448 self.fs = fs
449 self.checkPeaks(dwidth, dheight, frame=3)
451 def checkPeaks(self, dwidth=0, dheight=0, frame=3):
452 """Check that we got the peaks right"""
453 feet = self.fs.getFootprints()
454 #
455 # Check that we found all the peaks
456 #
457 self.assertEqual(sum([len(f.getPeaks()) for f in feet]),
458 sum([len(f.getPeaks()) for f in feet]))
460 if display:
461 disp = afwDisplay.Display(frame=frame)
462 disp.mtv(self.im, title=self._testMethodName + " image")
464 with disp.Buffering():
465 for i, foot in enumerate(feet):
466 for p in foot.getPeaks():
467 disp.dot("+", p.getIx(), p.getIy(), size=0.4)
469 if i < len(self.peaks):
470 for trueX, trueY, peakVal in self.peaks[i]:
471 disp.dot("x", trueX, trueY, size=0.4, ctype=afwDisplay.RED)
473 for i, foot in enumerate(feet):
474 npeak = None
475 #
476 # Peaks that touch the edge are handled differently, as only the single highest/lowest pixel
477 # is treated as a Peak
478 #
479 if (dwidth != 0 or dheight != 0):
480 if (foot.getBBox().getMinX() == 0
481 or foot.getBBox().getMaxX() == self.im.getWidth() - 1
482 or foot.getBBox().getMinY() == 0
483 or foot.getBBox().getMaxY() == self.im.getHeight() - 1):
484 npeak = 1
486 if npeak is None:
487 npeak = len(self.peaks[i])
489 self.assertEqual(len(foot.getPeaks()), npeak)
491 for j, p in enumerate(foot.getPeaks()):
492 trueX, trueY, peakVal = self.peaks[i][j]
493 self.assertEqual((p.getIx(), p.getIy()), (trueX, trueY))
495 def testSinglePeak(self):
496 """Test that we can find single Peaks in Footprints"""
498 self.doTestPeaks()
500 def testSingleNegativePeak(self):
501 """Test that we can find single Peaks in Footprints when looking for -ve detections"""
503 self.doTestPeaks(polarity=False)
505 def testSinglePeakAtEdge(self):
506 """Test that we handle Peaks correctly at the edge"""
508 self.doTestPeaks(dheight=-1)
510 def testSingleNegativePeakAtEdge(self):
511 """Test that we handle -ve Peaks correctly at the edge"""
513 self.doTestPeaks(dheight=-1, polarity=False)
515 def testMultiPeak(self):
516 """Test that multiple peaks are handled correctly"""
517 def callback():
518 x, y = 12, 7
519 self.im.getImage()[x, y, afwImage.LOCAL] = 100
520 self.peaks[1].append((x, y))
522 self.doTestPeaks(callback=callback)
524 def testMultiNegativePeak(self):
525 """Test that multiple negative peaks are handled correctly"""
526 def callback():
527 x, y = 12, 7
528 self.im.getImage()[x, y, afwImage.LOCAL] = -100
529 self.peaks[1].append((x, y))
531 self.doTestPeaks(polarity=False, callback=callback)
533 def testGrowFootprints(self):
534 """Test that we can grow footprints, correctly merging those that now touch"""
535 def callback():
536 self.im.getImage()[10, 4, afwImage.LOCAL] = 20
537 self.peaks[-2].append((10, 4,))
539 self.doTestPeaks(dwidth=1, dheight=1, callback=callback, grow=1)
541 def testGrowFootprints2(self):
542 """Test that we can grow footprints, correctly merging those that now overlap
543 N.b. this caused RHL's initial implementation to crash
544 """
545 def callback():
546 self.im.getImage()[10, 4, afwImage.LOCAL] = 20
547 self.peaks[-2].append((10, 4, ))
549 def peaksSortKey(p):
550 return peakFromImage(self.im, p)
551 self.peaks[0] = sorted(sum(self.peaks, []), key=peaksSortKey)
553 self.doTestPeaks(x0=0, y0=2, dwidth=2, dheight=2,
554 callback=callback, grow=2)
556 def testGrowFootprints3(self):
557 """Test that we can grow footprints, correctly merging those that now totally overwritten"""
559 self.im = afwImage.MaskedImageF(14, 11)
561 self.im.getImage().set(0)
562 self.peaks = []
564 value = 11
565 for x, y in [(4, 7), (5, 7), (6, 7), (7, 7), (8, 7),
566 (4, 6), (8, 6),
567 (4, 5), (8, 5),
568 (4, 4), (8, 4),
569 (4, 3), (8, 3),
570 ]:
571 self.im.getImage()[x, y, afwImage.LOCAL] = value
572 value -= 1e-3
574 self.im.getImage()[4, 7, afwImage.LOCAL] = 15
575 self.peaks.append([(4, 7,), ])
577 self.im.getImage()[6, 5, afwImage.LOCAL] = 30
578 self.peaks[0].append((6, 5,))
580 self.fs = afwDetect.FootprintSet(
581 self.im, afwDetect.Threshold(10), "BINNED1")
582 #
583 # The disappearing Footprint special case only shows up if the outer Footprint is grown
584 # _after_ the inner one. So arrange the order properly
585 feet = self.fs.getFootprints()
586 feet[0], feet[1] = feet[1], feet[0]
588 msk = self.im.getMask()
590 grow = 2
591 self.fs = afwDetect.FootprintSet(self.fs, grow, False)
592 afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(),
593 msk.getPlaneBitMask("DETECTED_NEGATIVE"))
595 if display:
596 frame = 0
598 disp = afwDisplay.Display(frame=frame)
599 disp.mtv(self.im, title=self._testMethodName + " image")
601 with disp.Buffering():
602 for i, foot in enumerate(self.fs.getFootprints()):
603 for p in foot.getPeaks():
604 disp.dot("+", p.getIx(), p.getIy(), size=0.4)
606 if i < len(self.peaks):
607 for trueX, trueY in self.peaks[i]:
608 disp.dot("x", trueX, trueY, size=0.4, ctype=afwDisplay.RED)
610 self.assertEqual(len(self.fs.getFootprints()), 1)
611 self.assertEqual(len(self.fs.getFootprints()[
612 0].getPeaks()), len(self.peaks[0]))
614 def testMergeFootprints(self): # YYYY
615 """Merge positive and negative Footprints"""
616 x0, y0 = 5, 6
617 dwidth, dheight = 6, 7
619 def callback():
620 x, y, value = x0 + 10, y0 + 4, -20
621 self.im.getImage()[x, y, afwImage.LOCAL] = value
622 peaks2.append((x, y, value))
624 for grow1, grow2 in [(1, 1), (3, 3), (6, 6), ]:
625 peaks2 = []
626 self.doTestPeaks(threshold=10, callback=callback, grow=0,
627 x0=x0, y0=y0, dwidth=dwidth, dheight=dheight)
629 threshold = afwDetect.Threshold(
630 10, afwDetect.Threshold.VALUE, False)
631 fs2 = afwDetect.FootprintSet(self.im, threshold)
633 msk = self.im.getMask()
634 afwDetect.setMaskFromFootprintList(
635 msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE"))
637 self.fs.merge(fs2, grow1, grow2)
638 self.peaks[-2] += peaks2
640 if grow1 + grow2 > 2: # grow merged all peaks
641 def peaksSortKey(p):
642 return peakFromImage(self.im, p)
643 self.peaks[0] = sorted(sum(self.peaks, []), key=peaksSortKey)
645 afwDetect.setMaskFromFootprintList(
646 msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE"))
648 self.checkPeaks(frame=3)
650 def testMergeFootprintsEngulf(self):
651 """Merge two Footprints when growing one Footprint totally replaces the other"""
652 def callback():
653 self.im.set(0)
654 self.peaks, self.objects = [], []
656 for x, y, I in [[6, 4, 20], [6, 5, 10]]:
657 self.im.getImage()[x, y, afwImage.LOCAL] = I
658 self.peaks.append([[6, 4]])
660 x, y, value = 8, 4, -20
661 self.im.getImage()[x, y, afwImage.LOCAL] = value
662 peaks2.append((x, y, value))
664 grow1, grow2 = 0, 3
665 peaks2 = []
666 self.doTestPeaks(threshold=10, callback=callback, grow=0)
668 threshold = afwDetect.Threshold(10, afwDetect.Threshold.VALUE, False)
669 fs2 = afwDetect.FootprintSet(self.im, threshold)
671 msk = self.im.getMask()
672 afwDetect.setMaskFromFootprintList(
673 msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE"))
675 self.fs.merge(fs2, grow1, grow2)
676 self.peaks[0] += peaks2
678 def peaksSortKey(p):
679 return peakFromImage(self.im, p)
680 self.peaks[0] = sorted(sum(self.peaks, []), key=peaksSortKey)
682 afwDetect.setMaskFromFootprintList(
683 msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE"))
685 self.checkPeaks(frame=3)
688class MemoryTester(lsst.utils.tests.MemoryTestCase):
689 pass
692def setup_module(module):
693 lsst.utils.tests.init()
696if __name__ == "__main__": 696 ↛ 697line 696 didn't jump to line 697, because the condition on line 696 was never true
697 lsst.utils.tests.init()
698 unittest.main()