5 from astropy.io
import fits
11 import lsst.pex.config
as lsstConfig
15 from .
import makeFakeGalaxy
as makeFake
19 galList = lsstConfig.Field(dtype=str,
20 doc=
"catalog of galaxies to add")
21 maxMargin = lsstConfig.Field(dtype=int, default=600,
24 seed = lsstConfig.Field(dtype=int, default=1,
25 doc=
"Seed for random number generator")
26 addShear = lsstConfig.Field(dtype=bool, default=
False,
27 doc=
'include shear in the galaxies')
28 addMask = lsstConfig.Field(dtype=bool, default=
False,
29 doc=
'add FAKE mask plane')
30 sersic_prec = lsstConfig.Field(dtype=float, default=0.0,
31 doc=
'The desired precision for n')
32 cosStr =
'Use Galsim.COSMOSlog()'
33 serStr =
'Single sersic galaxies added'
34 dSerStr =
'Double sersic galaxies added'
35 realStr =
'Real HST galaxy images added'
36 galType = lsstConfig.ChoiceField(dtype=str, default=
'sersic',
37 allowed={
'dsersic': dSerStr,
41 doc=
'type of GalSim galaxies to add')
42 exclusionLevel = lsstConfig.ChoiceField(dtype=str, default=
'none',
43 allowed={
'none':
"None",
44 'marginal':
"Marginal",
45 'bad_stamp':
"Bad Stamp",
46 'bad_fits':
"Bad Fits"},
47 doc=
'Exclusion level')
51 ConfigClass = PositionGalSimFakesConfig
54 BaseFakeSourcesTask.__init__(self, **kwargs)
55 print(
"RNG seed:", self.
config.seed)
60 def run(self, exposure, background):
61 self.
log.
info(
"Adding fake galaxies at real positions")
62 PARENT = lsst.afw.image.PARENT
63 psf = exposure.getPsf()
64 md = exposure.getMetadata()
65 calib = exposure.getCalib()
66 expBBox = exposure.getBBox(PARENT)
67 wcs = exposure.getWcs()
69 """Deal with the skipped ones."""
70 skipLog =
'runAddFake.skipped'
71 if not os.path.isfile(skipLog):
72 os.system(
'touch ' + skipLog)
74 if self.
config.galType ==
'cosmos':
76 exLevel = self.
config.exclusionLevel
77 cosmosCat = galsim.COSMOSCatalog(exclusion_level=exLevel)
81 for igal, gal
in enumerate(self.
galData):
88 flux = calib.getFlux(float(gal[
'mag']))
90 raise KeyError(
"No mag column in %s" % self.
config.galList)
93 galCoord = lsst.afw.geom.SpherePoint(gal[
'RA'], gal[
'DEC'], lsst.afw.geom.degrees)
95 raise KeyError(
"No RA/DEC column in {} table".
format(self.
config.galList))
97 skyToPixelMatrix = wcs.linearizeSkyToPixel(galCoord, lsst.afw.geom.degrees)
98 skyToPixelMatrix = skyToPixelMatrix.getLinear().getParameterVector() / 3600.0
100 galXY = wcs.skyToPixel(galCoord)
101 bboxI = exposure.getBBox(PARENT)
102 bboxI.grow(self.
config.maxMargin)
103 if not bboxI.contains(lsst.afw.geom.Point2I(galXY)):
109 self.
log.
info(
"Mag <= 0: Skipping %d" % galident)
110 self.
log.
info(
" mag: %7.3d" % gal[
'mag'])
111 with open(skipLog,
"a")
as slog:
113 fcntl.flock(slog, fcntl.LOCK_EX)
114 slog.write(
"%8d , negMag\n" % galident)
115 fcntl.flock(slog, fcntl.LOCK_UN)
124 psfImage = psf.computeKernelImage(galXY)
130 addShear = self.
config.addShear
131 prec = self.
config.sersic_prec
132 galType = self.
config.galType
133 if self.
config.galType !=
'cosmos':
134 galArray = makeFake.makeGalaxy(flux, gal,
140 transform=skyToPixelMatrix)
142 galArray = makeFake.makeGalaxy(flux, gal,
149 transform=skyToPixelMatrix)
150 except IndexError
as ierr:
151 self.
log.
info(
"GalSim Index Error: Skipping %d" % galident)
153 with open(skipLog,
"a")
as slog:
155 fcntl.flock(slog, fcntl.LOCK_EX)
156 slog.write(
"%8d , galsimI\n" % galident)
157 fcntl.flock(slog, fcntl.LOCK_UN)
161 except KeyError
as kerr:
162 self.
log.
info(
"GalSim Key Error: Skipping %d" % galident)
164 with open(skipLog,
"a")
as slog:
166 fcntl.flock(slog, fcntl.LOCK_EX)
167 slog.write(
"%8d , galsimK\n" % galident)
168 fcntl.flock(slog, fcntl.LOCK_UN)
172 except ValueError
as verr:
173 self.
log.
info(
"GalSim Value Error: Skipping %d" % galident)
175 with open(skipLog,
"a")
as slog:
177 fcntl.flock(slog, fcntl.LOCK_EX)
178 slog.write(
"%8d , galsimV\n" % galident)
179 fcntl.flock(slog, fcntl.LOCK_UN)
183 except RuntimeError
as rerr:
184 self.
log.
info(
"GalSim Runtime Error: Skipping %d" % galident)
186 with open(skipLog,
"a")
as slog:
188 fcntl.flock(slog, fcntl.LOCK_EX)
189 slog.write(
"%8d , galsimR\n" % galident)
190 fcntl.flock(slog, fcntl.LOCK_UN)
194 except Exception
as uerr:
195 self.
log.
info(
"Unexpected Error: Skipping %d" % galident)
197 with open(skipLog,
"a")
as slog:
199 fcntl.flock(slog, fcntl.LOCK_EX)
200 slog.write(
"%8d , Unexpected\n" % galident)
201 fcntl.flock(slog, fcntl.LOCK_UN)
206 galImage = lsst.afw.image.ImageF(galArray.astype(np.float32))
207 galBBox = galImage.getBBox(PARENT)
208 galX0 = (galXY.getX() - galBBox.getWidth()/2.0 + 0.5)
209 galY0 = (galXY.getY() - galBBox.getHeight()/2.0 + 0.5)
213 galBBox = galImage.getBBox(PARENT)
216 parentBox = galImage.getBBox(PARENT)
217 if expBBox.contains(parentBox)
is False:
218 newBBox = galImage.getBBox(PARENT)
219 newBBox.clip(expBBox)
220 if newBBox.getArea() <= 0:
221 self.
log.
info(
"BBoxEdge Error: Skipping %d" % galident)
222 with open(skipLog,
"a")
as slog:
224 fcntl.flock(slog, fcntl.LOCK_EX)
225 slog.write(
"%8d , bboxEdge\n" % galident)
226 fcntl.flock(slog, fcntl.LOCK_UN)
230 self.
log.
info(
"Cropping FAKE%d from %s to %s" % (galident,
231 str(galBBox), str(newBBox)))
232 galImage = galImage.Factory(galImage, newBBox,
236 galMaskedImage = lsst.afw.image.MaskedImageF(galImage)
239 md.set(
"FAKE%s" % str(galident),
"%.3f, %.3f" % (galXY.getX(),
241 self.
log.
info(
"Adding fake %s at: %.1f,%.1f" % (str(galident),
246 if not self.
config.addMask:
248 galMaskedImage.getMask().removeAndClearMaskPlane(
'FAKE',
253 galMaskedImage.getMask().removeAndClearMaskPlane(
'CROSSTALK',
258 galMaskedImage.getMask().removeAndClearMaskPlane(
'UNMASKEDNAN',
263 maskedImage = exposure.getMaskedImage()
265 maskedImage.getMask().removeAndClearMaskPlane(
'CROSSTALK',
270 maskedImage.getMask().removeAndClearMaskPlane(
'UNMASKEDNAN',
274 if not self.
config.addMask:
276 maskedImage.getMask().removeAndClearMaskPlane(
'FAKE',
True)
280 BBox = galMaskedImage.getBBox(PARENT)
281 subMaskedImage = maskedImage.Factory(exposure.getMaskedImage(),
284 subMaskedImage += galMaskedImage
288 galMaskedImage.getMask().set(self.bitmask)
290 maskedImage = exposure.getMaskedImage()
292 maskedImage.getMask().removeAndClearMaskPlane('CROSSTALK',
297 maskedImage.getMask().removeAndClearMaskPlane('UNMASKEDNAN',
302 maskedImage.getMask().removeAndClearMaskPlane('FAKE', True)