Coverage for examples/portionFigureWithMissingSrc.py: 0%

128 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-29 02:58 -0700

1#!/usr/bin/env python 

2 

3import numpy 

4import matplotlib.figure as figure 

5from matplotlib.backends.backend_agg import FigureCanvasAgg as FigCanvas 

6from matplotlib.patches import Rectangle 

7 

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 

14 

15 

16def randomCoords(nSrc, grid=False, minSep=0.15, maxSep=0.25): 

17 

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 

32 

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)) 

51 

52 return xy 

53 

54 

55def makeFakeImage(nx, ny, xys, fluxes, fwhms): 

56 

57 mimg = afwImage.MaskedImageF(nx, ny) 

58 img = mimg.getImage().getArray() 

59 var = mimg.getVariance().getArray() 

60 var[:, :] = 1.0 

61 

62 nSrc = len(xys) 

63 

64 n = min([nx, ny]) 

65 

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() 

76 

77 return mimg 

78 

79 

80def detect(mimg): 

81 

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 

91 

92 

93def makePortionFigure(deblend, origMimg, origMimgB, pedestal=0.0): 

94 

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()) 

101 

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) 

109 

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) 

114 

115 portions.append(portionedImg) 

116 

117 fig = figure.Figure(figsize=(8, 10)) 

118 FigCanvas(fig) 

119 

120 g = int(numpy.ceil(numpy.sqrt(len(deblend.peaks)))) 

121 gx, gy = g, g+1 

122 

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 

133 

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") 

137 

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 

148 

149 return fig 

150 

151 

152def main(): 

153 

154 log = Log.getLogger('foo') 

155 log.setLevel(Log.INFO) 

156 

157 ny, nx = 256, 256 

158 

159 fwhm0 = 5.0 

160 psf = measAlg.DoubleGaussianPsf(21, 21, fwhm0) 

161 flux = 1.0e6 

162 

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") 

169 

170 nSrcB = nSrc - 4 

171 mimgB = makeFakeImage(nx, ny, xy[0:nSrcB], fluxs[0:nSrcB], [3.0*fwhm0]*nSrcB) 

172 mimgB.writeFits("fooB.fits") 

173 

174 # Run the detection 

175 fp = detect(mimg) 

176 

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)) 

180 

181 fig = makePortionFigure(deb, mimg, mimgB) 

182 fig.savefig("test.png") 

183 

184 

185if __name__ == '__main__': 

186 main()