22__all__ = [
"BaseSourceSelectorConfig",
"BaseSourceSelectorTask",
"sourceSelectorRegistry",
23 "ColorLimit",
"MagnitudeLimit",
"SignalToNoiseLimit",
"MagnitudeErrorLimit",
24 "RequireFlags",
"RequireUnresolved",
"RequireFiniteRaDec",
"RequirePrimary",
25 "ScienceSourceSelectorConfig",
"ScienceSourceSelectorTask",
26 "ReferenceSourceSelectorConfig",
"ReferenceSourceSelectorTask",
27 "NullSourceSelectorTask"
32import astropy.units
as u
45 """Base class for source selectors
47 Source selectors are classes that perform a selection on a catalog
48 object given a set of criteria or cuts. They
return the selected catalog
49 and can optionally set a specified Flag field
in the input catalog to
50 identify
if the source was selected.
52 Register all source selectors
with the sourceSelectorRegistry using:
53 sourceSelectorRegistry.register(name,
class)
58 A boolean variable specify
if the inherited source selector uses
59 matches to an external catalog,
and thus requires the ``matches``
60 argument to ``run()``.
63 ConfigClass = BaseSourceSelectorConfig
64 _DefaultName = "sourceSelector"
68 pipeBase.Task.__init__(self, **kwargs)
70 def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None):
71 """Select sources and return them.
73 The input catalog must be contiguous in memory.
77 sourceCat : Various table formats
78 Catalog of sources to select
from. Can be
80 `astropy.table.Table`,
81 sourceSelectedField : `str`
or None
82 Name of flag field
in sourceCat to set
for selected sources.
83 If set, will modify sourceCat
in-place.
85 List of matches to use
for source selection.
86 If usesMatches
is set
in source selector this field
is required.
87 If
not, it
is ignored.
89 The exposure the catalog was built
from; used
for debug display.
93 struct : `lsst.pipe.base.Struct`
94 The struct contains the following data:
97 The catalog of sources that were selected.
98 (may
not be memory-contiguous)
100 or `astropy.table.Table`)
102 Boolean array of sources that were selected, same length
as
104 (`numpy.ndarray` of `bool`)
109 Raised
if ``sourceCat``
is not contiguous.
111 if hasattr(sourceCat,
'isContiguous'):
113 if not sourceCat.isContiguous():
114 raise RuntimeError(
"Input catalogs for source selection must be contiguous.")
120 if sourceSelectedField
is not None:
121 sourceCat[sourceSelectedField] = result.selected
123 return pipeBase.Struct(sourceCat=sourceCat[result.selected],
124 selected=result.selected)
128 """Return a selection of sources selected by some criteria.
132 sourceCat : Various table formats
133 Catalog of sources to select from. Supports
135 or `astropy.table.Table`
136 This catalog must be contiguous
in memory.
140 The exposure the catalog was built
from; used
for debug display.
144 struct : `lsst.pipe.base.Struct`
145 The struct contains the following data:
148 Boolean array of sources that were selected, same length
as
150 (`numpy.ndarray` of `bool`)
152 raise NotImplementedError(
"BaseSourceSelectorTask is abstract")
155sourceSelectorRegistry = pexConfig.makeRegistry(
156 doc=
"A registry of source selectors (subclasses of "
157 "BaseSourceSelectorTask)",
162 """Base class for selecting sources by applying a limit
165 the limit,
and then the `apply` method can be used to identify sources
166 in the catalog that match the configured limit.
168 This provides the `maximum`
and `minimum` fields
in the Config,
and
169 a method to apply the limits to an array of values calculated by the
172 minimum = pexConfig.Field(dtype=float, optional=True, doc=
"Select objects with value greater than this")
173 maximum = pexConfig.Field(dtype=float, optional=
True, doc=
"Select objects with value less than this")
176 """Apply the limits to an array of values
178 Subclasses should calculate the array of values and then
179 return the result of calling this method.
183 values : `numpy.ndarray`
184 Array of values to which to apply limits.
188 selected : `numpy.ndarray`
189 Boolean array indicating
for each source whether it
is selected
190 (
True means selected).
192 selected = np.ones(len(values), dtype=bool)
193 with np.errstate(invalid=
"ignore"):
195 selected &= values > self.
minimum
197 selected &= values < self.
maximum
202 """Select sources using a color limit
205 the limit,
and then the `apply` method can be used to identify sources
206 in the catalog that match the configured limit.
208 We refer to
'primary' and 'secondary' flux measurements; these are the
209 two components of the color, which
is:
211 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary])
213 primary = pexConfig.Field(dtype=str, doc="Name of column with primary flux measurement")
214 secondary = pexConfig.Field(dtype=str, doc=
"Name of column with secondary flux measurement")
217 """Apply the color limit to a catalog
221 catalog : Various table formats
222 Catalog of sources to which the limit will be applied.
224 or `astropy.table.Table`
228 selected : `numpy.ndarray`
229 Boolean array indicating
for each source whether it
is selected
230 (
True means selected).
235 primary = (primary*u.nJy).to_value(u.ABmag)
236 secondary = (secondary*u.nJy).to_value(u.ABmag)
237 color = primary - secondary
238 return BaseLimit.apply(self, color)
242 """Select sources using a flux limit
245 the limit,
and then the `apply` method can be used to identify sources
246 in the catalog that match the configured limit.
248 fluxField = pexConfig.Field(dtype=str, default="slot_CalibFlux_instFlux",
249 doc=
"Name of the source flux field to use.")
252 """Apply the flux limits to a catalog
257 Catalog of sources to which the limit will be applied.
261 selected : `numpy.ndarray`
262 Boolean array indicating for each source whether it
is selected
263 (
True means selected).
269 selected &= BaseLimit.apply(self, flux)
274 """Select sources using a magnitude limit
276 Note that this assumes that a zero-point has already been applied and
277 the fluxes are
in AB fluxes
in Jansky. It
is therefore principally
278 intended
for reference catalogs rather than catalogs extracted
from
282 the limit,
and then the `apply` method can be used to identify sources
283 in the catalog that match the configured limit.
285 fluxField = pexConfig.Field(dtype=str, default="flux",
286 doc=
"Name of the source flux field to use.")
289 """Apply the magnitude limits to a catalog
294 Catalog of sources to which the limit will be applied.
298 selected : `numpy.ndarray`
299 Boolean array indicating for each source whether it
is selected
300 (
True means selected).
306 magnitude = (flux*u.nJy).to_value(u.ABmag)
307 selected &= BaseLimit.apply(self, magnitude)
312 """Select sources using a flux signal-to-noise limit
315 the limit,
and then the `apply` method can be used to identify sources
316 in the catalog that match the configured limit.
318 fluxField = pexConfig.Field(dtype=str, default="flux",
319 doc=
"Name of the source flux field to use.")
320 errField = pexConfig.Field(dtype=str, default=
"flux_err",
321 doc=
"Name of the source flux error field to use.")
324 """Apply the signal-to-noise limits to a catalog
329 Catalog of sources to which the limit will be applied.
333 selected : `numpy.ndarray`
334 Boolean array indicating for each source whether it
is selected
335 (
True means selected).
342 signalToNoise = flux/err
343 selected &= BaseLimit.apply(self, signalToNoise)
348 """Select sources using a magnitude error limit
350 Because the magnitude error is the inverse of the signal-to-noise
351 ratio, this also works to select sources by signal-to-noise when
352 you only have a magnitude.
355 the limit,
and then the `apply` method can be used to identify sources
356 in the catalog that match the configured limit.
358 magErrField = pexConfig.Field(dtype=str, default="mag_err",
359 doc=
"Name of the source flux error field to use.")
362 """Apply the magnitude error limits to a catalog
367 Catalog of sources to which the limit will be applied.
371 selected : `numpy.ndarray`
372 Boolean array indicating for each source whether it
is selected
373 (
True means selected).
375 return BaseLimit.apply(self, catalog[self.
magErrField])
379 """Select sources using flags
382 the limit,
and then the `apply` method can be used to identify sources
383 in the catalog that match the configured limit.
385 good = pexConfig.ListField(dtype=str, default=[],
386 doc="List of source flag fields that must be set for a source to be used.")
387 bad = pexConfig.ListField(dtype=str, default=[],
388 doc=
"List of source flag fields that must NOT be set for a source to be used.")
391 """Apply the flag requirements to a catalog
393 Returns whether the source is selected.
398 Catalog of sources to which the requirements will be applied.
402 selected : `numpy.ndarray`
403 Boolean array indicating
for each source whether it
is selected
404 (
True means selected).
406 selected = np.ones(len(catalog), dtype=bool)
407 for flag
in self.
good:
408 selected &= catalog[flag]
409 for flag
in self.
bad:
410 selected &= ~catalog[flag]
415 """Select sources using star/galaxy separation
418 the limit,
and then the `apply` method can be used to identify sources
419 in the catalog that match the configured limit.
421 name = pexConfig.Field(dtype=str, default="base_ClassificationExtendedness_value",
422 doc=
"Name of column for star/galaxy separation")
427 ``base_ClassificationExtendedness_value < 0.5`` means unresolved.
432 """Apply the flag requirements to a catalog
434 Returns whether the source is selected.
439 Catalog of sources to which the requirements will be applied.
443 selected : `numpy.ndarray`
444 Boolean array indicating
for each source whether it
is selected
445 (
True means selected).
447 value = catalog[self.name]
448 return BaseLimit.apply(self, value)
452 """Select sources based on whether they are isolated
455 the column names to check
for "parent" and "nChild" keys.
457 Note that this should only be run on a catalog that has had the
458 deblender already run (
or else deblend_nChild does
not exist).
460 parentName = pexConfig.Field(dtype=str, default="parent",
461 doc=
"Name of column for parent")
462 nChildName = pexConfig.Field(dtype=str, default=
"deblend_nChild",
463 doc=
"Name of column for nChild")
466 """Apply the isolation requirements to a catalog
468 Returns whether the source is selected.
473 Catalog of sources to which the requirements will be applied.
477 selected : `numpy.ndarray`
478 Boolean array indicating
for each source whether it
is selected
479 (
True means selected).
487 """Select sources that have finite RA and Dec sky coordinate values
490 the column names to check
for "coord_ra" and "coord_dec" keys.
492 This will select against objects
for which either the RA
or Dec coordinate
493 entries are
not numpy.isfinite().
495 raColName = pexConfig.Field(dtype=str, default="coord_ra", doc=
"Name of column for RA coordinate")
496 decColName = pexConfig.Field(dtype=str, default=
"coord_dec", doc=
"Name of column for Dec coordinate")
499 """Apply the sky coordinate requirements to a catalog
501 Returns whether the sources were selected.
506 or `astropy.table.Table`
507 Catalog of sources to which the requirements will be applied.
511 selected : `numpy.ndarray`
512 Boolean array indicating
for each source whether it
is selected
513 (
True means selected).
521 """Select sources that have the detect_isPrimary flag set.
524 the column names to check
for "detect_isPrimary". For single frame
525 catalogs this will be
True when the source
is not a sky object,
and is
526 either an isolated parent that
is un-modeled
or deblended
from a parent
527 with multiple children. For meas_deblender, this
is equivalent to
528 deblend_nChild=0. For coadd catalogs there
is an additional constraint
529 that the source
is located on the interior of a patch
and tract.
531 primaryColName = pexConfig.Field(
533 default="detect_isPrimary",
534 doc=
"Name of primary flag column",
538 """Apply the primary requirements to a catalog.
540 Returns whether the sources were selected.
545 or `astropy.table.Table`
546 Catalog of sources to which the requirement will be applied.
550 selected : `numpy.ndarray`
551 Boolean array indicating
for each source whether it
is selected
552 (
True means selected).
560 """Configuration for selecting science sources"""
561 doFluxLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flux limit?")
562 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
563 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
564 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
565 doIsolated = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply isolated limitation?")
566 doRequireFiniteRaDec = pexConfig.Field(dtype=bool, default=
False,
567 doc=
"Apply finite sky coordinate check?")
568 doRequirePrimary = pexConfig.Field(dtype=bool, default=
False,
569 doc=
"Apply source is primary check?")
570 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc=
"Flux limit to apply")
571 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
572 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
573 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
574 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc=
"Isolated criteria to apply")
575 requireFiniteRaDec = pexConfig.ConfigField(dtype=RequireFiniteRaDec,
576 doc=
"Finite sky coordinate criteria to apply")
577 requirePrimary = pexConfig.ConfigField(dtype=RequirePrimary,
578 doc=
"Primary source criteria to apply")
581 pexConfig.Config.setDefaults(self)
582 self.
flags.bad = [
"base_PixelFlags_flag_edge",
"base_PixelFlags_flag_saturated",
"base_PsfFlux_flag"]
587@pexConfig.registerConfigurable("science", sourceSelectorRegistry)
589 """Science source selector
591 By "science" sources, we mean sources that are on images that we
592 are processing,
as opposed to sources
from reference catalogs.
594 This selects (science) sources by (optionally) applying each of a
595 magnitude limit, flag requirements
and star/galaxy separation.
597 ConfigClass = ScienceSourceSelectorConfig
600 """Return a selection of sources selected by specified criteria.
605 Catalog of sources to select from.
606 This catalog must be contiguous
in memory.
608 Ignored
in this SourceSelector.
610 The exposure the catalog was built
from; used
for debug display.
614 struct : `lsst.pipe.base.Struct`
615 The struct contains the following data:
618 Boolean array of sources that were selected, same length
as
620 (`numpy.ndarray` of `bool`)
622 selected = np.ones(len(sourceCat), dtype=bool)
623 if self.config.doFluxLimit:
624 selected &= self.config.fluxLimit.apply(sourceCat)
625 if self.config.doFlags:
626 selected &= self.config.flags.apply(sourceCat)
627 if self.config.doUnresolved:
628 selected &= self.config.unresolved.apply(sourceCat)
629 if self.config.doSignalToNoise:
630 selected &= self.config.signalToNoise.apply(sourceCat)
631 if self.config.doIsolated:
632 selected &= self.config.isolated.apply(sourceCat)
633 if self.config.doRequireFiniteRaDec:
634 selected &= self.config.requireFiniteRaDec.apply(sourceCat)
635 if self.config.doRequirePrimary:
636 selected &= self.config.requirePrimary.apply(sourceCat)
638 self.log.info(
"Selected %d/%d sources", selected.sum(), len(sourceCat))
640 return pipeBase.Struct(selected=selected)
644 doMagLimit = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude limit?")
645 doFlags = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply flag limitation?")
646 doUnresolved = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply unresolved limitation?")
647 doSignalToNoise = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply signal-to-noise limit?")
648 doMagError = pexConfig.Field(dtype=bool, default=
False, doc=
"Apply magnitude error limit?")
649 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc=
"Magnitude limit to apply")
650 flags = pexConfig.ConfigField(dtype=RequireFlags, doc=
"Flags to require")
651 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc=
"Star/galaxy separation to apply")
652 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc=
"Signal-to-noise limit to apply")
653 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc=
"Magnitude error limit to apply")
654 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
655 doc=
"Color limits to apply; key is used as a label only")
658@pexConfig.registerConfigurable("references", sourceSelectorRegistry)
660 """Reference source selector
662 This selects reference sources by (optionally) applying each of a
663 magnitude limit, flag requirements and color limits.
665 ConfigClass = ReferenceSourceSelectorConfig
668 """Return a selection of reference sources selected by some criteria.
673 Catalog of sources to select from.
674 This catalog must be contiguous
in memory.
676 Ignored
in this SourceSelector.
678 The exposure the catalog was built
from; used
for debug display.
682 struct : `lsst.pipe.base.Struct`
683 The struct contains the following data:
686 Boolean array of sources that were selected, same length
as
688 (`numpy.ndarray` of `bool`)
690 selected = np.ones(len(sourceCat), dtype=bool)
691 if self.config.doMagLimit:
692 selected &= self.config.magLimit.apply(sourceCat)
693 if self.config.doFlags:
694 selected &= self.config.flags.apply(sourceCat)
695 if self.config.doUnresolved:
696 selected &= self.config.unresolved.apply(sourceCat)
697 if self.config.doSignalToNoise:
698 selected &= self.config.signalToNoise.apply(sourceCat)
699 if self.config.doMagError:
700 selected &= self.config.magError.apply(sourceCat)
701 for limit
in self.config.colorLimits.values():
702 selected &= limit.apply(sourceCat)
704 self.log.info(
"Selected %d/%d references", selected.sum(), len(sourceCat))
706 return pipeBase.Struct(selected=selected)
709@pexConfig.registerConfigurable("null", sourceSelectorRegistry)
711 """Source selector that returns true for all sources.
713 Use this when you do not want any sub-selection on your inputs.
715 ConfigClass = BaseSourceSelectorConfig
719 return pipeBase.Struct(selected=np.ones(len(sourceCat), dtype=bool))
725 `pandas.DataFrame`
or `astropy.table.Table` catalogs.
730 or `astropy.table.Table`
731 Catalog of sources to extract field array
734 isFlag : `bool`, optional
735 Is this a flag column? If it does
not exist,
return array
741 Array of field values
from the catalog.
744 if isinstance(catalog, (pandas.DataFrame, astropy.table.Table)):
745 if field
in catalog.columns:
748 arr = np.array(catalog[field])
750 if field
in catalog.schema:
754 if isFlag
and not found:
755 arr = np.zeros(len(catalog), dtype=bool)
757 raise KeyError(f
"Could not find field {field} in catalog.")
A class to contain the data, WCS, and other information needed to describe an image of the sky.
selectSources(self, sourceCat, matches=None, exposure=None)
selectSources(self, sourceCat, **kwargs)
selectSources(self, sourceCat, matches=None, exposure=None)
selectSources(self, sourceCat, matches=None, exposure=None)
_getFieldFromCatalog(catalog, field, isFlag=False)
Lightweight representation of a geometric match between two records.