1 from __future__
import absolute_import, division, print_function
8 from .astromLib
import matchOptimisticB, MatchOptimisticBControl
10 __all__ = [
"MatchOptimisticBTask",
"MatchOptimisticBConfig"]
13 sourceFluxType = pexConfig.Field(
14 doc =
"Type of source flux; typically one of Ap or Psf",
18 maxMatchDistArcSec = pexConfig.RangeField(
19 doc =
"Maximum radius for matching sources to reference objects (arcsec)",
24 numBrightStars = pexConfig.RangeField(
25 doc =
"Number of bright stars to use",
30 minMatchedPairs = pexConfig.RangeField(
31 doc =
"Minimum number of matched pairs; see also minFracMatchedPairs",
36 minFracMatchedPairs = pexConfig.RangeField(
37 doc =
"Minimum number of matched pairs as a fraction of the smaller of "
38 "the number of reference stars or the number of good sources; "
39 "the actual minimum is the smaller of this value or minMatchedPairs",
45 maxOffsetPix = pexConfig.RangeField(
46 doc =
"Maximum offset between sources and position reference objects (pixel)",
51 rotationAllowedInRad = pexConfig.RangeField(
52 doc =
"Rotation angle allowed between sources and position reference objects (radian)",
57 angleDiffFrom90 = pexConfig.RangeField(
58 doc =
"Difference of angle between x and y from 90 degree allowed (degree)",
63 numPointsForShape = pexConfig.Field(
64 doc =
"number of points to define a shape for matching",
68 maxDeterminant = pexConfig.Field(
69 doc =
"maximum determinant of linear transformation matrix for a usable solution",
75 """Provide information about sources in a source catalog for various versions of the schema
78 - edgeKey key for field that is True if source is near an edge
79 - saturatedKey key for field that is True if source has any saturated pixels
80 - centroidKey key for centroid
81 - centroidFlagKey key for flag that is True if centroid is valid
82 - fluxField name of flux field
84 @throw RuntimeError if schema version unsupported or a needed field not found
87 """Construct a SourceInfo
89 @param[in] schema source catalog schema
90 @param[in] fluxType flux type: typically one of "Ap" or "Psf"
92 @throw RuntimeError if the flux field is not found
94 version = schema.getVersion()
96 self.
edgeKey = schema[
"flags.pixel.edge"].asKey()
102 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
103 self.
saturatedKey = schema[
"base_PixelFlags_flag_saturated"].asKey()
106 self.
fluxField =
"slot_%sFlux_flux" % (fluxType,)
108 raise RuntimeError(
"Version %r of sourceCat schema not supported" % (version,))
111 raise RuntimeError(
"Could not find flux field %s in source schema" % (self.
fluxField,))
114 """Return True if the source has a valid centroid
117 return numpy.all(numpy.isfinite(centroid))
and not source.getCentroidFlag()
120 """Return True if the source has a valid centroid and is not near the edge
125 """Return True if source is clean (as per isCleanSource) and is not saturated
139 """!Match sources to reference objects
141 @anchor MatchOptimisticBTask_
143 @section meas_astrom_matchOptimisticB_Contents Contents
145 - @ref meas_astrom_matchOptimisticB_Purpose
146 - @ref meas_astrom_matchOptimisticB_Initialize
147 - @ref meas_astrom_matchOptimisticB_IO
148 - @ref meas_astrom_matchOptimisticB_Config
149 - @ref meas_astrom_matchOptimisticB_Example
150 - @ref meas_astrom_matchOptimisticB_Debug
152 @section meas_astrom_matchOptimisticB_Purpose Description
154 Match sources to reference objects. This is often done as a preliminary step to fitting an astrometric
155 or photometric solution. For details about the matching algorithm see matchOptimisticB.h
157 @section meas_astrom_matchOptimisticB_Initialize Task initialisation
159 @copydoc \_\_init\_\_
161 @section meas_astrom_matchOptimisticB_IO Invoking the Task
163 @copydoc matchObjectsToSources
165 @section meas_astrom_matchOptimisticB_Config Configuration parameters
167 See @ref MatchOptimisticBConfig
169 @section meas_astrom_matchOptimisticB_Example A complete example of using MatchOptimisticBTask
171 MatchOptimisticBTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
172 See \ref meas_photocal_photocal_Example.
174 @section meas_astrom_matchOptimisticB_Debug Debug variables
176 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink interface supports a
177 flag @c -d to import @b debug.py from your @c PYTHONPATH; see @ref baseDebug for more about
180 The available variables in MatchOptimisticBTask are:
182 <DT> @c verbose (bool)
183 <DD> If True then the matcher prints debug messages to stdout
186 To investigate the @ref meas_astrom_matchOptimisticB_Debug, put something like
190 debug = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
191 if name == "lsst.pipe.tasks.astrometry":
196 lsstDebug.Info = DebugInfo
198 into your debug.py file and run this task with the @c --debug flag.
200 ConfigClass = MatchOptimisticBConfig
201 _DefaultName =
"matchObjectsToSources"
204 """Extra filtering pass; subclass if desired
210 """!Match sources to position reference stars
212 @param[in] refCat catalog of reference objects that overlap the exposure; reads fields for:
214 - the specified flux field
215 @param[in] sourceCat catalog of sources found on an exposure; reads fields for:
220 - aperture flux, if found, else PSF flux
221 @param[in] wcs estimated WCS
222 @param[in] refFluxField field of refCat to use for flux
223 @return an lsst.pipe.base.Struct with fields:
224 - matches a list of matches, an instance of lsst.afw.table.ReferenceMatch
229 preNumObj = len(refCat)
231 numRefObj = len(refCat)
233 if self.log: self.log.info(
"filterStars purged %d reference stars, leaving %d stars" % \
234 (preNumObj - numRefObj, numRefObj))
236 sourceInfo =
SourceInfo(schema=sourceCat.schema, fluxType=self.config.sourceFluxType)
239 numSources = len(sourceCat)
241 cleanSourceCat.extend(s
for s
in sourceCat
if sourceInfo.isCleanSource(s))
242 numCleanSources = len(cleanSourceCat)
243 self.log.info(
"Purged %d unsuable sources, leaving %d clean sources" % \
244 (numSources - numCleanSources, numCleanSources))
248 goodSources.extend(s
for s
in cleanSourceCat
if sourceInfo.isGoodSource(s))
249 numGoodSources = len(goodSources)
250 self.log.info(
"Purged %d saturated sources, leaving %d good sources" % \
251 (numCleanSources - numGoodSources, numGoodSources))
255 self.log.info(
"Matching to %d/%d good input sources" % (len(goodSources), len(cleanSourceCat)))
257 minMatchedPairs =
min(self.config.minMatchedPairs,
258 int(self.config.minFracMatchedPairs *
min([len(refCat), len(goodSources)])))
263 sourceCat = cleanSourceCat,
265 refFluxField = refFluxField,
266 numCleanSources = numCleanSources,
267 minMatchedPairs = minMatchedPairs,
268 sourceInfo = sourceInfo,
269 verbose = debug.verbose,
271 if matches0
is not None:
272 matches0 = [m
for m
in matches0
if sourceInfo.isGoodSource(m.second)]
277 if len(refCat) > len(cleanSourceCat) - len(goodSources):
280 sourceCat = goodSources,
282 refFluxField = refFluxField,
283 numCleanSources = numCleanSources,
284 minMatchedPairs = minMatchedPairs,
285 sourceInfo = sourceInfo,
286 verbose = debug.verbose,
293 if len(matches0) == 0
and len(matches1) == 0:
294 raise RuntimeError(
"Unable to match sources")
297 if len(matches0) > len(matches1):
302 if self.log: self.log.info(
"Matched %d sources" % len(matches))
303 if len(matches) < minMatchedPairs:
304 self.log.warn(
"Number of matches is smaller than request")
306 return pipeBase.Struct(
311 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numCleanSources, minMatchedPairs,
312 sourceInfo, verbose):
313 """!Implementation of matching sources to position reference stars
315 Unlike matchObjectsToSources, this method does not check if the sources are suitable.
317 @param[in] refCat catalog of position reference stars that overlap an exposure
318 @param[in] sourceCat catalog of sources found on the exposure
319 @param[in] wcs estimated WCS of exposure
320 @param[in] refFluxField field of refCat to use for flux
321 @param[in] numCleanSources number of clean sources (sources with known centroid
322 that are not near the edge, but may be saturated)
323 @param[in] minMatchedPairs minimum number of matches
324 @param[in] sourceInfo SourceInfo for the sourceCat
325 @param[in] verbose true to print diagnostic information to std::cout
327 numSources = len(sourceCat)
328 posRefBegInd = numCleanSources - numSources
329 configMatchDistPix = self.config.maxMatchDistArcSec/wcs.pixelScale().asArcseconds()
332 matchControl.refFluxField = refFluxField
333 matchControl.sourceFluxField = sourceInfo.fluxField
334 matchControl.numBrightStars = self.config.numBrightStars
335 matchControl.minMatchedPairs = self.config.minMatchedPairs
336 matchControl.maxOffsetPix = self.config.maxOffsetPix
337 matchControl.numPointsForShape = self.config.numPointsForShape
338 matchControl.maxDeterminant = self.config.maxDeterminant
340 for maxRotInd
in range(4):
341 matchControl.maxRotationRad = self.config.rotationAllowedInRad * math.pow(2.0, 0.5*maxRotInd)
342 for matchRadInd
in range(3):
343 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
345 for angleDiffInd
in range(3):
346 matchControl.angleDiffFrom90 = self.config.angleDiffFrom90*(angleDiffInd+1)
354 if matches
is not None and len(matches) != 0:
Match sources to reference objects.
def matchObjectsToSources
Match sources to position reference stars.
afwTable::ReferenceMatchVector matchOptimisticB(afwTable::SimpleCatalog const &posRefCat, afwTable::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, int posRefBegInd, bool verbose)
def _doMatch
Implementation of matching sources to position reference stars.
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.