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",
52 "base_PixelFlags_flag_interpolated",
58 """!Base class for source selectors 60 Register all source selectors with the sourceSelectorRegistry using: 61 sourceSelectorRegistry.register(name, class) 64 ConfigClass = BaseSourceSelectorConfig
65 _DefaultName =
"sourceSelector" 68 """!Initialize a source selector.""" 69 pipeBase.Task.__init__(self, **kwargs)
71 def run(self, sourceCat, maskedImage=None, **kwargs):
72 """!Select sources and return them. 74 @param[in] sourceCat catalog of sources that may be sources (an lsst.afw.table.SourceCatalog) 75 @param[in] maskedImage the maskedImage containing the sources, for plotting. 77 @return an lsst.pipe.base.Struct containing: 78 - sourceCat catalog of sources that were selected 80 return self.
selectSources(maskedImage=maskedImage, sourceCat=sourceCat, **kwargs)
84 """!Return a catalog of sources: a subset of sourceCat. 86 @param[in] sourceCat catalog of sources that may be sources (an lsst.afw.table.SourceCatalog) 88 @return a pipeBase.Struct containing: 89 - sourceCat a catalog of sources 93 result = afwTable.SourceCatalog(sourceCat.table)
94 for source
in sourceCat:
95 if not self.
_isBad(source):
97 return pipeBase.Struct(sourceCat=result)
99 def _isBad(self, source):
100 """Return True if any of config.badFlags are set for this source.""" 101 return any(source.get(flag)
for flag
in self.config.badFlags)
104 sourceSelectorRegistry = pexConfig.makeRegistry(
105 doc=
"A registry of source selectors (subclasses of BaseSourceSelectorTask)",
110 """Base class for selecting sources by applying a limit 112 This object can be used as a `lsst.pex.config.Config` for configuring 113 the limit, and then the `apply` method can be used to identify sources 114 in the catalog that match the configured limit. 116 This provides the `maximum` and `minimum` fields in the Config, and 117 a method to apply the limits to an array of values calculated by the 120 minimum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value greater than this")
121 maximum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value less than this")
124 """Apply the limits to an array of values 126 Subclasses should calculate the array of values and then 127 return the result of calling this method. 131 values : `numpy.ndarray` 132 Array of values to which to apply limits. 136 selected : `numpy.ndarray` 137 Boolean array indicating for each source whether it is selected 138 (True means selected). 140 selected = np.ones(len(values), dtype=bool)
141 with np.errstate(invalid=
"ignore"):
143 selected &= values > self.
minimum 145 selected &= values < self.
maximum 150 """Select sources using a color limit 152 This object can be used as a `lsst.pex.config.Config` for configuring 153 the limit, and then the `apply` method can be used to identify sources 154 in the catalog that match the configured limit. 156 We refer to 'primary' and 'secondary' flux measurements; these are the 157 two components of the color, which is: 159 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary]) 161 primary = pexConfig.Field(dtype=str, doc=
"Name of column with primary flux measurement")
162 secondary = pexConfig.Field(dtype=str, doc=
"Name of column with secondary flux measurement")
165 """Apply the color limit to a catalog 169 catalog : `lsst.afw.table.SourceCatalog` 170 Catalog of sources to which the limit will be applied. 174 selected : `numpy.ndarray` 175 Boolean array indicating for each source whether it is selected 176 (True means selected). 180 color = primary - secondary
181 return BaseLimit.apply(self, color)
185 """Select sources using a flux limit 187 This object can be used as a `lsst.pex.config.Config` for configuring 188 the limit, and then the `apply` method can be used to identify sources 189 in the catalog that match the configured limit. 191 fluxField = pexConfig.Field(dtype=str, default=
"slot_CalibFlux_flux",
192 doc=
"Name of the source flux field to use.")
195 """Apply the flux limits to a catalog 199 catalog : `lsst.afw.table.SourceCatalog` 200 Catalog of sources to which the limit will be applied. 204 selected : `numpy.ndarray` 205 Boolean array indicating for each source whether it is selected 206 (True means selected). 209 if flagField
in catalog.schema:
210 selected = np.logical_not(catalog[flagField])
212 selected = np.ones(len(catalog), dtype=bool)
215 selected &= BaseLimit.apply(self, flux)
220 """Select sources using a magnitude limit 222 Note that this assumes that a zero-point has already been applied and 223 the fluxes are in AB fluxes in Jansky. It is therefore principally 224 intended for reference catalogs rather than catalogs extracted from 227 This object can be used as a `lsst.pex.config.Config` for configuring 228 the limit, and then the `apply` method can be used to identify sources 229 in the catalog that match the configured limit. 231 fluxField = pexConfig.Field(dtype=str, default=
"flux",
232 doc=
"Name of the source flux field to use.")
235 """Apply the magnitude limits to a catalog 239 catalog : `lsst.afw.table.SourceCatalog` 240 Catalog of sources to which the limit will be applied. 244 selected : `numpy.ndarray` 245 Boolean array indicating for each source whether it is selected 246 (True means selected). 249 if flagField
in catalog.schema:
250 selected = np.logical_not(catalog[flagField])
252 selected = np.ones(len(catalog), dtype=bool)
255 selected &= BaseLimit.apply(self, magnitude)
260 """Select sources using a flux signal-to-noise limit 262 This object can be used as a `lsst.pex.config.Config` for configuring 263 the limit, and then the `apply` method can be used to identify sources 264 in the catalog that match the configured limit. 266 fluxField = pexConfig.Field(dtype=str, default=
"flux",
267 doc=
"Name of the source flux field to use.")
268 errField = pexConfig.Field(dtype=str, default=
"flux_err",
269 doc=
"Name of the source flux error field to use.")
272 """Apply the signal-to-noise limits to a catalog 276 catalog : `lsst.afw.table.SourceCatalog` 277 Catalog of sources to which the limit will be applied. 281 selected : `numpy.ndarray` 282 Boolean array indicating for each source whether it is selected 283 (True means selected). 286 if flagField
in catalog.schema:
287 selected = np.logical_not(catalog[flagField])
289 selected = np.ones(len(catalog), dtype=bool)
292 selected &= BaseLimit.apply(self, signalToNoise)
297 """Select sources using a magnitude error limit 299 Because the magnitude error is the inverse of the signal-to-noise 300 ratio, this also works to select sources by signal-to-noise when 301 you only have a magnitude. 303 This object can be used as a `lsst.pex.config.Config` for configuring 304 the limit, and then the `apply` method can be used to identify sources 305 in the catalog that match the configured limit. 307 magErrField = pexConfig.Field(dtype=str, default=
"mag_err",
308 doc=
"Name of the source flux error field to use.")
311 """Apply the magnitude error limits to a catalog 315 catalog : `lsst.afw.table.SourceCatalog` 316 Catalog of sources to which the limit will be applied. 320 selected : `numpy.ndarray` 321 Boolean array indicating for each source whether it is selected 322 (True means selected). 324 return BaseLimit.apply(self, catalog[self.
magErrField])
328 """Select sources using flags 330 This object can be used as a `lsst.pex.config.Config` for configuring 331 the limit, and then the `apply` method can be used to identify sources 332 in the catalog that match the configured limit. 334 good = pexConfig.ListField(dtype=str, default=[],
335 doc=
"List of source flag fields that must be set for a source to be used.")
336 bad = pexConfig.ListField(dtype=str, default=[],
337 doc=
"List of source flag fields that must NOT be set for a source to be used.")
340 """Apply the flag requirements to a catalog 342 Returns whether the source is selected. 346 catalog : `lsst.afw.table.SourceCatalog` 347 Catalog of sources to which the requirements will be applied. 351 selected : `numpy.ndarray` 352 Boolean array indicating for each source whether it is selected 353 (True means selected). 355 selected = np.ones(len(catalog), dtype=bool)
356 for flag
in self.
good:
357 selected &= catalog[flag]
358 for flag
in self.
bad:
359 selected &= ~catalog[flag]
364 """Select sources using star/galaxy separation 366 This object can be used as a `lsst.pex.config.Config` for configuring 367 the limit, and then the `apply` method can be used to identify sources 368 in the catalog that match the configured limit. 370 name = pexConfig.Field(dtype=str, default=
"base_ClassificationExtendedness_value",
371 doc=
"Name of column for star/galaxy separation")
374 """Apply the flag requirements to a catalog 376 Returns whether the source is selected. 380 catalog : `lsst.afw.table.SourceCatalog` 381 Catalog of sources to which the requirements will be applied. 385 selected : `numpy.ndarray` 386 Boolean array indicating for each source whether it is selected 387 (True means selected). 389 selected = np.ones(len(catalog), dtype=bool)
390 value = catalog[self.
name]
391 return BaseLimit.apply(self, value)
394 """Select sources based on whether they are isolated 396 This object can be used as a `lsst.pex.config.Config` for configuring 397 the column names to check for "parent" and "nChild" keys. 399 Note that this should only be run on a catalog that has had the 400 deblender already run (or else deblend_nChild does not exist). 402 parentName = pexConfig.Field(dtype=str, default=
"parent",
403 doc=
"Name of column for parent")
404 nChildName = pexConfig.Field(dtype=str, default=
"deblend_nChild",
405 doc=
"Name of column for nChild")
408 """Apply the isolation requirements to a catalog 410 Returns whether the source is selected. 414 catalog : `lsst.afw.table.SourceCatalog` 415 Catalog of sources to which the requirements will be applied. 419 selected : `numpy.ndarray` 420 Boolean array indicating for each source whether it is selected 421 (True means selected). 428 """Configuration for selecting science sources""" 429 doFluxLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flux limit?")
430 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
431 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
432 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
433 doIsolated = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply isolated limitation?")
434 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc=
"Flux limit to apply")
435 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
436 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
437 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
438 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc=
"Isolated criteria to apply")
441 pexConfig.Config.setDefaults(self)
442 self.
flags.bad = [
"base_PixelFlags_flag_edge",
"base_PixelFlags_flag_interpolated",
443 "base_PixelFlags_flag_saturated",
"base_PsfFlux_flags"]
449 """Science source selector 451 By "science" sources, we mean sources that are on images that we 452 are processing, as opposed to sources from reference catalogs. 454 This selects (science) sources by (optionally) applying each of a 455 magnitude limit, flag requirements and star/galaxy separation. 457 ConfigClass = ScienceSourceSelectorConfig
460 """Return a catalog of selected sources 464 catalog : `lsst.afw.table.SourceCatalog` 465 Catalog of sources to select. 466 matches : `lsst.afw.table.ReferenceMatchVector`, optional 467 List of matches; ignored. 471 sourceCat : `lsst.afw.table.SourceCatalog` 472 Catalog of selected sources, non-contiguous. 474 selected = np.ones(len(catalog), dtype=bool)
475 if self.config.doFluxLimit:
476 selected &= self.config.fluxLimit.apply(catalog)
477 if self.config.doFlags:
478 selected &= self.config.flags.apply(catalog)
479 if self.config.doUnresolved:
480 selected &= self.config.unresolved.apply(catalog)
481 if self.config.doSignalToNoise:
482 selected &= self.config.signalToNoise.apply(catalog)
483 if self.config.doIsolated:
484 selected &= self.config.isolated.apply(catalog)
486 self.log.info(
"Selected %d/%d sources", selected.sum(), len(catalog))
488 return pipeBase.Struct(sourceCat=catalog[selected],
492 doMagLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude limit?")
493 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
494 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
495 doMagError = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude error limit?")
496 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc=
"Magnitude limit to apply")
497 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
498 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
499 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc=
"Magnitude error limit to apply")
500 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
501 doc=
"Color limits to apply; key is used as a label only")
505 """Reference source selector 507 This selects reference sources by (optionally) applying each of a 508 magnitude limit, flag requirements and color limits. 510 ConfigClass = ReferenceSourceSelectorConfig
513 """Return a catalog of selected reference sources 517 catalog : `lsst.afw.table.SourceCatalog` 518 Catalog of sources to select. 519 matches : `lsst.afw.table.ReferenceMatchVector`, optional 520 List of matches; ignored. 524 sourceCat : `lsst.afw.table.SourceCatalog` 525 Catalog of selected sources, non-contiguous. 527 selected = np.ones(len(catalog), dtype=bool)
528 if self.config.doMagLimit:
529 selected &= self.config.magLimit.apply(catalog)
530 if self.config.doFlags:
531 selected &= self.config.flags.apply(catalog)
532 if self.config.doSignalToNoise:
533 selected &= self.config.signalToNoise.apply(catalog)
534 if self.config.doMagError:
535 selected &= self.config.magError.apply(catalog)
536 for limit
in self.config.colorLimits.values():
537 selected &= limit.apply(catalog)
539 self.log.info(
"Selected %d/%d references", selected.sum(), len(catalog))
541 result = type(catalog)(catalog.table)
542 for source
in catalog[selected]:
543 result.append(source)
544 return pipeBase.Struct(sourceCat=result, selection=selected)
547 sourceSelectorRegistry.register(
"science", ScienceSourceSelectorTask)
548 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)
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)
ndarray::Array< T, 1 > abMagFromFlux(ndarray::Array< T const, 1 > const &flux)
Base class for source selectors.