2 __all__ = [
"matchOptimisticB",
"MatchOptimisticBTask",
"MatchOptimisticBConfig",
11 from ..setMatchDistance
import setMatchDistance
12 from .
import matchOptimisticB, MatchOptimisticBControl
16 """Stores match tolerances for use in `lsst.meas.astrom.AstrometryTask` and 17 later iterations of the matcher. 19 MatchOptimsiticBTask relies on a maximum distance for matching 20 set by either the default in MatchOptimisticBConfig or the 2 sigma 21 scatter found after AstrometryTask has fit for a wcs. 25 maxMatchDist : `lsst.geom.Angle` 26 Current maximum distance to consider a match. 34 """Configuration for MatchOptimisticBTask 36 maxMatchDistArcSec = pexConfig.RangeField(
37 doc=
"Maximum separation between reference objects and sources " 38 "beyond which they will not be considered a match (arcsec)",
43 numBrightStars = pexConfig.RangeField(
44 doc=
"Number of bright stars to use",
49 minMatchedPairs = pexConfig.RangeField(
50 doc=
"Minimum number of matched pairs; see also minFracMatchedPairs",
55 minFracMatchedPairs = pexConfig.RangeField(
56 doc=
"Minimum number of matched pairs as a fraction of the smaller of " 57 "the number of reference stars or the number of good sources; " 58 "the actual minimum is the smaller of this value or minMatchedPairs",
64 maxOffsetPix = pexConfig.RangeField(
65 doc=
"Maximum allowed shift of WCS, due to matching (pixel). " 66 "When changing this value, the LoadReferenceObjectsConfig.pixelMargin should also be updated.",
71 maxRotationDeg = pexConfig.RangeField(
72 doc=
"Rotation angle allowed between sources and position reference objects (degrees)",
77 allowedNonperpDeg = pexConfig.RangeField(
78 doc=
"Allowed non-perpendicularity of x and y (degree)",
83 numPointsForShape = pexConfig.Field(
84 doc=
"number of points to define a shape for matching",
88 maxDeterminant = pexConfig.Field(
89 doc=
"maximum determinant of linear transformation matrix for a usable solution",
93 sourceSelector = sourceSelectorRegistry.makeField(
94 doc=
"How to select sources for cross-matching",
100 sourceSelector.setDefaults()
113 """Match sources to reference objects using the Optimistic Pattern Matcher 114 B algorithm of Tabur 2007. 116 ConfigClass = MatchOptimisticBConfig
117 _DefaultName =
"matchObjectsToSources" 120 pipeBase.Task.__init__(self, **kwargs)
121 self.makeSubtask(
"sourceSelector")
124 """Extra filtering pass; subclass if desired. 128 refCat : `lsst.afw.table.SimpleCatalog` 129 Catalog of reference objects. 133 trimmedRefCat : `lsst.afw.table.SimpleCatalog` 134 Reference catalog with some filtering applied. Currently no 135 filtering is applied. 141 match_tolerance=None):
142 """Match sources to position reference stars. 146 refCat : `lsst.afw.table.SimpleCatalog` 147 Reference catalog to match. 148 sourceCat : `lsst.afw.table.SourceCatalog` 149 Source catalog to match. 150 wcs : `lsst.afw.geom.SkyWcs` 151 Current WCS of the exposure containing the sources. 153 Name of the reference catalog filter to use. 154 match_tolerance : `lsst.meas.astrom.MatchTolerance` 155 Object containing information from previous 156 `lsst.meas.astrom.AstrometryTask` match/fit cycles for use in 157 matching. If `None` is config defaults. 161 matchResult : `lsst.pipe.base.Struct` 162 Result struct with components 164 - ``matches`` : List of matches with distance below the maximum match 165 distance (`list` of `lsst.afw.table.ReferenceMatch`). 166 - ``useableSourceCat`` : Catalog of sources matched and suited for 167 WCS fitting (`lsst.afw.table.SourceCatalog`). 168 - ``match_tolerance`` : MatchTolerance object updated from this 169 match iteration (`lsst.meas.astrom.MatchTolerance`). 174 preNumObj = len(refCat)
176 numRefObj = len(refCat)
179 self.log.
info(
"filterStars purged %d reference stars, leaving %d stars" %
180 (preNumObj - numRefObj, numRefObj))
182 if match_tolerance
is None:
186 numSources = len(sourceCat)
187 selectedSources = self.sourceSelector.
run(sourceCat)
188 usableSourceCat = selectedSources.sourceCat
189 numUsableSources = len(usableSourceCat)
190 self.log.
info(
"Purged %d unusable sources, leaving %d usable sources" %
191 (numSources - numUsableSources, numUsableSources))
193 if len(usableSourceCat) == 0:
194 raise pipeBase.TaskError(
"No sources are usable")
198 minMatchedPairs =
min(self.config.minMatchedPairs,
199 int(self.config.minFracMatchedPairs *
min([len(refCat), len(usableSourceCat)])))
204 sourceCat=usableSourceCat,
206 refFluxField=refFluxField,
207 numUsableSources=numUsableSources,
208 minMatchedPairs=minMatchedPairs,
209 maxMatchDist=match_tolerance.maxMatchDist,
210 sourceFluxField=self.sourceSelector.fluxField,
211 verbose=debug.verbose,
217 for match
in usableMatches:
220 matches.append(match)
222 self.log.
debug(
"Found %d usable matches, of which %d had good sources",
223 len(usableMatches), len(matches))
225 if len(matches) == 0:
226 raise RuntimeError(
"Unable to match sources")
228 self.log.
info(
"Matched %d sources" % len(matches))
229 if len(matches) < minMatchedPairs:
230 self.log.
warn(
"Number of matches is smaller than request")
232 return pipeBase.Struct(
234 usableSourceCat=usableSourceCat,
235 match_tolerance=match_tolerance,
238 def _getIsGoodKeys(self, schema):
239 """Retrieve the keys needed for the isGoodTest from the source catalog 244 schema : `lsst.afw.table.Schema` 245 Source schema to retrieve `lsst.afw.table.Key` s from. 247 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
251 def _isGoodTest(self, source):
252 """Test that an object is good for use in the WCS fitter. 254 This is a hard coded version of the isGood flag from the old SourceInfo 255 class that used to be part of this class. 259 source : `lsst.afw.table.SourceRecord` 265 Source passes CCD edge and saturated tests. 267 return (
not source.get(self.
edgeKey)
and 272 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs,
273 maxMatchDist, sourceFluxField, verbose):
274 """Implementation of matching sources to position reference stars. 276 Unlike matchObjectsToSources, this method does not check if the sources 281 refCat : `lsst.afw.table.SimpleCatalog` 282 Catalog of reference objects. 283 sourceCat : `lsst.afw.table.SourceCatalog` 284 Catalog of detected sources. 285 wcs : `lsst.afw.geom.SkyWcs` 286 Current best WCS of the image. 287 refFluxFioeld : `str` 288 Name of flux field in refCat to use. 289 numUsableSources : `int` 290 Total number of source usable for matching. 291 mintMatchPairs : `int` 292 Minimum number of objects to match between the refCat and sourceCat 293 to consider a valid match. 294 maxMatchDist : `lsst.geom.Angle` 295 Maximum separation to considering a reference and a source a match. 296 sourceFluxField : `str` 297 Name of source catalog flux field. 299 Print diagnostic information std::cout 303 matches : `list` of `lsst.afw.table.ReferenceMatch` 305 numSources = len(sourceCat)
306 posRefBegInd = numUsableSources - numSources
307 if maxMatchDist
is None:
308 maxMatchDistArcSec = self.config.maxMatchDistArcSec
310 maxMatchDistArcSec =
min(maxMatchDist.asArcseconds(), self.config.maxMatchDistArcSec)
311 configMatchDistPix = maxMatchDistArcSec/wcs.getPixelScale().asArcseconds()
313 matchControl = MatchOptimisticBControl()
314 matchControl.refFluxField = refFluxField
315 matchControl.sourceFluxField = sourceFluxField
316 matchControl.numBrightStars = self.config.numBrightStars
317 matchControl.minMatchedPairs = self.config.minMatchedPairs
318 matchControl.maxOffsetPix = self.config.maxOffsetPix
319 matchControl.numPointsForShape = self.config.numPointsForShape
320 matchControl.maxDeterminant = self.config.maxDeterminant
322 for maxRotInd
in range(4):
323 matchControl.maxRotationDeg = self.config.maxRotationDeg * math.pow(2.0, 0.5*maxRotInd)
324 for matchRadInd
in range(3):
325 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
327 for angleDiffInd
in range(3):
328 matchControl.allowedNonperpDeg = self.config.allowedNonperpDeg*(angleDiffInd+1)
337 if matches
is not None and len(matches) > 0:
def _isGoodTest(self, source)
afw::table::ReferenceMatchVector matchOptimisticB(afw::table::SimpleCatalog const &posRefCat, afw::table::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, afw::geom::SkyWcs const &wcs, int posRefBegInd=0, bool verbose=false)
Match sources to stars in a position reference catalog using optimistic pattern matching B...
def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs, maxMatchDist, sourceFluxField, verbose)
def filterStars(self, refCat)
def __init__(self, kwargs)
def setMatchDistance(matches)
def __init__(self, maxMatchDist=None)
def matchObjectsToSources(self, refCat, sourceCat, wcs, refFluxField, match_tolerance=None)
def _getIsGoodKeys(self, schema)