lsst.meas.algorithms gee31e0d7c8+667bae79af
Loading...
Searching...
No Matches
sourceSelector.py
Go to the documentation of this file.
1# This file is part of meas_algorithms.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22__all__ = ["BaseSourceSelectorConfig", "BaseSourceSelectorTask", "sourceSelectorRegistry",
23 "ColorLimit", "MagnitudeLimit", "SignalToNoiseLimit", "MagnitudeErrorLimit",
24 "RequireFlags", "RequireUnresolved", "RequireFiniteRaDec", "RequirePrimary",
25 "ScienceSourceSelectorConfig", "ScienceSourceSelectorTask",
26 "ReferenceSourceSelectorConfig", "ReferenceSourceSelectorTask",
27 ]
28
29import abc
30import numpy as np
31import astropy.units as u
32import pandas
33import astropy.table
34
35import lsst.pex.config as pexConfig
36import lsst.pipe.base as pipeBase
37
38
39class BaseSourceSelectorConfig(pexConfig.Config):
40 pass
41
42
43class BaseSourceSelectorTask(pipeBase.Task, metaclass=abc.ABCMeta):
44 """Base class for source selectors
45
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.
50
51 Register all source selectors with the sourceSelectorRegistry using:
52 sourceSelectorRegistry.register(name, class)
53
54 Attributes
55 ----------
56 usesMatches : `bool`
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()``.
60 """
61
62 ConfigClass = BaseSourceSelectorConfig
63 _DefaultName = "sourceSelector"
64 usesMatches = False
65
66 def __init__(self, **kwargs):
67 pipeBase.Task.__init__(self, **kwargs)
68
69 def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None):
70 """Select sources and return them.
71
72 The input catalog must be contiguous in memory.
73
74 Parameters
75 ----------
76 sourceCat : Various table formats
77 Catalog of sources to select from. Can be
78 `lsst.afw.table.SourceCatalog` or `pandas.DataFrame` or
79 `astropy.table.Table`,
80 sourceSelectedField : `str` or None
81 Name of flag field in sourceCat to set for selected sources.
82 If set, will modify sourceCat in-place.
83 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
84 List of matches to use for source selection.
85 If usesMatches is set in source selector this field is required.
86 If not, it is ignored.
87 exposure : `lsst.afw.image.Exposure` or None
88 The exposure the catalog was built from; used for debug display.
89
90 Returns
91 -------
92 struct : `lsst.pipe.base.Struct`
93 The struct contains the following data:
94
95 ``sourceCat``
96 The catalog of sources that were selected.
97 (may not be memory-contiguous)
98 (`lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
99 or `astropy.table.Table`)
100 ``selected``
101 Boolean array of sources that were selected, same length as
102 sourceCat.
103 (`numpy.ndarray` of `bool`)
104
105 Raises
106 ------
107 RuntimeError
108 Raised if ``sourceCat`` is not contiguous.
109 """
110 if hasattr(sourceCat, 'isContiguous'):
111 # Check for continuity on afwTable catalogs
112 if not sourceCat.isContiguous():
113 raise RuntimeError("Input catalogs for source selection must be contiguous.")
114
115 result = self.selectSources(sourceCat=sourceCat,
116 exposure=exposure,
117 matches=matches)
118
119 if sourceSelectedField is not None:
120 sourceCat[sourceSelectedField] = result.selected
121
122 return pipeBase.Struct(sourceCat=sourceCat[result.selected],
123 selected=result.selected)
124
125 @abc.abstractmethod
126 def selectSources(self, sourceCat, matches=None, exposure=None):
127 """Return a selection of sources selected by some criteria.
128
129 Parameters
130 ----------
131 sourceCat : Various table formats
132 Catalog of sources to select from. Supports
133 `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
134 or `astropy.table.Table`
135 This catalog must be contiguous in memory.
136 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
137 A list of lsst.afw.table.ReferenceMatch objects
138 exposure : `lsst.afw.image.Exposure` or None
139 The exposure the catalog was built from; used for debug display.
140
141 Returns
142 -------
143 struct : `lsst.pipe.base.Struct`
144 The struct contains the following data:
145
146 ``selected``
147 Boolean array of sources that were selected, same length as
148 sourceCat.
149 (`numpy.ndarray` of `bool`)
150 """
151 raise NotImplementedError("BaseSourceSelectorTask is abstract")
152
153
154sourceSelectorRegistry = pexConfig.makeRegistry(
155 doc="A registry of source selectors (subclasses of "
156 "BaseSourceSelectorTask)",
157)
158
159
160class BaseLimit(pexConfig.Config):
161 """Base class for selecting sources by applying a limit
162
163 This object can be used as a `lsst.pex.config.Config` for configuring
164 the limit, and then the `apply` method can be used to identify sources
165 in the catalog that match the configured limit.
166
167 This provides the `maximum` and `minimum` fields in the Config, and
168 a method to apply the limits to an array of values calculated by the
169 subclass.
170 """
171 minimum = pexConfig.Field(dtype=float, optional=True, doc="Select objects with value greater than this")
172 maximum = pexConfig.Field(dtype=float, optional=True, doc="Select objects with value less than this")
173
174 def apply(self, values):
175 """Apply the limits to an array of values
176
177 Subclasses should calculate the array of values and then
178 return the result of calling this method.
179
180 Parameters
181 ----------
182 values : `numpy.ndarray`
183 Array of values to which to apply limits.
184
185 Returns
186 -------
187 selected : `numpy.ndarray`
188 Boolean array indicating for each source whether it is selected
189 (True means selected).
190 """
191 selected = np.ones(len(values), dtype=bool)
192 with np.errstate(invalid="ignore"): # suppress NAN warnings
193 if self.minimum is not None:
194 selected &= values > self.minimum
195 if self.maximum is not None:
196 selected &= values < self.maximum
197 return selected
198
199
201 """Select sources using a color limit
202
203 This object can be used as a `lsst.pex.config.Config` for configuring
204 the limit, and then the `apply` method can be used to identify sources
205 in the catalog that match the configured limit.
206
207 We refer to 'primary' and 'secondary' flux measurements; these are the
208 two components of the color, which is:
209
210 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary])
211 """
212 primary = pexConfig.Field(dtype=str, doc="Name of column with primary flux measurement")
213 secondary = pexConfig.Field(dtype=str, doc="Name of column with secondary flux measurement")
214
215 def apply(self, catalog):
216 """Apply the color limit to a catalog
217
218 Parameters
219 ----------
220 catalog : Various table formats
221 Catalog of sources to which the limit will be applied.
222 Supports `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
223 or `astropy.table.Table`
224
225 Returns
226 -------
227 selected : `numpy.ndarray`
228 Boolean array indicating for each source whether it is selected
229 (True means selected).
230 """
231 primary = _getFieldFromCatalog(catalog, self.primary)
232 secondary = _getFieldFromCatalog(catalog, self.secondary)
233
234 primary = (primary*u.nJy).to_value(u.ABmag)
235 secondary = (secondary*u.nJy).to_value(u.ABmag)
236 color = primary - secondary
237 return BaseLimit.apply(self, color)
238
239
241 """Select sources using a flux limit
242
243 This object can be used as a `lsst.pex.config.Config` for configuring
244 the limit, and then the `apply` method can be used to identify sources
245 in the catalog that match the configured limit.
246 """
247 fluxField = pexConfig.Field(dtype=str, default="slot_CalibFlux_instFlux",
248 doc="Name of the source flux field to use.")
249
250 def apply(self, catalog):
251 """Apply the flux limits to a catalog
252
253 Parameters
254 ----------
256 Catalog of sources to which the limit will be applied.
257
258 Returns
259 -------
260 selected : `numpy.ndarray`
261 Boolean array indicating for each source whether it is selected
262 (True means selected).
263 """
264 flagField = self.fluxField + "_flag"
265 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
266 flux = _getFieldFromCatalog(catalog, self.fluxField)
267
268 selected &= BaseLimit.apply(self, flux)
269 return selected
270
271
273 """Select sources using a magnitude limit
274
275 Note that this assumes that a zero-point has already been applied and
276 the fluxes are in AB fluxes in Jansky. It is therefore principally
277 intended for reference catalogs rather than catalogs extracted from
278 science images.
279
280 This object can be used as a `lsst.pex.config.Config` for configuring
281 the limit, and then the `apply` method can be used to identify sources
282 in the catalog that match the configured limit.
283 """
284 fluxField = pexConfig.Field(dtype=str, default="flux",
285 doc="Name of the source flux field to use.")
286
287 def apply(self, catalog):
288 """Apply the magnitude limits to a catalog
289
290 Parameters
291 ----------
293 Catalog of sources to which the limit will be applied.
294
295 Returns
296 -------
297 selected : `numpy.ndarray`
298 Boolean array indicating for each source whether it is selected
299 (True means selected).
300 """
301 flagField = self.fluxField + "_flag"
302 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
303 flux = _getFieldFromCatalog(catalog, self.fluxField)
304
305 magnitude = (flux*u.nJy).to_value(u.ABmag)
306 selected &= BaseLimit.apply(self, magnitude)
307 return selected
308
309
311 """Select sources using a flux signal-to-noise limit
312
313 This object can be used as a `lsst.pex.config.Config` for configuring
314 the limit, and then the `apply` method can be used to identify sources
315 in the catalog that match the configured limit.
316 """
317 fluxField = pexConfig.Field(dtype=str, default="flux",
318 doc="Name of the source flux field to use.")
319 errField = pexConfig.Field(dtype=str, default="flux_err",
320 doc="Name of the source flux error field to use.")
321
322 def apply(self, catalog):
323 """Apply the signal-to-noise limits to a catalog
324
325 Parameters
326 ----------
328 Catalog of sources to which the limit will be applied.
329
330 Returns
331 -------
332 selected : `numpy.ndarray`
333 Boolean array indicating for each source whether it is selected
334 (True means selected).
335 """
336 flagField = self.fluxField + "_flag"
337 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
338 flux = _getFieldFromCatalog(catalog, self.fluxField)
339 err = _getFieldFromCatalog(catalog, self.errField)
340
341 signalToNoise = flux/err
342 selected &= BaseLimit.apply(self, signalToNoise)
343 return selected
344
345
347 """Select sources using a magnitude error limit
348
349 Because the magnitude error is the inverse of the signal-to-noise
350 ratio, this also works to select sources by signal-to-noise when
351 you only have a magnitude.
352
353 This object can be used as a `lsst.pex.config.Config` for configuring
354 the limit, and then the `apply` method can be used to identify sources
355 in the catalog that match the configured limit.
356 """
357 magErrField = pexConfig.Field(dtype=str, default="mag_err",
358 doc="Name of the source flux error field to use.")
359
360 def apply(self, catalog):
361 """Apply the magnitude error limits to a catalog
362
363 Parameters
364 ----------
366 Catalog of sources to which the limit will be applied.
367
368 Returns
369 -------
370 selected : `numpy.ndarray`
371 Boolean array indicating for each source whether it is selected
372 (True means selected).
373 """
374 return BaseLimit.apply(self, catalog[self.magErrField])
375
376
377class RequireFlags(pexConfig.Config):
378 """Select sources using flags
379
380 This object can be used as a `lsst.pex.config.Config` for configuring
381 the limit, and then the `apply` method can be used to identify sources
382 in the catalog that match the configured limit.
383 """
384 good = pexConfig.ListField(dtype=str, default=[],
385 doc="List of source flag fields that must be set for a source to be used.")
386 bad = pexConfig.ListField(dtype=str, default=[],
387 doc="List of source flag fields that must NOT be set for a source to be used.")
388
389 def apply(self, catalog):
390 """Apply the flag requirements to a catalog
391
392 Returns whether the source is selected.
393
394 Parameters
395 ----------
397 Catalog of sources to which the requirements will be applied.
398
399 Returns
400 -------
401 selected : `numpy.ndarray`
402 Boolean array indicating for each source whether it is selected
403 (True means selected).
404 """
405 selected = np.ones(len(catalog), dtype=bool)
406 for flag in self.good:
407 selected &= catalog[flag]
408 for flag in self.bad:
409 selected &= ~catalog[flag]
410 return selected
411
412
414 """Select sources using star/galaxy separation
415
416 This object can be used as a `lsst.pex.config.Config` for configuring
417 the limit, and then the `apply` method can be used to identify sources
418 in the catalog that match the configured limit.
419 """
420 name = pexConfig.Field(dtype=str, default="base_ClassificationExtendedness_value",
421 doc="Name of column for star/galaxy separation")
422
423 def setDefaults(self):
424 """Set default
425
426 ``base_ClassificationExtendedness_value < 0.5`` means unresolved.
427 """
428 self.maximummaximum = 0.5
429
430 def apply(self, catalog):
431 """Apply the flag requirements to a catalog
432
433 Returns whether the source is selected.
434
435 Parameters
436 ----------
438 Catalog of sources to which the requirements will be applied.
439
440 Returns
441 -------
442 selected : `numpy.ndarray`
443 Boolean array indicating for each source whether it is selected
444 (True means selected).
445 """
446 value = catalog[self.name]
447 return BaseLimit.apply(self, value)
448
449
450class RequireIsolated(pexConfig.Config):
451 """Select sources based on whether they are isolated
452
453 This object can be used as a `lsst.pex.config.Config` for configuring
454 the column names to check for "parent" and "nChild" keys.
455
456 Note that this should only be run on a catalog that has had the
457 deblender already run (or else deblend_nChild does not exist).
458 """
459 parentName = pexConfig.Field(dtype=str, default="parent",
460 doc="Name of column for parent")
461 nChildName = pexConfig.Field(dtype=str, default="deblend_nChild",
462 doc="Name of column for nChild")
463
464 def apply(self, catalog):
465 """Apply the isolation requirements to a catalog
466
467 Returns whether the source is selected.
468
469 Parameters
470 ----------
472 Catalog of sources to which the requirements will be applied.
473
474 Returns
475 -------
476 selected : `numpy.ndarray`
477 Boolean array indicating for each source whether it is selected
478 (True means selected).
479 """
480 selected = ((catalog[self.parentName] == 0)
481 & (catalog[self.nChildName] == 0))
482 return selected
483
484
485class RequireFiniteRaDec(pexConfig.Config):
486 """Select sources that have finite RA and Dec sky coordinate values
487
488 This object can be used as a `lsst.pex.config.Config` for configuring
489 the column names to check for "coord_ra" and "coord_dec" keys.
490
491 This will select against objects for which either the RA or Dec coordinate
492 entries are not numpy.isfinite().
493 """
494 raColName = pexConfig.Field(dtype=str, default="coord_ra", doc="Name of column for RA coordinate")
495 decColName = pexConfig.Field(dtype=str, default="coord_dec", doc="Name of column for Dec coordinate")
496
497 def apply(self, catalog):
498 """Apply the sky coordinate requirements to a catalog
499
500 Returns whether the sources were selected.
501
502 Parameters
503 ----------
504 catalog : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
505 or `astropy.table.Table`
506 Catalog of sources to which the requirements will be applied.
507
508 Returns
509 -------
510 selected : `numpy.ndarray`
511 Boolean array indicating for each source whether it is selected
512 (True means selected).
513 """
514 selected = (np.isfinite(_getFieldFromCatalog(catalog, self.raColName))
515 & np.isfinite(_getFieldFromCatalog(catalog, self.decColName)))
516 return selected
517
518
519class RequirePrimary(pexConfig.Config):
520 """Select sources that have the detect_isPrimary flag set.
521
522 This object can be used as a `lsst.pex.config.Config` for configuring
523 the column names to check for "detect_isPrimary". For single frame
524 catalogs this will be True when the source is not a sky object, and is
525 either an isolated parent that is un-modeled or deblended from a parent
526 with multiple children. For meas_deblender, this is equivalent to
527 deblend_nChild=0. For coadd catalogs there is an additional constraint
528 that the source is located on the interior of a patch and tract.
529 """
530 primaryColName = pexConfig.Field(
531 dtype=str,
532 default="detect_isPrimary",
533 doc="Name of primary flag column",
534 )
535
536 def apply(self, catalog):
537 """Apply the primary requirements to a catalog.
538
539 Returns whether the sources were selected.
540
541 Parameters
542 ----------
543 catalog : lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
544 or `astropy.table.Table`
545 Catalog of sources to which the requirement will be applied.
546
547 Returns
548 -------
549 selected : `numpy.ndarray`
550 Boolean array indicating for each source whether it is selected
551 (True means selected).
552 """
553 selected = (_getFieldFromCatalog(catalog, self.primaryColName)).astype(bool)
554
555 return selected
556
557
558class ScienceSourceSelectorConfig(pexConfig.Config):
559 """Configuration for selecting science sources"""
560 doFluxLimit = pexConfig.Field(dtype=bool, default=False, doc="Apply flux limit?")
561 doFlags = pexConfig.Field(dtype=bool, default=False, doc="Apply flag limitation?")
562 doUnresolved = pexConfig.Field(dtype=bool, default=False, doc="Apply unresolved limitation?")
563 doSignalToNoise = pexConfig.Field(dtype=bool, default=False, doc="Apply signal-to-noise limit?")
564 doIsolated = pexConfig.Field(dtype=bool, default=False, doc="Apply isolated limitation?")
565 doRequireFiniteRaDec = pexConfig.Field(dtype=bool, default=False,
566 doc="Apply finite sky coordinate check?")
567 doRequirePrimary = pexConfig.Field(dtype=bool, default=False,
568 doc="Apply source is primary check?")
569 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc="Flux limit to apply")
570 flags = pexConfig.ConfigField(dtype=RequireFlags, doc="Flags to require")
571 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc="Star/galaxy separation to apply")
572 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc="Signal-to-noise limit to apply")
573 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc="Isolated criteria to apply")
574 requireFiniteRaDec = pexConfig.ConfigField(dtype=RequireFiniteRaDec,
575 doc="Finite sky coordinate criteria to apply")
576 requirePrimary = pexConfig.ConfigField(dtype=RequirePrimary,
577 doc="Primary source criteria to apply")
578
579 def setDefaults(self):
580 pexConfig.Config.setDefaults(self)
581 self.flags.bad = ["base_PixelFlags_flag_edge", "base_PixelFlags_flag_saturated", "base_PsfFlux_flags"]
582 self.signalToNoise.fluxField = "base_PsfFlux_instFlux"
583 self.signalToNoise.errField = "base_PsfFlux_instFluxErr"
584
585
586@pexConfig.registerConfigurable("science", sourceSelectorRegistry)
588 """Science source selector
589
590 By "science" sources, we mean sources that are on images that we
591 are processing, as opposed to sources from reference catalogs.
592
593 This selects (science) sources by (optionally) applying each of a
594 magnitude limit, flag requirements and star/galaxy separation.
595 """
596 ConfigClass = ScienceSourceSelectorConfig
597
598 def selectSources(self, sourceCat, matches=None, exposure=None):
599 """Return a selection of sources selected by specified criteria.
600
601 Parameters
602 ----------
603 sourceCat : `lsst.afw.table.SourceCatalog`
604 Catalog of sources to select from.
605 This catalog must be contiguous in memory.
606 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
607 Ignored in this SourceSelector.
608 exposure : `lsst.afw.image.Exposure` or None
609 The exposure the catalog was built from; used for debug display.
610
611 Returns
612 -------
613 struct : `lsst.pipe.base.Struct`
614 The struct contains the following data:
615
616 ``selected``
617 Boolean array of sources that were selected, same length as
618 sourceCat.
619 (`numpy.ndarray` of `bool`)
620 """
621 selected = np.ones(len(sourceCat), dtype=bool)
622 if self.config.doFluxLimit:
623 selected &= self.config.fluxLimit.apply(sourceCat)
624 if self.config.doFlags:
625 selected &= self.config.flags.apply(sourceCat)
626 if self.config.doUnresolved:
627 selected &= self.config.unresolved.apply(sourceCat)
628 if self.config.doSignalToNoise:
629 selected &= self.config.signalToNoise.apply(sourceCat)
630 if self.config.doIsolated:
631 selected &= self.config.isolated.apply(sourceCat)
632 if self.config.doRequireFiniteRaDec:
633 selected &= self.config.requireFiniteRaDec.apply(sourceCat)
634 if self.config.doRequirePrimary:
635 selected &= self.config.requirePrimary.apply(sourceCat)
636
637 self.log.info("Selected %d/%d sources", selected.sum(), len(sourceCat))
638
639 return pipeBase.Struct(selected=selected)
640
641
642class ReferenceSourceSelectorConfig(pexConfig.Config):
643 doMagLimit = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude limit?")
644 doFlags = pexConfig.Field(dtype=bool, default=False, doc="Apply flag limitation?")
645 doUnresolved = pexConfig.Field(dtype=bool, default=False, doc="Apply unresolved limitation?")
646 doSignalToNoise = pexConfig.Field(dtype=bool, default=False, doc="Apply signal-to-noise limit?")
647 doMagError = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude error limit?")
648 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc="Magnitude limit to apply")
649 flags = pexConfig.ConfigField(dtype=RequireFlags, doc="Flags to require")
650 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc="Star/galaxy separation to apply")
651 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc="Signal-to-noise limit to apply")
652 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc="Magnitude error limit to apply")
653 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
654 doc="Color limits to apply; key is used as a label only")
655
656
657@pexConfig.registerConfigurable("references", sourceSelectorRegistry)
659 """Reference source selector
660
661 This selects reference sources by (optionally) applying each of a
662 magnitude limit, flag requirements and color limits.
663 """
664 ConfigClass = ReferenceSourceSelectorConfig
665
666 def selectSources(self, sourceCat, matches=None, exposure=None):
667 """Return a selection of reference sources selected by some criteria.
668
669 Parameters
670 ----------
671 sourceCat : `lsst.afw.table.SourceCatalog`
672 Catalog of sources to select from.
673 This catalog must be contiguous in memory.
674 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
675 Ignored in this SourceSelector.
676 exposure : `lsst.afw.image.Exposure` or None
677 The exposure the catalog was built from; used for debug display.
678
679 Returns
680 -------
681 struct : `lsst.pipe.base.Struct`
682 The struct contains the following data:
683
684 ``selected``
685 Boolean array of sources that were selected, same length as
686 sourceCat.
687 (`numpy.ndarray` of `bool`)
688 """
689 selected = np.ones(len(sourceCat), dtype=bool)
690 if self.config.doMagLimit:
691 selected &= self.config.magLimit.apply(sourceCat)
692 if self.config.doFlags:
693 selected &= self.config.flags.apply(sourceCat)
694 if self.config.doUnresolved:
695 selected &= self.config.unresolved.apply(sourceCat)
696 if self.config.doSignalToNoise:
697 selected &= self.config.signalToNoise.apply(sourceCat)
698 if self.config.doMagError:
699 selected &= self.config.magError.apply(sourceCat)
700 for limit in self.config.colorLimits.values():
701 selected &= limit.apply(sourceCat)
702
703 self.log.info("Selected %d/%d references", selected.sum(), len(sourceCat))
704
705 return pipeBase.Struct(selected=selected)
706
707
708def _getFieldFromCatalog(catalog, field, isFlag=False):
709 """
710 Get a field from a catalog, for `lsst.afw.table` catalogs or
711 `pandas.DataFrame` or `astropy.table.Table` catalogs.
712
713 Parameters
714 ----------
715 catalog : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
716 or `astropy.table.Table`
717 Catalog of sources to extract field array
718 field : `str`
719 Name of field
720 isFlag : `bool`, optional
721 Is this a flag column? If it does not exist, return array
722 of False.
723
724 Returns
725 -------
726 array : `np.ndarray`
727 Array of field values from the catalog.
728 """
729 found = False
730 if isinstance(catalog, (pandas.DataFrame, astropy.table.Table)):
731 if field in catalog.columns:
732 found = True
733 # Sequences must be converted to numpy arrays
734 arr = np.array(catalog[field])
735 else:
736 if field in catalog.schema:
737 found = True
738 arr = catalog[field]
739
740 if isFlag and not found:
741 arr = np.zeros(len(catalog), dtype=bool)
742 elif not found:
743 raise KeyError(f"Could not find field {field} in catalog.")
744
745 return arr
run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None)
selectSources(self, sourceCat, matches=None, exposure=None)
selectSources(self, sourceCat, matches=None, exposure=None)
selectSources(self, sourceCat, matches=None, exposure=None)
_getFieldFromCatalog(catalog, field, isFlag=False)