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)