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 @param bbox: parent bbox of exposure 

36 @param kwid: kernel width (and height; kernel is square) 

37 @param sky: amount of sky background (counts) 

38 @param coordList: a list of [x, y, counts, sigma], where: 

39 * x,y are relative to exposure origin 

40 * counts is the integrated counts for the star 

41 * sigma is the Gaussian sigma in pixels 

42 @param addPoissonNoise: add Poisson noise to the exposure? 

43 """ 

44 # make an image with sources 

45 img = afwImage.ImageD(bbox) 

46 meanSigma = 0.0 

47 for coord in coordList: 

48 x, y, counts, sigma = coord 

49 meanSigma += sigma 

50 

51 # make a single gaussian psf 

52 psf = SingleGaussianPsf(kwid, kwid, sigma) 

53 

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

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

56 thisPsfImg *= counts 

57 

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

59 psfBox = thisPsfImg.getBBox() 

60 psfBox.clip(bbox) 

61 if psfBox != thisPsfImg.getBBox(): 

62 thisPsfImg = thisPsfImg[psfBox, afwImage.PARENT] 

63 imgSeg = img[psfBox, afwImage.PARENT] 

64 imgSeg += thisPsfImg 

65 meanSigma /= len(coordList) 

66 

67 img += sky 

68 

69 # add Poisson noise 

70 if (addPoissonNoise): 

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

72 imgArr = img.getArray() 

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

74 

75 # bundle into a maskedimage and an exposure 

76 mask = afwImage.Mask(bbox) 

77 var = img.convertFloat() 

78 img -= sky 

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

80 exposure = afwImage.makeExposure(mimg) 

81 

82 # insert an approximate psf 

83 psf = SingleGaussianPsf(kwid, kwid, meanSigma) 

84 exposure.setPsf(psf) 

85 

86 return exposure 

87 

88 

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

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

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

92 wavelength variation. 

93 

94 Parameters 

95 ---------- 

96 rng : numpy.random.RandomState 

97 Random number generator. 

98 minWavelength : float 

99 Average minimum wavelength for generated TransmissionCurves (will be 

100 randomly perturbed). 

101 maxWavelength : float 

102 Average maximum wavelength for generated TransmissionCurves (will be 

103 randomly perturbed). 

104 nWavelengths : int 

105 Number of samples in the wavelength dimension. 

106 maxRadius : float 

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

108 nRadii : int 

109 Number of samples in the radial dimension. 

110 perturb: float 

111 Fraction by which wavelength and radius bounds should be randomly 

112 perturbed. 

113 """ 

114 dWavelength = maxWavelength - minWavelength 

115 

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

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

118 

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

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

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

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

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

124 peak0 = perturbed(0.9, 0.05) 

125 start0 = perturbed(minWavelength + 0.25*dWavelength) 

126 stop0 = perturbed(minWavelength + 0.75*dWavelength) 

127 for i, r in enumerate(radii): 

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

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

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

131 

132 

133def makeDefectList(): 

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

135 

136 Returns 

137 ------- 

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

139 The list of defects. 

140 """ 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

169 ] 

170 

171 return defectList