2 __all__ = [
"SkyObjectsConfig", 
"SkyObjectsTask", 
"generateSkyObjects"]
 
    4 from lsst.pex.config 
import Config, Field, ListField
 
   13     """Configuration for generating sky objects""" 
   14     avoidMask = ListField(dtype=str, default=[
"DETECTED", 
"DETECTED_NEGATIVE", 
"BAD", 
"NO_DATA"],
 
   15                           doc=
"Avoid pixels masked with these mask planes")
 
   16     growMask = Field(dtype=int, default=0,
 
   17                      doc=
"Number of pixels to grow the masked pixels when adding sky objects")
 
   18     sourceRadius = Field(dtype=float, default=8, doc=
"Radius, in pixels, of sky objects")
 
   19     nSources = Field(dtype=int, default=100, doc=
"Try to add this many sky objects")
 
   20     nTrialSources = Field(dtype=int, default=
None, optional=
True,
 
   21                           doc=
"Maximum number of trial sky object positions\n" 
   22                               "(default: nSkySources*nTrialSkySourcesMultiplier)")
 
   23     nTrialSourcesMultiplier = Field(dtype=int, default=5,
 
   24                                     doc=
"Set nTrialSkySources to\n" 
   25                                         "    nSkySources*nTrialSkySourcesMultiplier\n" 
   26                                         "if nTrialSkySources is None")
 
   30     """Generate a list of Footprints of sky objects 
   32     Sky objects don't overlap with other objects. This is determined 
   33     through the provided `mask` (in which objects are typically flagged 
   36     The algorithm for determining sky objects is random trial and error: 
   37     we try up to `nTrialSkySources` random positions to find `nSources` 
   42     mask : `lsst.afw.image.Mask` 
   43         Input mask plane, which identifies pixels to avoid for the sky 
   46         Random number generator seed. 
   47     config : `SkyObjectsConfig` 
   48         Configuration for finding sky objects. 
   52     skyFootprints : `list` of `lsst.afw.detection.Footprint` 
   53         Footprints of sky objects. Each will have a peak at the center 
   56     if config.nSources <= 0:
 
   59     skySourceRadius = config.sourceRadius
 
   60     nSkySources = config.nSources
 
   61     nTrialSkySources = config.nTrialSources
 
   62     if nTrialSkySources 
is None:
 
   63         nTrialSkySources = config.nTrialSourcesMultiplier*nSkySources
 
   66     box.grow(-(int(skySourceRadius) + 1))  
 
   67     xMin, yMin = box.getMin()
 
   68     xMax, yMax = box.getMax()
 
   71     if config.growMask > 0:
 
   72         avoid = avoid.dilated(config.growMask)
 
   77     for _ 
in range(nTrialSkySources):
 
   78         if len(skyFootprints) == nSkySources:
 
   81         x = int(rng.flat(xMin, xMax))
 
   82         y = int(rng.flat(yMin, yMax))
 
   84         if spans.overlaps(avoid):
 
   89         skyFootprints.append(fp)
 
   95     ConfigClass = SkyObjectsConfig
 
   97     def run(self, mask, seed):
 
   98         """Generate a list of Footprints of sky objects 
  100         Sky objects don't overlap with other objects. This is determined 
  101         through the provided `mask` (in which objects are typically flagged 
  104         The algorithm for determining sky objects is random trial and error: 
  105         we try up to `nTrialSkySources` random positions to find `nSources` 
  110         mask : `lsst.afw.image.Mask` 
  111             Input mask plane, which identifies pixels to avoid for the sky 
  114             Random number generator seed. 
  118         skyFootprints : `list` of `lsst.afw.detection.Footprint` 
  119             Footprints of sky objects. Each will have a peak at the center 
  123         self.
log.
info(
"Added %d of %d requested sky sources (%.0f%%)", len(skyFootprints),
 
  124                       self.
config.nSources, 100*len(skyFootprints)/self.
config.nSources)