72 """Generate a list of Footprints of sky objects
74 Sky objects don't overlap with other objects. This is determined
75 through the provided `mask` (in which objects are typically flagged
78 Sky objects are positioned using a quasi-random Halton sequence number
79 generator. This is a deterministic sequence that mimics a random trial and
80 error approach whilst acting to minimize clustering of points for a given
81 field of view. Up to `nTrialSources` points are generated, returning the
82 first `nSources` that do not overlap with the mask.
86 mask : `lsst.afw.image.Mask`
87 Input mask plane, which identifies pixels to avoid for the sky
90 Random number generator seed.
91 config : `SkyObjectsConfig`
92 Configuration for finding sky objects.
96 skyFootprints : `list` of `lsst.afw.detection.Footprint`
97 Footprints of sky objects. Each will have a peak at the center
100 if config.nSources <= 0:
103 skySourceRadius = config.sourceRadius
104 nSkySources = config.nSources
105 nTrialSkySources = config.nTrialSources
106 if nTrialSkySources
is None:
107 nTrialSkySources = config.nTrialSourcesMultiplier*nSkySources
110 box.grow(-(int(skySourceRadius) + 1))
111 xMin, yMin = box.getMin()
112 xMax, yMax = box.getMax()
115 if config.growMask > 0:
116 avoid = avoid.dilated(config.growMask)
118 sampler = qmc.Halton(d=2, seed=seed).random(nTrialSkySources)
119 sample = qmc.scale(sampler, [xMin, yMin], [xMax, yMax])
122 for x, y
in zip(sample[:, 0].astype(int), sample[:, 1].astype(int)):
123 if len(skyFootprints) == nSkySources:
127 if spans.overlaps(avoid):
132 skyFootprints.append(fp)
135 avoid = avoid.union(spans.dilated(int(skySourceRadius)))