Coverage for examples/portionFigureWithMissingSrc.py: 0%
128 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-20 02:44 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-20 02:44 -0700
1#!/usr/bin/env python
3import numpy
4import matplotlib.figure as figure
5from matplotlib.backends.backend_agg import FigureCanvasAgg as FigCanvas
6from matplotlib.patches import Rectangle
8import lsst.afw.geom as afwGeom
9import lsst.afw.image as afwImage
10import lsst.afw.detection as afwDet
11from lsst.log import Log
12import lsst.meas.algorithms as measAlg
13import lsst.meas.deblender.baseline as measDeb
16def randomCoords(nSrc, grid=False, minSep=0.15, maxSep=0.25):
18 if grid:
19 # 3 in a row is a known failure, so ignore nSrc
20 xy = (
21 (0.33, 0.33),
22 (0.33, 0.67),
23 (0.67, 0.33),
24 (0.67, 0.67),
25 )
26 nSrc = len(xy)
27 else:
28 i = 0
29 x = numpy.array([numpy.random.uniform(maxSep, 1.0-maxSep)])
30 y = numpy.array([numpy.random.uniform(maxSep, 1.0-maxSep)])
31 nMax = 10
33 # keep trying to add sources until we have nSrc
34 while (i < nSrc - 1):
35 smin = 0.0
36 iTry = 0
37 _x, _y = None, None
38 while ((smin < minSep or smin > maxSep) and iTry < nMax):
39 _x, _y = numpy.random.uniform(maxSep, 1.0-maxSep, 2)
40 dx = x - _x
41 dy = y - _y
42 s = numpy.sqrt(dx*dx + dy*dy)
43 smin = s.min()
44 print(smin, iTry)
45 iTry += 1
46 if _x and _y:
47 x = numpy.append(x, _x)
48 y = numpy.append(y, _y)
49 i += 1
50 xy = list(zip(x, y))
52 return xy
55def makeFakeImage(nx, ny, xys, fluxes, fwhms):
57 mimg = afwImage.MaskedImageF(nx, ny)
58 img = mimg.getImage().getArray()
59 var = mimg.getVariance().getArray()
60 var[:, :] = 1.0
62 nSrc = len(xys)
64 n = min([nx, ny])
66 for i in range(nSrc):
67 x, y = nx*xys[i][0], ny*xys[i][1]
68 src = measAlg.DoubleGaussianPsf(n, n, fwhms[i], fwhms[i], 0.03)
69 pimg = src.computeImage(afwGeom.Point2D(x, y))
70 pbox = pimg.getBBox(afwImage.PARENT)
71 pbox.clip(mimg.getBBox())
72 pimg = pimg.Factory(pimg, pbox, afwImage.PARENT)
73 xlo, xhi = pbox.getMinX(), pbox.getMaxX() + 1
74 ylo, yhi = pbox.getMinY(), pbox.getMaxY() + 1
75 img[ylo:yhi, xlo:xhi] += fluxes[i]*pimg.getArray()
77 return mimg
80def detect(mimg):
82 thresh = afwDet.createThreshold(10., 'value', True)
83 fpSet = afwDet.FootprintSet(mimg, thresh, 'DETECTED', 1)
84 fps = fpSet.getFootprints()
85 print('found', len(fps), 'footprints')
86 for fp in fps:
87 print('peaks:', len(fp.getPeaks()))
88 for pk in fp.getPeaks():
89 print(' ', pk.getIx(), pk.getIy())
90 return fps[0] if fps else None
93def makePortionFigure(deblend, origMimg, origMimgB, pedestal=0.0):
95 portions = []
96 centers = []
97 boxes = []
98 for i, peak in enumerate(deblend.peaks):
99 # make an image matching the size of the original
100 portionedImg = afwImage.ImageF(origMimg.getBBox())
102 # get the heavy footprint for the flux aportioned to this peak
103 heavyFoot = peak.getFluxPortion()
104 footBox = heavyFoot.getBBox()
105 pk = peak.peak
106 centers.append((pk.getIx(), pk.getIy()))
107 boxes.append(((footBox.getMinX(), footBox.getMinY()), footBox.getWidth(), footBox.getHeight()))
108 print(i, peak, pk.getIx(), pk.getIy(), footBox, "skip:", peak.skip)
110 # make a sub-image for this peak, and put the aportioned flux into it
111 portionedSubImg = afwImage.ImageF(portionedImg, footBox)
112 portionedSubImg += pedestal
113 heavyFoot.insert(portionedSubImg)
115 portions.append(portionedImg)
117 fig = figure.Figure(figsize=(8, 10))
118 FigCanvas(fig)
120 g = int(numpy.ceil(numpy.sqrt(len(deblend.peaks))))
121 gx, gy = g, g+1
123 def makeAx(ax, im, title):
124 im = im.getArray()
125 a = ax.imshow(im, cmap='gray')
126 cb = fig.colorbar(a)
127 ax.set_title(title, size='small')
128 ax.set_xlim((0, im.shape[0]))
129 ax.set_ylim((0, im.shape[1]))
130 for t in ax.get_xticklabels() + ax.get_yticklabels() + cb.ax.get_yticklabels():
131 t.set_size('x-small')
132 return ax
134 # show the originals
135 makeAx(fig.add_subplot(gy, gx, 1), origMimg.getImage(), "Orig")
136 makeAx(fig.add_subplot(gy, gx, 2), origMimgB.getImage(), "Missing Src")
138 # show each aportioned image
139 i = gy
140 for i_p in range(len(portions)):
141 im = portions[i_p]
142 ax = makeAx(fig.add_subplot(gy, gx, i), im, "")
143 xy, w, h = boxes[i_p]
144 ax.add_patch(Rectangle(xy, w, h, fill=False, edgecolor='#ff0000'))
145 for x, y in centers:
146 ax.plot(x, y, '+', color='#00ff00')
147 i += 1
149 return fig
152def main():
154 log = Log.getLogger('foo')
155 log.setLevel(Log.INFO)
157 ny, nx = 256, 256
159 fwhm0 = 5.0
160 psf = measAlg.DoubleGaussianPsf(21, 21, fwhm0)
161 flux = 1.0e6
163 # make two sets of fake data, seconds set is missing a source
164 nSrc = 4
165 xy = randomCoords(nSrc)
166 fluxs = [flux]*(nSrc-1) + [0.7*flux]
167 mimg = makeFakeImage(nx, ny, xy, fluxs, [3.0*fwhm0]*nSrc)
168 mimg.writeFits("foo.fits")
170 nSrcB = nSrc - 4
171 mimgB = makeFakeImage(nx, ny, xy[0:nSrcB], fluxs[0:nSrcB], [3.0*fwhm0]*nSrcB)
172 mimgB.writeFits("fooB.fits")
174 # Run the detection
175 fp = detect(mimg)
177 # deblend mimgB (missing a peak) using the fp with the extra peak
178 deb = measDeb.deblend(fp, mimgB, psf, fwhm0, verbose=True, rampFluxAtEdge=True, log=log)
179 print("Deblended peaks: ", len(deb.peaks))
181 fig = makePortionFigure(deb, mimg, mimgB)
182 fig.savefig("test.png")
185if __name__ == '__main__':
186 main()