lsst.meas.algorithms  14.0-18-gf7dca964+5
skyObjects.py
Go to the documentation of this file.
1 from __future__ import absolute_import, division, print_function
2 
3 __all__ = ["SkyObjectsConfig", "SkyObjectsTask", "generateSkyObjects"]
4 
5 from lsst.pex.config import Config, Field, ListField
6 from lsst.pipe.base import Task
7 
9 import lsst.afw.geom
10 import lsst.afw.math
11 
12 
13 class SkyObjectsConfig(Config):
14  """Configuration for generating sky objects"""
15  avoidMask = ListField(dtype=str, default=["DETECTED", "DETECTED_NEGATIVE", "BAD", "NO_DATA"],
16  doc="Avoid pixels masked with these mask planes")
17  growMask = Field(dtype=int, default=0,
18  doc="Number of pixels to grow the masked pixels when adding sky objects")
19  sourceRadius = Field(dtype=float, default=8, doc="Radius, in pixels, of sky objects")
20  nSources = Field(dtype=int, default=100, doc="Try to add this many sky objects")
21  nTrialSources = Field(dtype=int, default=None, optional=True,
22  doc="Maximum number of trial sky object positions\n"
23  "(default: nSkySources*nTrialSkySourcesMultiplier)")
24  nTrialSourcesMultiplier = Field(dtype=int, default=5,
25  doc="Set nTrialSkySources to\n"
26  " nSkySources*nTrialSkySourcesMultiplier\n"
27  "if nTrialSkySources is None")
28 
29 
30 def generateSkyObjects(mask, seed, config):
31  """Generate a list of Footprints of sky objects
32 
33  Sky objects don't overlap with other objects. This is determined
34  through the provided `mask` (in which objects are typically flagged
35  as `DETECTED`).
36 
37  The algorithm for determining sky objects is random trial and error:
38  we try up to `nTrialSkySources` random positions to find `nSources`
39  sky objects.
40 
41  Parameters
42  ----------
43  mask : `lsst.afw.image.Mask`
44  Input mask plane, which identifies pixels to avoid for the sky
45  objects.
46  seed : `int`
47  Random number generator seed.
48  config : `SkyObjectsConfig`
49  Configuration for finding sky objects.
50 
51  Returns
52  -------
53  skyFootprints : `list` of `lsst.afw.detection.Footprint`
54  Footprints of sky objects. Each will have a peak at the center
55  of the sky object.
56  """
57  if config.nSources <= 0:
58  return []
59 
60  skySourceRadius = config.sourceRadius
61  nSkySources = config.nSources
62  nTrialSkySources = config.nTrialSources
63  if nTrialSkySources is None:
64  nTrialSkySources = config.nTrialSourcesMultiplier*nSkySources
65 
66  box = mask.getBBox()
67  box.grow(-(int(skySourceRadius) + 1)) # Avoid objects partially off the image
68  xMin, yMin = box.getMin()
69  xMax, yMax = box.getMax()
70 
71  avoid = lsst.afw.geom.SpanSet.fromMask(mask, mask.getPlaneBitMask(config.avoidMask))
72  if config.growMask > 0:
73  avoid = avoid.dilated(config.growMask)
74 
75  rng = lsst.afw.math.Random(seed=seed)
76 
77  skyFootprints = []
78  for _ in range(nTrialSkySources):
79  if len(skyFootprints) == nSkySources:
80  break
81 
82  x = int(rng.flat(xMin, xMax))
83  y = int(rng.flat(yMin, yMax))
84  spans = lsst.afw.geom.SpanSet.fromShape(int(skySourceRadius), offset=(x, y))
85  if spans.overlaps(avoid):
86  continue
87 
88  fp = lsst.afw.detection.Footprint(spans, mask.getBBox())
89  fp.addPeak(x, y, 0)
90  skyFootprints.append(fp)
91 
92  return skyFootprints
93 
94 
95 class SkyObjectsTask(Task):
96  ConfigClass = SkyObjectsConfig
97 
98  def run(self, mask, seed):
99  """Generate a list of Footprints of sky objects
100 
101  Sky objects don't overlap with other objects. This is determined
102  through the provided `mask` (in which objects are typically flagged
103  as `DETECTED`).
104 
105  The algorithm for determining sky objects is random trial and error:
106  we try up to `nTrialSkySources` random positions to find `nSources`
107  sky objects.
108 
109  Parameters
110  ----------
111  mask : `lsst.afw.image.Mask`
112  Input mask plane, which identifies pixels to avoid for the sky
113  objects.
114  seed : `int`
115  Random number generator seed.
116 
117  Returns
118  -------
119  skyFootprints : `list` of `lsst.afw.detection.Footprint`
120  Footprints of sky objects. Each will have a peak at the center
121  of the sky object.
122  """
123  skyFootprints = generateSkyObjects(mask, seed, self.config)
124  self.log.info("Added %d of %d requested sky sources (%.0f%%)", len(skyFootprints),
125  self.config.nSources, 100*len(skyFootprints)/self.config.nSources)
126  return skyFootprints
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, Point2I offset=Point2I())
static std::shared_ptr< geom::SpanSet > fromMask(image::Mask< T > const &mask, UnaryPredicate comparator=details::AnyBitSetFunctor< T >())
def generateSkyObjects(mask, seed, config)
Definition: skyObjects.py:30