Hide keyboard shortcuts

Hot-keys 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# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2017 AURA/LSST. 

5# 

6# This product includes software developed by the 

7# LSST Project (http://www.lsst.org/). 

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 LSST License Statement and 

20# the GNU General Public License along with this program. If not, 

21# see <https://www.lsstcorp.org/LegalNotices/>. 

22# 

23 

24import numpy as np 

25 

26import lsst.geom 

27import lsst.afw.image as afwImage 

28from . import SingleGaussianPsf 

29from . import Defect 

30 

31 

32def plantSources(bbox, kwid, sky, coordList, addPoissonNoise=True): 

33 """Make an exposure with stars (modelled as Gaussians) 

34 

35 Parameters 

36 ---------- 

37 bbox : `lsst.geom.Box2I` 

38 Parent bbox of exposure 

39 kwid : `int` 

40 Kernal width (and height; kernal is square) 

41 sky : `float` 

42 Amount of sky background (counts) 

43 coordList : `list [tuple]` 

44 A list of [x, y, counts, sigma] where: 

45 * x,y are relative to exposure origin 

46 * counts is the integrated counts for the star 

47 * sigma is the Gaussian sigma in pixels 

48 addPoissonNoise : `bool` 

49 If True: add Poisson noise to the exposure 

50 """ 

51 # make an image with sources 

52 img = afwImage.ImageD(bbox) 

53 meanSigma = 0.0 

54 for coord in coordList: 

55 x, y, counts, sigma = coord 

56 meanSigma += sigma 

57 

58 # make a single gaussian psf 

59 psf = SingleGaussianPsf(kwid, kwid, sigma) 

60 

61 # make an image of it and scale to the desired number of counts 

62 thisPsfImg = psf.computeImage(lsst.geom.PointD(x, y)) 

63 thisPsfImg *= counts 

64 

65 # bbox a window in our image and add the fake star image 

66 psfBox = thisPsfImg.getBBox() 

67 psfBox.clip(bbox) 

68 if psfBox != thisPsfImg.getBBox(): 

69 thisPsfImg = thisPsfImg[psfBox, afwImage.PARENT] 

70 imgSeg = img[psfBox, afwImage.PARENT] 

71 imgSeg += thisPsfImg 

72 meanSigma /= len(coordList) 

73 

74 img += sky 

75 

76 # add Poisson noise 

77 if (addPoissonNoise): 

78 np.random.seed(seed=1) # make results reproducible 

79 imgArr = img.getArray() 

80 imgArr[:] = np.random.poisson(imgArr) 

81 

82 # bundle into a maskedimage and an exposure 

83 mask = afwImage.Mask(bbox) 

84 var = img.convertFloat() 

85 img -= sky 

86 mimg = afwImage.MaskedImageF(img.convertFloat(), mask, var) 

87 exposure = afwImage.makeExposure(mimg) 

88 

89 # insert an approximate psf 

90 psf = SingleGaussianPsf(kwid, kwid, meanSigma) 

91 exposure.setPsf(psf) 

92 

93 return exposure 

94 

95 

96def makeRandomTransmissionCurve(rng, minWavelength=4000.0, maxWavelength=7000.0, nWavelengths=200, 

97 maxRadius=80.0, nRadii=30, perturb=0.05): 

98 """Create a random TransmissionCurve with nontrivial spatial and 

99 wavelength variation. 

100 

101 Parameters 

102 ---------- 

103 rng : numpy.random.RandomState 

104 Random number generator. 

105 minWavelength : float 

106 Average minimum wavelength for generated TransmissionCurves (will be 

107 randomly perturbed). 

108 maxWavelength : float 

109 Average maximum wavelength for generated TransmissionCurves (will be 

110 randomly perturbed). 

111 nWavelengths : int 

112 Number of samples in the wavelength dimension. 

113 maxRadius : float 

114 Average maximum radius for spatial variation (will be perturbed). 

115 nRadii : int 

116 Number of samples in the radial dimension. 

117 perturb: float 

118 Fraction by which wavelength and radius bounds should be randomly 

119 perturbed. 

120 """ 

121 dWavelength = maxWavelength - minWavelength 

122 

123 def perturbed(x, s=perturb*dWavelength): 

124 return x + 2.0*s*(rng.rand() - 0.5) 

125 

126 wavelengths = np.linspace(perturbed(minWavelength), perturbed(maxWavelength), nWavelengths) 

127 radii = np.linspace(0.0, perturbed(maxRadius, perturb*maxRadius), nRadii) 

128 throughput = np.zeros(wavelengths.shape + radii.shape, dtype=float) 

129 # throughput will be a rectangle in wavelength, shifting to higher wavelengths and shrinking 

130 # in height with radius, going to zero at all bounds. 

131 peak0 = perturbed(0.9, 0.05) 

132 start0 = perturbed(minWavelength + 0.25*dWavelength) 

133 stop0 = perturbed(minWavelength + 0.75*dWavelength) 

134 for i, r in enumerate(radii): 

135 mask = np.logical_and(wavelengths >= start0 + r, wavelengths <= stop0 + r) 

136 throughput[mask, i] = peak0*(1.0 - r/1000.0) 

137 return afwImage.TransmissionCurve.makeRadial(throughput, wavelengths, radii) 

138 

139 

140def makeDefectList(): 

141 """Create a list of defects that can be used for testing. 

142 

143 Returns 

144 ------- 

145 defectList = `list` [`lsst.meas.algorithms.Defect`] 

146 The list of defects. 

147 """ 

148 defectList = [Defect(lsst.geom.Box2I(lsst.geom.Point2I(962, 0), 

149 lsst.geom.Extent2I(2, 4611))), 

150 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1316, 0), 

151 lsst.geom.Extent2I(2, 4611))), 

152 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1576, 0), 

153 lsst.geom.Extent2I(4, 4611))), 

154 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1626, 0), 

155 lsst.geom.Extent2I(2, 4611))), 

156 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1994, 252), 

157 lsst.geom.Extent2I(2, 4359))), 

158 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1426, 702), 

159 lsst.geom.Extent2I(2, 3909))), 

160 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1526, 1140), 

161 lsst.geom.Extent2I(2, 3471))), 

162 Defect(lsst.geom.Box2I(lsst.geom.Point2I(856, 2300), 

163 lsst.geom.Extent2I(2, 2311))), 

164 Defect(lsst.geom.Box2I(lsst.geom.Point2I(858, 2328), 

165 lsst.geom.Extent2I(2, 65))), 

166 Defect(lsst.geom.Box2I(lsst.geom.Point2I(859, 2328), 

167 lsst.geom.Extent2I(1, 56))), 

168 Defect(lsst.geom.Box2I(lsst.geom.Point2I(844, 2796), 

169 lsst.geom.Extent2I(4, 1814))), 

170 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1366, 2804), 

171 lsst.geom.Extent2I(2, 1806))), 

172 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1766, 3844), 

173 lsst.geom.Extent2I(2, 766))), 

174 Defect(lsst.geom.Box2I(lsst.geom.Point2I(1872, 4228), 

175 lsst.geom.Extent2I(2, 382))), 

176 ] 

177 

178 return defectList