lsst.synpipe  15.0-4-g9ee0f43+9
positionStarFakes.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # encoding: utf-8
3 
4 from __future__ import print_function
5 from __future__ import absolute_import
6 from builtins import str
7 import numpy as np
8 
9 import pyfits as fits
10 
11 import lsst.afw.geom as afwGeom
12 import lsst.afw.math as afwMath
13 import lsst.afw.image as afwImage
14 import lsst.pex.config as afwConfig
15 
16 from lsst.pipe.tasks.fakes import BaseFakeSourcesConfig, BaseFakeSourcesTask
17 from lsst.pex.exceptions import InvalidParameterError
18 
19 from . import FakeSourceLib as fsl
20 
21 
22 class PositionStarFakesConfig(BaseFakeSourcesConfig):
23  starList = afwConfig.Field(dtype=str,
24  doc="Catalog of stars with mags ra/dec")
25  seed = afwConfig.Field(dtype=int, default=1,
26  doc="Seed for random number generator")
27 
28 
29 class PositionStarFakesTask(BaseFakeSourcesTask):
30  ConfigClass = PositionStarFakesConfig
31 
32  def __init__(self, **kwargs):
33  BaseFakeSourcesTask.__init__(self, **kwargs)
34  print("RNG seed:", self.config.seed)
35  self.rng = afwMath.Random(seed=self.config.seed)
36  self.npRand = np.random.RandomState(self.config.seed)
37  try:
38  self.starData = fits.open(self.config.starList)[1].data
39  except Exception:
40  raise
41 
42  def run(self, exposure, background):
43 
44  self.log.info("Adding fake stars at real positions")
45  psf = exposure.getPsf()
46  psfBBox = psf.computeImage().getBBox()
47  margin = max(psfBBox.getWidth(), psfBBox.getHeight())/2 + 1
48 
49  PARENT = afwImage.PARENT
50  md = exposure.getMetadata()
51  expBBox = exposure.getBBox(PARENT)
52  wcs = exposure.getWcs()
53 
54  for istar, star in enumerate(self.starData):
55  try:
56  starident = star["ID"]
57  except KeyError:
58  starident = istar + 1
59 
60  try:
61  flux = exposure.getCalib().getFlux(float(star['mag']))
62  except KeyError:
63  raise KeyError("No mag column in %s" % self.config.starList)
64 
65  try:
66  starCoord = afwGeom.SpherePoint(star['RA'], star['DEC'], afwGeom.degrees)
67  except KeyError:
68  raise KeyError("No RA/DEC column in table".format(self.config.starList))
69 
70  starXY = wcs.skyToPixel(starCoord)
71  bboxI = exposure.getBBox(PARENT)
72  bboxI.grow(int(margin))
73  if not bboxI.contains(afwGeom.Point2I(starXY)):
74  continue
75 
76  try:
77  starImage = psf.computeImage(starXY)
78  except InvalidParameterError:
79  # This means an image was computed in an area where there was no data
80  # continue on to the next star. This is most likely to occur when inserting
81  # into coadds
82  logmsg = "Skipping fake {} because no input images present at point {}"
83  self.log.info(logmsg.format(starident, starXY))
84  continue
85 
86  starImage *= flux
87  starBBox = starImage.getBBox(PARENT)
88 
89  # Check that we're within the larger exposure, otherwise crop
90  if expBBox.contains(starBBox) is False:
91  newBBox = starImage.getBBox(PARENT)
92  newBBox.clip(expBBox)
93  if newBBox.getArea() <= 0:
94  self.log.info("Skipping fake %d" % starident)
95  continue
96  self.log.info("Cropping FAKE%d from %s to %s" % (starident,
97  str(starBBox), str(newBBox)))
98  starImage = starImage.Factory(starImage, newBBox, PARENT)
99  starBBox = newBBox
100 
101  starMaskedImage = afwImage.MaskedImageF(starImage.convertF())
102 
103  starMaskedImage.getMask().set(self.bitmask)
104 
105  md.set("FAKE%s" % str(starident), "%.3f, %.3f" % (starXY.getX(),
106  starXY.getY()))
107  self.log.info("Adding fake %s at: %.1f,%.1f" % (str(starident),
108  starXY.getX(),
109  starXY.getY()))
110 
111  maskedImage = exposure.getMaskedImage()
112  BBox = starMaskedImage.getBBox(PARENT)
113  subMaskedImage = maskedImage.Factory(exposure.getMaskedImage(),
114  BBox,
115  PARENT)
116  subMaskedImage += starMaskedImage