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

1from builtins import object 

2import numpy as np 

3from lsst.sims.utils import arcsecFromRadians 

4 

5__all__ = ["GalSimCelestialObject"] 

6 

7class GalSimCelestialObject(object): 

8 """ 

9 This is a class meant to carry around all of the data required by 

10 the GalSimInterpreter to draw an image of a single object. The idea 

11 is that all of the drawing functions in the GalSimInterpreter will 

12 just take a GalSimCelestialObject as an argument, rather than taking 

13 a bunch of different arguments, one for each datum. 

14 """ 

15 

16 def __init__(self, galSimType, xPupil, yPupil, 

17 halfLightRadius, minorAxis, majorAxis, positionAngle, 

18 sindex, sed, bp_dict, photParams, npoints, 

19 fits_image_file, pixel_scale, rotation_angle, 

20 gamma1=0, gamma2=0, kappa=0, uniqueId=None): 

21 """ 

22 @param [in] galSimType is a string, either 'pointSource', 'sersic', 

23 'RandomWalk', or 'FitsImage' denoting the shape of the object 

24 

25 @param [in] xPupil is the x pupil coordinate of the object in radians 

26 

27 @param [in] yPupil is the y pupil coordinate of the object in radians 

28 

29 @param [in] halfLightRadius is the halfLightRadius of the object in radians 

30 

31 @param [in] minorAxis is the semi-minor axis of the object in radians 

32 

33 @param [in] majorAxis is the semi-major axis of the object in radians 

34 

35 @param [in] positionAngle is the position angle of the object in radians 

36 

37 @param [in] sindex is the sersic index of the object 

38 

39 @param [in] sed is an instantiation of lsst.sims.photUtils.Sed 

40 representing the SED of the object (with all normalization, 

41 dust extinction, redshifting, etc. applied) 

42 

43 @param [in] bp_dict is an instantiation of lsst.sims.photUtils.BandpassDict 

44 representing the bandpasses of this telescope 

45 

46 @param [in] photParams is an instantioation of 

47 lsst.sims.photUtils.PhotometricParameters representing the physical 

48 parameters of the telescope that inform simulated photometry 

49 

50 Together, sed, bp_dict, and photParams will be used to create 

51 a dict that maps bandpass name to electron counts for this 

52 celestial object. 

53 

54 @param [in] npoints is the number of point sources in a RandomWalk 

55 

56 @param [in] fits_image_file is the filename for the FitsImage 

57 

58 @param [in] pixel_scale is the pixel size in arcsec of the FitsImage 

59 

60 @param [in] rotation_angle is the rotation angle in degrees for 

61 the FitsImage 

62 

63 @param [in] gamma1 is the real part of the WL shear parameter 

64 

65 @param [in] gamma2 is the imaginary part of the WL shear parameter 

66 

67 @param [in] kappa is the WL convergence parameter 

68 

69 @param [in] uniqueId is an int storing a unique identifier for this object 

70 """ 

71 self._uniqueId = uniqueId 

72 self._galSimType = galSimType 

73 self._fits_image_file = fits_image_file 

74 

75 # The galsim.lens(...) function wants to be passed reduced 

76 # shears and magnification, so convert the WL parameters as 

77 # defined in phosim instance catalogs to these values. See 

78 # https://github.com/GalSim-developers/GalSim/blob/releases/1.4/doc/GalSim_Quick_Reference.pdf 

79 # and Hoekstra, 2013, http://lanl.arxiv.org/abs/1312.5981 

80 g1 = gamma1/(1. - kappa) # real part of reduced shear 

81 g2 = gamma2/(1. - kappa) # imaginary part of reduced shear 

82 mu = 1./((1. - kappa)**2 - (gamma1**2 + gamma2**2)) # magnification 

83 

84 self._fluxDict = {} 

85 self._sed = sed 

86 self._bp_dict = bp_dict 

87 self._photParams = photParams 

88 

89 # Put all the float values into a numpy array for better memory usage. 

90 # (Otherwise, python allocates a shared pointer for each one of these 15 values, which 

91 # adds up to a significant memory overhead.) 

