132 match_tolerance=None):
133 """Match sources to position reference stars.
137 refCat : `lsst.afw.table.SimpleCatalog`
138 Reference catalog to match.
139 sourceCat : `lsst.afw.table.SourceCatalog`
140 Catalog of sources found on an exposure. This should already be
141 down-selected to "good"/"usable" sources in the calling Task.
142 wcs : `lsst.afw.geom.SkyWcs`
143 Current WCS of the exposure containing the sources.
144 sourceFluxField : `str`
145 Field of the sourceCat to use for flux
147 Field of the refCat to use for flux
148 match_tolerance : `lsst.meas.astrom.MatchTolerance`
149 Object containing information from previous
150 `lsst.meas.astrom.AstrometryTask` match/fit cycles for use in
151 matching. If `None` is config defaults.
155 matchResult : `lsst.pipe.base.Struct`
156 Result struct with components
158 - ``matches`` : List of matches with distance below the maximum match
159 distance (`list` of `lsst.afw.table.ReferenceMatch`).
160 - ``useableSourceCat`` : Catalog of sources matched and suited for
161 WCS fitting (`lsst.afw.table.SourceCatalog`).
162 - ``match_tolerance`` : MatchTolerance object updated from this
163 match iteration (`lsst.meas.astrom.MatchTolerance`).
168 preNumObj = len(refCat)
170 numRefObj = len(refCat)
173 self.log.info(
"filterStars purged %d reference stars, leaving %d stars",
174 preNumObj - numRefObj, numRefObj)
176 if match_tolerance
is None:
181 usableSourceCat = sourceCat
183 numUsableSources = len(usableSourceCat)
185 if len(usableSourceCat) == 0:
186 raise pipeBase.TaskError(
"No sources are usable")
188 minMatchedPairs = min(self.config.minMatchedPairs,
189 int(self.config.minFracMatchedPairs * min([len(refCat), len(usableSourceCat)])))
194 sourceCat=usableSourceCat,
196 refFluxField=refFluxField,
197 numUsableSources=numUsableSources,
198 minMatchedPairs=minMatchedPairs,
199 maxMatchDist=match_tolerance.maxMatchDist,
200 sourceFluxField=sourceFluxField,
201 verbose=debug.verbose,
207 for match
in usableMatches:
210 matches.append(match)
212 self.log.debug(
"Found %d usable matches, of which %d had good sources",
213 len(usableMatches), len(matches))
215 if len(matches) == 0:
216 raise RuntimeError(
"Unable to match sources")
218 self.log.info(
"Matched %d sources", len(matches))
219 if len(matches) < minMatchedPairs:
220 self.log.warning(
"Number of matches is smaller than request")
222 return pipeBase.Struct(
224 usableSourceCat=usableSourceCat,
225 match_tolerance=match_tolerance,
262 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs,
263 maxMatchDist, sourceFluxField, verbose):
264 """Implementation of matching sources to position reference stars.
266 Unlike matchObjectsToSources, this method does not check if the sources
271 refCat : `lsst.afw.table.SimpleCatalog`
272 Catalog of reference objects.
273 sourceCat : `lsst.afw.table.SourceCatalog`
274 Catalog of detected sources.
275 wcs : `lsst.afw.geom.SkyWcs`
276 Current best WCS of the image.
277 refFluxFioeld : `str`
278 Name of flux field in refCat to use.
279 numUsableSources : `int`
280 Total number of source usable for matching.
281 mintMatchPairs : `int`
282 Minimum number of objects to match between the refCat and sourceCat
283 to consider a valid match.
284 maxMatchDist : `lsst.geom.Angle`
285 Maximum separation to considering a reference and a source a match.
286 sourceFluxField : `str`
287 Name of source catalog flux field.
289 Print diagnostic information std::cout
293 matches : `list` of `lsst.afw.table.ReferenceMatch`
295 numSources = len(sourceCat)
296 posRefBegInd = numUsableSources - numSources
297 if maxMatchDist
is None:
298 maxMatchDistArcSec = self.config.maxMatchDistArcSec
300 maxMatchDistArcSec = min(maxMatchDist.asArcseconds(), self.config.maxMatchDistArcSec)
301 configMatchDistPix = maxMatchDistArcSec/wcs.getPixelScale().asArcseconds()
303 matchControl = MatchOptimisticBControl()
304 matchControl.refFluxField = refFluxField
305 matchControl.sourceFluxField = sourceFluxField
306 matchControl.numBrightStars = self.config.numBrightStars
307 matchControl.minMatchedPairs = self.config.minMatchedPairs
308 matchControl.maxOffsetPix = self.config.maxOffsetPix
309 matchControl.numPointsForShape = self.config.numPointsForShape
310 matchControl.maxDeterminant = self.config.maxDeterminant
312 for maxRotInd
in range(4):
313 matchControl.maxRotationDeg = self.config.maxRotationDeg * math.pow(2.0, 0.5*maxRotInd)
314 for matchRadInd
in range(3):
315 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
317 for angleDiffInd
in range(3):
318 matchControl.allowedNonperpDeg = self.config.allowedNonperpDeg*(angleDiffInd+1)
319 matches = matchOptimisticB(
327 if matches
is not None and len(matches) > 0:
328 setMatchDistance(matches)