lsst.synpipe  15.0-3-g11fe1a0+9
randomGalSimFakes.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from builtins import zip
3 from builtins import str
4 from builtins import range
5 import numpy as np
6 
7 import lsst.afw.image
8 import lsst.afw.geom
9 import lsst.afw.math
11 import lsst.pex.config
12 from lsst.pipe.tasks.fakes import BaseFakeSourcesConfig, BaseFakeSourcesTask
13 import pyfits as fits
14 
15 import lsst.synpipe.makeFakeGalaxy as makeFake
16 import lsst.synpipe.FakeSourceLib as fsl
17 
18 
19 class RandomGalSimFakesConfig(BaseFakeSourcesConfig):
20  galList = lsst.pex.config.Field(dtype=str, doc="catalog of galaxies to add")
21  margin = lsst.pex.config.Field(dtype=int, default=None, optional=True,
22  doc="Size of margin at edge that should not be added")
23  seed = lsst.pex.config.Field(dtype=int, default=1,
24  doc="Seed for random number generator")
25  galType = lsst.pex.config.ChoiceField(dtype=str, default='sersic',
26  allowed={'dsersic': 'double sersic galaxies added',
27  'sersic': 'single sersic galaxies added',
28  'real': 'real HST galaxy images added'},
29  doc='type of GalSim galaxies to add')
30  nGal = lsst.pex.config.Field(dtype=int, doc="""number of galaxies to add, if 0, then everything in catalog,
31  otherwise a random subset of nGal from the catalog""", default=0)
32 
33 
34 class RandomGalSimFakesTask(BaseFakeSourcesTask):
35  ConfigClass = RandomGalSimFakesConfig
36 
37  def __init__(self, **kwargs):
38  BaseFakeSourcesTask.__init__(self, **kwargs)
39  print("RNG seed:", self.config.seed)
40  self.rng = lsst.afw.math.Random(seed=self.config.seed)
41  self.npRand = np.random.RandomState(self.config.seed)
42  self.galData = fits.open(self.config.galList)[1].data
43 
44  def run(self, exposure, background):
45 
46  self.log.info("Adding fake random galaxies")
47  psf = exposure.getPsf()
48  psfBBox = psf.computeImage().getBBox()
49  minMargin = int(np.floor(max(psfBBox.getWidth(), psfBBox.getHeight())/2)) + 1
50  md = exposure.getMetadata()
51  expBBox = exposure.getBBox()
52  scalingMatrix = np.array([[0.0, 1.0], [1.0, 0.0]]) / exposure.getWcs().pixelScale().asArcseconds()
53 
54  if self.config.nGal == 0:
55  doGal = enumerate(self.galData)
56  else:
57  inds = self.npRand.choice(list(range(len(self.galData))), size=self.config.nGal, replace=False)
58  doGal = list(zip(inds, self.galData[inds]))
59 
60  for igal, gal in doGal:
61  try:
62  galident = gal["ID"]
63  except KeyError:
64  galident = igal + 1
65 
66  try:
67  flux = exposure.getCalib().getFlux(float(gal['mag']))
68  except KeyError:
69  raise KeyError("No mag column in %s table"%self.config.galList)
70 
71  #don't put the galaxy within one PSF box of the edge
72  #or within the given pixel margin
73  if self.config.margin is not None:
74  margin = self.config.margin
75  else:
76  margin = minMargin
77  bboxI = (exposure.getBBox(lsst.afw.image.PARENT))
78  bboxI.grow(-margin)
79  bboxD = lsst.afw.geom.BoxD(bboxI)
80  x = self.rng.flat(bboxD.getMinX(), bboxD.getMaxX())
81  y = self.rng.flat(bboxD.getMinY(), bboxD.getMaxY())
82  #TODO: check for overlaps here and regenerate x,y if necessary
83 
84  psfImage = psf.computeKernelImage(lsst.afw.geom.Point2D(x, y))
85  galArray = makeFake.makeGalaxy(flux, gal, psfImage.getArray(), self.config.galType,
86  transform=scalingMatrix)
87  galImage = lsst.afw.image.ImageF(galArray.astype(np.float32))
88  galBBox = galImage.getBBox(lsst.afw.image.PARENT)
89  galImage = lsst.afw.math.offsetImage(galImage,
90  x - galBBox.getWidth()/2.0 + 0.5,
91  y - galBBox.getHeight()/2.0 + 0.5,
92  'lanczos3')
93  galBBox = galImage.getBBox(lsst.afw.image.PARENT)
94 
95  #check that we're within the larger exposure, otherwise crop
96  if expBBox.contains(galImage.getBBox(lsst.afw.image.PARENT)) is False:
97  newBBox = galImage.getBBox(lsst.afw.image.PARENT)
98  newBBox.clip(expBBox)
99  self.log.info("Cropping FAKE%d from %s to %s"%(galident, str(galBBox), str(newBBox)))
100  galImage = galImage.Factory(galImage, newBBox, lsst.afw.image.PARENT)
101  galBBox = newBBox
102 
103  galMaskedImage = lsst.afw.image.MaskedImageF(galImage)
104 
105  mask = galMaskedImage.getMask()
106  mask.set(self.bitmask)
107 
108  md.set("FAKE%d" % gal['ID'], "%.3f, %.3f" % (x, y))
109  self.log.info("Adding fake at: %.1f,%.1f" % (x, y))
110 
111  #TODO: set the mask
112  galMaskedImage.getMask().set(self.bitmask)
113  subMaskedImage = exposure.getMaskedImage().Factory(exposure.getMaskedImage(),
114  galMaskedImage.getBBox(lsst.afw.image.PARENT),
115  lsst.afw.image.PARENT)
116  subMaskedImage += galMaskedImage
std::shared_ptr< ImageT > offsetImage(ImageT const &image, float dx, float dy, std::string const &algorithmName="lanczos5", unsigned int buffer=0)