92 self._float_values = np.array([ 

93 xPupil, # xPupilRadians, 0 

94 arcsecFromRadians(xPupil), # xPupilArcsec, 1 

95 yPupil, # yPupilRadians, 2 

96 arcsecFromRadians(yPupil), # yPupilArcsec, 3 

97 halfLightRadius, # halfLightRadiusRadians, 4 

98 arcsecFromRadians(halfLightRadius), # halfLightRadiusArcsec, 5 

99 minorAxis, # minorAxisRadians, 6 

100 majorAxis, # majorAxisRadians, 7 

101 positionAngle, # positionAngleRadians, 8 

102 sindex, # sindex, 9 

103 pixel_scale, # pixel_scale, 10 

104 rotation_angle, # rotation_angle, 11 

105 g1, # g1, 12 

106 g2, # g2, 13 

107 mu, # mu, 14 

108 npoints # npoints, 15 

109 ], dtype=float) 

110 

111 # XXX: We could probably get away with np.float32 for these, but the main 

112 # advantage is from only allocating the actual memory, and not the python 

113 # pointers to the memory. So not so much more gain to be had from switching 

114 # to single precision. 

115 

116 # 

117 # First properties for all the non-float values. 

118 # 

119 

120 @property 

121 def sed(self): 

122 return self._sed 

123 

124 @property 

125 def uniqueId(self): 

126 return self._uniqueId 

127 

128 # XXX: I'd recommend removing all these setters and just let python raise an 

129 # AttributeError if people try to set the values, rather than raising a 

130 # RuntimeError manually. -- MJ 

131 @uniqueId.setter 

132 def uniqueId(self, value): 

133 raise RuntimeError("You should not be setting the unique id on the fly; " \ 

134 + "just instantiate a new GalSimCelestialObject") 

135 

136 @property 

137 def galSimType(self): 

138 return self._galSimType 

139 

140 @galSimType.setter 

141 def galSimType(self, value): 

142 raise RuntimeError("You should not be setting galSimType on the fly; " \ 

143 + "just instantiate a new GalSimCelestialObject") 

144 

145 @property 

146 def npoints(self): 

147 return int(self._float_values[15]+0.5) 

148 

149 @npoints.setter 

150 def npoints(self, value): 

151 raise RuntimeError("You should not be setting npoints on the fly; " \ 

152 + "just instantiate a new GalSimCelestialObject") 

153 

154 @property 

155 def fits_image_file(self): 

156 return self._fits_image_file 

157 

158 @fits_image_file.setter 

159 def fits_image_file(self, value): 

160 raise RuntimeError("You should not be setting fits_image_file on the fly; " 

161 "just instantiate a new GalSimCelestialObject") 

162 

163 

164 # 

165 # The float values are accessed from the numpy array called self._float_values. 

166 # 

167 

168 @property 

169 def xPupilRadians(self): 

170 return self._float_values[0] 

171 

172 @xPupilRadians.setter 

173 def xPupilRadians(self, value): 

174 raise RuntimeError("You should not be setting xPupilRadians on the fly; " \ 

175 + "just instantiate a new GalSimCelestialObject") 

176 

177 

178 @property 

179 def xPupilArcsec(self): 

180 return self._float_values[1] 

181 

182 @xPupilArcsec.setter 

183 def xPupilArcsec(self, value): 

184 raise RuntimeError("You should not be setting xPupilArcsec on the fly; " \ 

185 + "just instantiate a new GalSimCelestialObject") 

186 

187 

188 @property 

189 def yPupilRadians(self): 

190 return self._float_values[2] 

191 

192 @yPupilRadians.setter 

193 def yPupilRadians(self, value): 

194 raise RuntimeError("You should not be setting yPupilRadians on the fly; " \ 

195 + "just instantiate a new GalSimCelestialObject") 

196 

197 

198 @property 

199 def yPupilArcsec(self): 

200 return self._float_values[3] 

201 

202 @yPupilArcsec.setter 

203 def yPupilArcsec(self, value): 

204 raise RuntimeError("You should not be setting yPupilArcsec on the fly; " \ 

205 + "just instantiate a new GalSimCelestialObject") 

206 

207 

208 @property 

