23 from __future__
import absolute_import, division, print_function
25 __all__ = [
"BaseSourceSelectorConfig",
"BaseSourceSelectorTask",
"sourceSelectorRegistry",
26 "ColorLimit",
"MagnitudeLimit",
"SignalToNoiseLimit",
"MagnitudeErrorLimit",
27 "RequireFlags",
"RequireUnresolved",
28 "ScienceSourceSelectorConfig",
"ScienceSourceSelectorTask",
29 "ReferenceSourceSelectorConfig",
"ReferenceSourceSelectorTask",
39 from future.utils
import with_metaclass
43 badFlags = pexConfig.ListField(
44 doc=
"List of flags which cause a source to be rejected as bad",
47 "base_PixelFlags_flag_edge",
48 "base_PixelFlags_flag_interpolatedCenter",
49 "base_PixelFlags_flag_saturatedCenter",
50 "base_PixelFlags_flag_crCenter",
51 "base_PixelFlags_flag_bad",
57 """!Base class for source selectors 59 Register all source selectors with the sourceSelectorRegistry using: 60 sourceSelectorRegistry.register(name, class) 63 ConfigClass = BaseSourceSelectorConfig
64 _DefaultName =
"sourceSelector" 67 """!Initialize a source selector.""" 68 pipeBase.Task.__init__(self, **kwargs)
70 def run(self, sourceCat, maskedImage=None, **kwargs):
71 """!Select sources and return them. 73 @param[in] sourceCat catalog of sources that may be sources (an lsst.afw.table.SourceCatalog) 74 @param[in] maskedImage the maskedImage containing the sources, for plotting. 76 @return an lsst.pipe.base.Struct containing: 77 - sourceCat catalog of sources that were selected 79 return self.
selectSources(maskedImage=maskedImage, sourceCat=sourceCat, **kwargs)
83 """!Return a catalog of sources: a subset of sourceCat. 85 @param[in] sourceCat catalog of sources that may be sources (an lsst.afw.table.SourceCatalog) 87 @return a pipeBase.Struct containing: 88 - sourceCat a catalog of sources 92 result = afwTable.SourceCatalog(sourceCat.table)
93 for source
in sourceCat:
94 if not self.
_isBad(source):
96 return pipeBase.Struct(sourceCat=result)
98 def _isBad(self, source):
99 """Return True if any of config.badFlags are set for this source.""" 100 return any(source.get(flag)
for flag
in self.config.badFlags)
103 sourceSelectorRegistry = pexConfig.makeRegistry(
104 doc=
"A registry of source selectors (subclasses of BaseSourceSelectorTask)",
109 """Base class for selecting sources by applying a limit 111 This object can be used as a `lsst.pex.config.Config` for configuring 112 the limit, and then the `apply` method can be used to identify sources 113 in the catalog that match the configured limit. 115 This provides the `maximum` and `minimum` fields in the Config, and 116 a method to apply the limits to an array of values calculated by the 119 minimum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value greater than this")
120 maximum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value less than this")
123 """Apply the limits to an array of values 125 Subclasses should calculate the array of values and then 126 return the result of calling this method. 130 values : `numpy.ndarray` 131 Array of values to which to apply limits. 135 selected : `numpy.ndarray` 136 Boolean array indicating for each source whether it is selected 137 (True means selected). 139 selected = np.ones(len(values), dtype=bool)
140 with np.errstate(invalid=
"ignore"):
142 selected &= values > self.
minimum 144 selected &= values < self.
maximum 149 """Select sources using a color limit 151 This object can be used as a `lsst.pex.config.Config` for configuring 152 the limit, and then the `apply` method can be used to identify sources 153 in the catalog that match the configured limit. 155 We refer to 'primary' and 'secondary' flux measurements; these are the 156 two components of the color, which is: 158 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary]) 160 primary = pexConfig.Field(dtype=str, doc=
"Name of column with primary flux measurement")
161 secondary = pexConfig.Field(dtype=str, doc=
"Name of column with secondary flux measurement")
164 """Apply the color limit to a catalog 168 catalog : `lsst.afw.table.SourceCatalog` 169 Catalog of sources to which the limit will be applied. 173 selected : `numpy.ndarray` 174 Boolean array indicating for each source whether it is selected 175 (True means selected). 179 color = primary - secondary
180 return BaseLimit.apply(self, color)
184 """Select sources using a flux limit 186 This object can be used as a `lsst.pex.config.Config` for configuring 187 the limit, and then the `apply` method can be used to identify sources 188 in the catalog that match the configured limit. 190 fluxField = pexConfig.Field(dtype=str, default=
"slot_CalibFlux_flux",
191 doc=
"Name of the source flux field to use.")
194 """Apply the flux limits to a catalog 198 catalog : `lsst.afw.table.SourceCatalog` 199 Catalog of sources to which the limit will be applied. 203 selected : `numpy.ndarray` 204 Boolean array indicating for each source whether it is selected 205 (True means selected). 208 if flagField
in catalog.schema:
209 selected = np.logical_not(catalog[flagField])
211 selected = np.ones(len(catalog), dtype=bool)
214 selected &= BaseLimit.apply(self, flux)
219 """Select sources using a magnitude limit 221 Note that this assumes that a zero-point has already been applied and 222 the fluxes are in AB fluxes in Jansky. It is therefore principally 223 intended for reference catalogs rather than catalogs extracted from 226 This object can be used as a `lsst.pex.config.Config` for configuring 227 the limit, and then the `apply` method can be used to identify sources 228 in the catalog that match the configured limit. 230 fluxField = pexConfig.Field(dtype=str, default=
"flux",
231 doc=
"Name of the source flux field to use.")
234 """Apply the magnitude limits to a catalog 238 catalog : `lsst.afw.table.SourceCatalog` 239 Catalog of sources to which the limit will be applied. 243 selected : `numpy.ndarray` 244 Boolean array indicating for each source whether it is selected 245 (True means selected). 248 if flagField
in catalog.schema:
249 selected = np.logical_not(catalog[flagField])
251 selected = np.ones(len(catalog), dtype=bool)
254 selected &= BaseLimit.apply(self, magnitude)
259 """Select sources using a flux signal-to-noise limit 261 This object can be used as a `lsst.pex.config.Config` for configuring 262 the limit, and then the `apply` method can be used to identify sources 263 in the catalog that match the configured limit. 265 fluxField = pexConfig.Field(dtype=str, default=
"flux",
266 doc=
"Name of the source flux field to use.")
267 errField = pexConfig.Field(dtype=str, default=
"flux_err",
268 doc=
"Name of the source flux error field to use.")
271 """Apply the signal-to-noise limits to a catalog 275 catalog : `lsst.afw.table.SourceCatalog` 276 Catalog of sources to which the limit will be applied. 280 selected : `numpy.ndarray` 281 Boolean array indicating for each source whether it is selected 282 (True means selected). 285 if flagField
in catalog.schema:
286 selected = np.logical_not(catalog[flagField])
288 selected = np.ones(len(catalog), dtype=bool)
291 selected &= BaseLimit.apply(self, signalToNoise)
296 """Select sources using a magnitude error limit 298 Because the magnitude error is the inverse of the signal-to-noise 299 ratio, this also works to select sources by signal-to-noise when 300 you only have a magnitude. 302 This object can be used as a `lsst.pex.config.Config` for configuring 303 the limit, and then the `apply` method can be used to identify sources 304 in the catalog that match the configured limit. 306 magErrField = pexConfig.Field(dtype=str, default=
"mag_err",
307 doc=
"Name of the source flux error field to use.")
310 """Apply the magnitude error limits to a catalog 314 catalog : `lsst.afw.table.SourceCatalog` 315 Catalog of sources to which the limit will be applied. 319 selected : `numpy.ndarray` 320 Boolean array indicating for each source whether it is selected 321 (True means selected). 323 return BaseLimit.apply(self, catalog[self.
magErrField])
327 """Select sources using flags 329 This object can be used as a `lsst.pex.config.Config` for configuring 330 the limit, and then the `apply` method can be used to identify sources 331 in the catalog that match the configured limit. 333 good = pexConfig.ListField(dtype=str, default=[],
334 doc=
"List of source flag fields that must be set for a source to be used.")
335 bad = pexConfig.ListField(dtype=str, default=[],
336 doc=
"List of source flag fields that must NOT be set for a source to be used.")
339 """Apply the flag requirements to a catalog 341 Returns whether the source is selected. 345 catalog : `lsst.afw.table.SourceCatalog` 346 Catalog of sources to which the requirements will be applied. 350 selected : `numpy.ndarray` 351 Boolean array indicating for each source whether it is selected 352 (True means selected). 354 selected = np.ones(len(catalog), dtype=bool)
355 for flag
in self.
good:
356 selected &= catalog[flag]
357 for flag
in self.
bad:
358 selected &= ~catalog[flag]
363 """Select sources using star/galaxy separation 365 This object can be used as a `lsst.pex.config.Config` for configuring 366 the limit, and then the `apply` method can be used to identify sources 367 in the catalog that match the configured limit. 369 name = pexConfig.Field(dtype=str, default=
"base_ClassificationExtendedness_value",
370 doc=
"Name of column for star/galaxy separation")
373 """Apply the flag requirements to a catalog 375 Returns whether the source is selected. 379 catalog : `lsst.afw.table.SourceCatalog` 380 Catalog of sources to which the requirements will be applied. 384 selected : `numpy.ndarray` 385 Boolean array indicating for each source whether it is selected 386 (True means selected). 388 selected = np.ones(len(catalog), dtype=bool)
389 value = catalog[self.
name]
390 return BaseLimit.apply(self, value)
393 """Select sources based on whether they are isolated 395 This object can be used as a `lsst.pex.config.Config` for configuring 396 the column names to check for "parent" and "nChild" keys. 398 Note that this should only be run on a catalog that has had the 399 deblender already run (or else deblend_nChild does not exist). 401 parentName = pexConfig.Field(dtype=str, default=
"parent",
402 doc=
"Name of column for parent")
403 nChildName = pexConfig.Field(dtype=str, default=
"deblend_nChild",
404 doc=
"Name of column for nChild")
407 """Apply the isolation requirements to a catalog 409 Returns whether the source is selected. 413 catalog : `lsst.afw.table.SourceCatalog` 414 Catalog of sources to which the requirements will be applied. 418 selected : `numpy.ndarray` 419 Boolean array indicating for each source whether it is selected 420 (True means selected). 427 """Configuration for selecting science sources""" 428 doFluxLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flux limit?")
429 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
430 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
431 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
432 doIsolated = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply isolated limitation?")
433 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc=
"Flux limit to apply")
434 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
435 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
436 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
437 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc=
"Isolated criteria to apply")
440 pexConfig.Config.setDefaults(self)
441 self.
flags.bad = [
"base_PixelFlags_flag_edge",
"base_PixelFlags_flag_saturated",
"base_PsfFlux_flags"]
447 """Science source selector 449 By "science" sources, we mean sources that are on images that we 450 are processing, as opposed to sources from reference catalogs. 452 This selects (science) sources by (optionally) applying each of a 453 magnitude limit, flag requirements and star/galaxy separation. 455 ConfigClass = ScienceSourceSelectorConfig
458 """Return a catalog of selected sources 462 catalog : `lsst.afw.table.SourceCatalog` 463 Catalog of sources to select. 464 matches : `lsst.afw.table.ReferenceMatchVector`, optional 465 List of matches; ignored. 469 sourceCat : `lsst.afw.table.SourceCatalog` 470 Catalog of selected sources, non-contiguous. 472 selected = np.ones(len(catalog), dtype=bool)
473 if self.config.doFluxLimit:
474 selected &= self.config.fluxLimit.apply(catalog)
475 if self.config.doFlags:
476 selected &= self.config.flags.apply(catalog)
477 if self.config.doUnresolved:
478 selected &= self.config.unresolved.apply(catalog)
479 if self.config.doSignalToNoise:
480 selected &= self.config.signalToNoise.apply(catalog)
481 if self.config.doIsolated:
482 selected &= self.config.isolated.apply(catalog)
484 self.log.info(
"Selected %d/%d sources", selected.sum(), len(catalog))
486 return pipeBase.Struct(sourceCat=catalog[selected],
490 doMagLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude limit?")
491 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
492 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
493 doMagError = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude error limit?")
494 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc=
"Magnitude limit to apply")
495 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
496 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
497 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc=
"Magnitude error limit to apply")
498 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
499 doc=
"Color limits to apply; key is used as a label only")
503 """Reference source selector 505 This selects reference sources by (optionally) applying each of a 506 magnitude limit, flag requirements and color limits. 508 ConfigClass = ReferenceSourceSelectorConfig
511 """Return a catalog of selected reference sources 515 catalog : `lsst.afw.table.SourceCatalog` 516 Catalog of sources to select. 517 matches : `lsst.afw.table.ReferenceMatchVector`, optional 518 List of matches; ignored. 522 sourceCat : `lsst.afw.table.SourceCatalog` 523 Catalog of selected sources, non-contiguous. 525 selected = np.ones(len(catalog), dtype=bool)
526 if self.config.doMagLimit:
527 selected &= self.config.magLimit.apply(catalog)
528 if self.config.doFlags:
529 selected &= self.config.flags.apply(catalog)
530 if self.config.doSignalToNoise:
531 selected &= self.config.signalToNoise.apply(catalog)
532 if self.config.doMagError:
533 selected &= self.config.magError.apply(catalog)
534 for limit
in self.config.colorLimits.values():
535 selected &= limit.apply(catalog)
537 self.log.info(
"Selected %d/%d references", selected.sum(), len(catalog))
539 result = type(catalog)(catalog.table)
540 for source
in catalog[selected]:
541 result.append(source)
542 return pipeBase.Struct(sourceCat=result, selection=selected)
545 sourceSelectorRegistry.register(
"science", ScienceSourceSelectorTask)
546 sourceSelectorRegistry.register(
"references", ReferenceSourceSelectorTask)
def selectSources(self, sourceCat, matches=None)
Return a catalog of sources: a subset of sourceCat.
def selectSources(self, catalog, matches=None)
template ndarray::Array< double, 1 > abMagFromFlux(ndarray::Array< double const, 1 > const &flux)
def __init__(self, kwargs)
Initialize a source selector.
def run(self, sourceCat, maskedImage=None, kwargs)
Select sources and return them.
def selectSources(self, catalog, matches=None)
Base class for source selectors.