24 __all__ = [
"BaseSourceSelectorConfig",
"BaseSourceSelectorTask",
"sourceSelectorRegistry",
25 "ColorLimit",
"MagnitudeLimit",
"SignalToNoiseLimit",
"MagnitudeErrorLimit",
26 "RequireFlags",
"RequireUnresolved",
27 "ScienceSourceSelectorConfig",
"ScienceSourceSelectorTask",
28 "ReferenceSourceSelectorConfig",
"ReferenceSourceSelectorTask",
33 import astropy.units
as u
44 """Base class for source selectors 46 Source selectors are classes that perform a selection on a catalog 47 object given a set of criteria or cuts. They return the selected catalog 48 and can optionally set a specified Flag field in the input catalog to 49 identify if the source was selected. 51 Register all source selectors with the sourceSelectorRegistry using: 52 sourceSelectorRegistry.register(name, class) 57 A boolean variable specify if the inherited source selector uses 58 matches to an external catalog, and thus requires the ``matches`` 59 argument to ``run()``. 62 ConfigClass = BaseSourceSelectorConfig
63 _DefaultName =
"sourceSelector" 67 pipeBase.Task.__init__(self, **kwargs)
69 def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None):
70 """Select sources and return them. 72 The input catalog must be contiguous in memory. 76 sourceCat : `lsst.afw.table.SourceCatalog` 77 Catalog of sources to select from. 78 sourceSelectedField : `str` or None 79 Name of flag field in sourceCat to set for selected sources. 80 If set, will modify sourceCat in-place. 81 matches : `list` of `lsst.afw.table.ReferenceMatch` or None 82 List of matches to use for source selection. 83 If usesMatches is set in source selector this field is required. 84 If not, it is ignored. 85 exposure : `lsst.afw.image.Exposure` or None 86 The exposure the catalog was built from; used for debug display. 90 struct : `lsst.pipe.base.Struct` 91 The struct contains the following data: 93 - sourceCat : `lsst.afw.table.SourceCatalog` 94 The catalog of sources that were selected. 95 (may not be memory-contiguous) 96 - selected : `numpy.ndarray` of `bool`` 97 Boolean array of sources that were selected, same length as 103 Raised if ``sourceCat`` is not contiguous. 105 if not sourceCat.isContiguous():
106 raise RuntimeError(
"Input catalogs for source selection must be contiguous.")
112 if sourceSelectedField
is not None:
113 source_selected_key = \
114 sourceCat.getSchema()[sourceSelectedField].asKey()
116 for source, flag
in zip(sourceCat, result.selected):
117 source.set(source_selected_key, bool(flag))
118 return pipeBase.Struct(sourceCat=sourceCat[result.selected],
119 selected=result.selected)
123 """Return a selection of sources selected by some criteria. 127 sourceCat : `lsst.afw.table.SourceCatalog` 128 Catalog of sources to select from. 129 This catalog must be contiguous in memory. 130 matches : `list` of `lsst.afw.table.ReferenceMatch` or None 131 A list of lsst.afw.table.ReferenceMatch objects 132 exposure : `lsst.afw.image.Exposure` or None 133 The exposure the catalog was built from; used for debug display. 137 struct : `lsst.pipe.base.Struct` 138 The struct contains the following data: 140 - selected : `numpy.ndarray` of `bool`` 141 Boolean array of sources that were selected, same length as 144 raise NotImplementedError(
"BaseSourceSelectorTask is abstract")
147 sourceSelectorRegistry = pexConfig.makeRegistry(
148 doc=
"A registry of source selectors (subclasses of " 149 "BaseSourceSelectorTask)",
154 """Base class for selecting sources by applying a limit 156 This object can be used as a `lsst.pex.config.Config` for configuring 157 the limit, and then the `apply` method can be used to identify sources 158 in the catalog that match the configured limit. 160 This provides the `maximum` and `minimum` fields in the Config, and 161 a method to apply the limits to an array of values calculated by the 164 minimum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value greater than this")
165 maximum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value less than this")
168 """Apply the limits to an array of values 170 Subclasses should calculate the array of values and then 171 return the result of calling this method. 175 values : `numpy.ndarray` 176 Array of values to which to apply limits. 180 selected : `numpy.ndarray` 181 Boolean array indicating for each source whether it is selected 182 (True means selected). 184 selected = np.ones(len(values), dtype=bool)
185 with np.errstate(invalid=
"ignore"):
187 selected &= values > self.
minimum 189 selected &= values < self.
maximum 194 """Select sources using a color limit 196 This object can be used as a `lsst.pex.config.Config` for configuring 197 the limit, and then the `apply` method can be used to identify sources 198 in the catalog that match the configured limit. 200 We refer to 'primary' and 'secondary' flux measurements; these are the 201 two components of the color, which is: 203 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary]) 205 primary = pexConfig.Field(dtype=str, doc=
"Name of column with primary flux measurement")
206 secondary = pexConfig.Field(dtype=str, doc=
"Name of column with secondary flux measurement")
209 """Apply the color limit to a catalog 213 catalog : `lsst.afw.table.SourceCatalog` 214 Catalog of sources to which the limit will be applied. 218 selected : `numpy.ndarray` 219 Boolean array indicating for each source whether it is selected 220 (True means selected). 222 primary = (catalog[self.
primary]*u.nJy).to_value(u.ABmag)
223 secondary = (catalog[self.
secondary]*u.nJy).to_value(u.ABmag)
224 color = primary - secondary
225 return BaseLimit.apply(self, color)
229 """Select sources using a flux limit 231 This object can be used as a `lsst.pex.config.Config` for configuring 232 the limit, and then the `apply` method can be used to identify sources 233 in the catalog that match the configured limit. 235 fluxField = pexConfig.Field(dtype=str, default=
"slot_CalibFlux_instFlux",
236 doc=
"Name of the source flux field to use.")
239 """Apply the flux limits to a catalog 243 catalog : `lsst.afw.table.SourceCatalog` 244 Catalog of sources to which the limit will be applied. 248 selected : `numpy.ndarray` 249 Boolean array indicating for each source whether it is selected 250 (True means selected). 253 if flagField
in catalog.schema:
254 selected = np.logical_not(catalog[flagField])
256 selected = np.ones(len(catalog), dtype=bool)
259 selected &= BaseLimit.apply(self, flux)
264 """Select sources using a magnitude limit 266 Note that this assumes that a zero-point has already been applied and 267 the fluxes are in AB fluxes in Jansky. It is therefore principally 268 intended for reference catalogs rather than catalogs extracted from 271 This object can be used as a `lsst.pex.config.Config` for configuring 272 the limit, and then the `apply` method can be used to identify sources 273 in the catalog that match the configured limit. 275 fluxField = pexConfig.Field(dtype=str, default=
"flux",
276 doc=
"Name of the source flux field to use.")
279 """Apply the magnitude limits to a catalog 283 catalog : `lsst.afw.table.SourceCatalog` 284 Catalog of sources to which the limit will be applied. 288 selected : `numpy.ndarray` 289 Boolean array indicating for each source whether it is selected 290 (True means selected). 293 if flagField
in catalog.schema:
294 selected = np.logical_not(catalog[flagField])
296 selected = np.ones(len(catalog), dtype=bool)
298 magnitude = (catalog[self.
fluxField]*u.nJy).to_value(u.ABmag)
299 selected &= BaseLimit.apply(self, magnitude)
304 """Select sources using a flux signal-to-noise limit 306 This object can be used as a `lsst.pex.config.Config` for configuring 307 the limit, and then the `apply` method can be used to identify sources 308 in the catalog that match the configured limit. 310 fluxField = pexConfig.Field(dtype=str, default=
"flux",
311 doc=
"Name of the source flux field to use.")
312 errField = pexConfig.Field(dtype=str, default=
"flux_err",
313 doc=
"Name of the source flux error field to use.")
316 """Apply the signal-to-noise limits to a catalog 320 catalog : `lsst.afw.table.SourceCatalog` 321 Catalog of sources to which the limit will be applied. 325 selected : `numpy.ndarray` 326 Boolean array indicating for each source whether it is selected 327 (True means selected). 330 if flagField
in catalog.schema:
331 selected = np.logical_not(catalog[flagField])
333 selected = np.ones(len(catalog), dtype=bool)
336 selected &= BaseLimit.apply(self, signalToNoise)
341 """Select sources using a magnitude error limit 343 Because the magnitude error is the inverse of the signal-to-noise 344 ratio, this also works to select sources by signal-to-noise when 345 you only have a magnitude. 347 This object can be used as a `lsst.pex.config.Config` for configuring 348 the limit, and then the `apply` method can be used to identify sources 349 in the catalog that match the configured limit. 351 magErrField = pexConfig.Field(dtype=str, default=
"mag_err",
352 doc=
"Name of the source flux error field to use.")
355 """Apply the magnitude error limits to a catalog 359 catalog : `lsst.afw.table.SourceCatalog` 360 Catalog of sources to which the limit will be applied. 364 selected : `numpy.ndarray` 365 Boolean array indicating for each source whether it is selected 366 (True means selected). 368 return BaseLimit.apply(self, catalog[self.
magErrField])
372 """Select sources using flags 374 This object can be used as a `lsst.pex.config.Config` for configuring 375 the limit, and then the `apply` method can be used to identify sources 376 in the catalog that match the configured limit. 378 good = pexConfig.ListField(dtype=str, default=[],
379 doc=
"List of source flag fields that must be set for a source to be used.")
380 bad = pexConfig.ListField(dtype=str, default=[],
381 doc=
"List of source flag fields that must NOT be set for a source to be used.")
384 """Apply the flag requirements to a catalog 386 Returns whether the source is selected. 390 catalog : `lsst.afw.table.SourceCatalog` 391 Catalog of sources to which the requirements will be applied. 395 selected : `numpy.ndarray` 396 Boolean array indicating for each source whether it is selected 397 (True means selected). 399 selected = np.ones(len(catalog), dtype=bool)
400 for flag
in self.
good:
401 selected &= catalog[flag]
402 for flag
in self.
bad:
403 selected &= ~catalog[flag]
408 """Select sources using star/galaxy separation 410 This object can be used as a `lsst.pex.config.Config` for configuring 411 the limit, and then the `apply` method can be used to identify sources 412 in the catalog that match the configured limit. 414 name = pexConfig.Field(dtype=str, default=
"base_ClassificationExtendedness_value",
415 doc=
"Name of column for star/galaxy separation")
420 ``base_ClassificationExtendedness_value < 0.5`` means unresolved. 425 """Apply the flag requirements to a catalog 427 Returns whether the source is selected. 431 catalog : `lsst.afw.table.SourceCatalog` 432 Catalog of sources to which the requirements will be applied. 436 selected : `numpy.ndarray` 437 Boolean array indicating for each source whether it is selected 438 (True means selected). 440 value = catalog[self.
name]
441 return BaseLimit.apply(self, value)
445 """Select sources based on whether they are isolated 447 This object can be used as a `lsst.pex.config.Config` for configuring 448 the column names to check for "parent" and "nChild" keys. 450 Note that this should only be run on a catalog that has had the 451 deblender already run (or else deblend_nChild does not exist). 453 parentName = pexConfig.Field(dtype=str, default=
"parent",
454 doc=
"Name of column for parent")
455 nChildName = pexConfig.Field(dtype=str, default=
"deblend_nChild",
456 doc=
"Name of column for nChild")
459 """Apply the isolation requirements to a catalog 461 Returns whether the source is selected. 465 catalog : `lsst.afw.table.SourceCatalog` 466 Catalog of sources to which the requirements will be applied. 470 selected : `numpy.ndarray` 471 Boolean array indicating for each source whether it is selected 472 (True means selected). 480 """Configuration for selecting science sources""" 481 doFluxLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flux limit?")
482 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
483 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
484 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
485 doIsolated = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply isolated limitation?")
486 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc=
"Flux limit to apply")
487 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
488 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
489 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
490 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc=
"Isolated criteria to apply")
493 pexConfig.Config.setDefaults(self)
494 self.
flags.bad = [
"base_PixelFlags_flag_edge",
"base_PixelFlags_flag_saturated",
"base_PsfFlux_flags"]
499 @pexConfig.registerConfigurable(
"science", sourceSelectorRegistry)
501 """Science source selector 503 By "science" sources, we mean sources that are on images that we 504 are processing, as opposed to sources from reference catalogs. 506 This selects (science) sources by (optionally) applying each of a 507 magnitude limit, flag requirements and star/galaxy separation. 509 ConfigClass = ScienceSourceSelectorConfig
512 """Return a selection of sources selected by specified criteria. 516 sourceCat : `lsst.afw.table.SourceCatalog` 517 Catalog of sources to select from. 518 This catalog must be contiguous in memory. 519 matches : `list` of `lsst.afw.table.ReferenceMatch` or None 520 Ignored in this SourceSelector. 521 exposure : `lsst.afw.image.Exposure` or None 522 The exposure the catalog was built from; used for debug display. 526 struct : `lsst.pipe.base.Struct` 527 The struct contains the following data: 529 - selected : `array` of `bool`` 530 Boolean array of sources that were selected, same length as 533 selected = np.ones(len(sourceCat), dtype=bool)
534 if self.config.doFluxLimit:
535 selected &= self.config.fluxLimit.apply(sourceCat)
536 if self.config.doFlags:
537 selected &= self.config.flags.apply(sourceCat)
538 if self.config.doUnresolved:
539 selected &= self.config.unresolved.apply(sourceCat)
540 if self.config.doSignalToNoise:
541 selected &= self.config.signalToNoise.apply(sourceCat)
542 if self.config.doIsolated:
543 selected &= self.config.isolated.apply(sourceCat)
545 self.log.
info(
"Selected %d/%d sources", selected.sum(), len(sourceCat))
547 return pipeBase.Struct(selected=selected)
551 doMagLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude limit?")
552 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
553 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
554 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
555 doMagError = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude error limit?")
556 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc=
"Magnitude limit to apply")
557 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
558 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
559 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
560 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc=
"Magnitude error limit to apply")
561 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
562 doc=
"Color limits to apply; key is used as a label only")
565 @pexConfig.registerConfigurable(
"references", sourceSelectorRegistry)
567 """Reference source selector 569 This selects reference sources by (optionally) applying each of a 570 magnitude limit, flag requirements and color limits. 572 ConfigClass = ReferenceSourceSelectorConfig
575 """Return a selection of reference sources selected by some criteria. 579 sourceCat : `lsst.afw.table.SourceCatalog` 580 Catalog of sources to select from. 581 This catalog must be contiguous in memory. 582 matches : `list` of `lsst.afw.table.ReferenceMatch` or None 583 Ignored in this SourceSelector. 584 exposure : `lsst.afw.image.Exposure` or None 585 The exposure the catalog was built from; used for debug display. 589 struct : `lsst.pipe.base.Struct` 590 The struct contains the following data: 592 - selected : `array` of `bool`` 593 Boolean array of sources that were selected, same length as 596 selected = np.ones(len(sourceCat), dtype=bool)
597 if self.config.doMagLimit:
598 selected &= self.config.magLimit.apply(sourceCat)
599 if self.config.doFlags:
600 selected &= self.config.flags.apply(sourceCat)
601 if self.config.doUnresolved:
602 selected &= self.config.unresolved.apply(sourceCat)
603 if self.config.doSignalToNoise:
604 selected &= self.config.signalToNoise.apply(sourceCat)
605 if self.config.doMagError:
606 selected &= self.config.magError.apply(sourceCat)
607 for limit
in self.config.colorLimits.values():
608 selected &= limit.apply(sourceCat)
610 self.log.
info(
"Selected %d/%d references", selected.sum(), len(sourceCat))
612 return pipeBase.Struct(selected=selected)
def selectSources(self, sourceCat, matches=None, exposure=None)
def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None)
def __init__(self, kwargs)
def selectSources(self, sourceCat, matches=None, exposure=None)
def selectSources(self, sourceCat, matches=None, exposure=None)