209 def halfLightRadiusRadians(self): 

210 return self._float_values[4] 

211 

212 @halfLightRadiusRadians.setter 

213 def halfLightRadiusRadians(self, value): 

214 raise RuntimeError("You should not be setting halfLightRadiusRadians on the fly; " \ 

215 + "just instantiate a new GalSimCelestialObject") 

216 

217 

218 @property 

219 def halfLightRadiusArcsec(self): 

220 return self._float_values[5] 

221 

222 @halfLightRadiusArcsec.setter 

223 def halfLightRadiusArcsec(self, value): 

224 raise RuntimeError("You should not be setting halfLightRadiusArcsec on the fly; " \ 

225 + "just instantiate a new GalSimCelestialObject") 

226 

227 

228 @property 

229 def minorAxisRadians(self): 

230 return self._float_values[6] 

231 

232 @minorAxisRadians.setter 

233 def minorAxisRadians(self, value): 

234 raise RuntimeError("You should not be setting minorAxisRadians on the fly; " \ 

235 + "just instantiate a new GalSimCelestialObject") 

236 

237 

238 @property 

239 def majorAxisRadians(self): 

240 return self._float_values[7] 

241 

242 @majorAxisRadians.setter 

243 def majorAxisRadians(self, value): 

244 raise RuntimeError("You should not be setting majorAxisRadians on the fly; " \ 

245 + "just instantiate a new GalSimCelestialObject") 

246 

247 

248 @property 

249 def positionAngleRadians(self): 

250 return self._float_values[8] 

251 

252 @positionAngleRadians.setter 

253 def positionAngleRadians(self, value): 

254 raise RuntimeError("You should not be setting positionAngleRadians on the fly; " \ 

255 + "just instantiate a new GalSimCelestialObject") 

256 

257 

258 @property 

259 def sindex(self): 

260 return self._float_values[9] 

261 

262 @sindex.setter 

263 def sindex(self, value): 

264 raise RuntimeError("You should not be setting sindex on the fly; " \ 

265 + "just instantiate a new GalSimCelestialObject") 

266 

267 @property 

268 def pixel_scale(self): 

269 return self._float_values[10] 

270 

271 @pixel_scale.setter 

272 def pixel_scale(self, value): 

273 raise RuntimeError("You should not be setting pixel_scale on the fly; " 

274 "just instantiate a new GalSimCelestialObject") 

275 

276 @property 

277 def rotation_angle(self): 

278 return self._float_values[11] 

279 

280 @rotation_angle.setter 

281 def rotation_angle(self, value): 

282 raise RuntimeError("You should not be setting rotation_angle on the fly; " 

283 "just instantiate a new GalSimCelestialObject") 

284 

285 @property 

286 def g1(self): 

287 return self._float_values[12] 

288 

289 @g1.setter 

290 def g1(self, value): 

291 raise RuntimeError("You should not be setting g1 on the fly; " \ 

292 + "just instantiate a new GalSimCelestialObject") 

293 

294 

295 @property 

296 def g2(self): 

297 return self._float_values[13] 

298 

299 @g2.setter 

300 def g2(self, value): 

301 raise RuntimeError("You should not be setting g2 on the fly; " \ 

302 + "just instantiate a new GalSimCelestialObject") 

303 

304 

305 @property 

306 def mu(self): 

307 return self._float_values[14] 

308 

309 @mu.setter 

310 def mu(self, value): 

311 raise RuntimeError("You should not be setting mu on the fly; " \ 

312 + "just instantiate a new GalSimCelestialObject") 

313 

314 

315 

316 def flux(self, band): 

317 """ 

318 @param [in] band is the name of a bandpass 

319 

320 @param [out] the ADU in that bandpass, as stored in self._fluxDict 

321 """ 

322 if band not in self._bp_dict: 

323 raise RuntimeError("Asked GalSimCelestialObject for flux in %s; that band does not exist" % band) 

324 

325 if band not in self._fluxDict: 

326 adu = self.sed.calcADU(self._bp_dict[band], self._photParams) 

327 self._fluxDict[band] = adu*self._photParams.gain 

328 

329 return self._fluxDict[band]