LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
LSST Data Management Base Package
sourceSelector.py
Go to the documentation of this file.
2# LSST Data Management System
3#
4# Copyright 2008-2017 AURA/LSST.
5#
6# This product includes software developed by the
7# LSST Project (http://www.lsst.org/).
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 LSST License Statement and
20# the GNU General Public License along with this program. If not,
21# see <https://www.lsstcorp.org/LegalNotices/>.
22#
23
24__all__ = ["BaseSourceSelectorConfig", "BaseSourceSelectorTask", "sourceSelectorRegistry",
25 "ColorLimit", "MagnitudeLimit", "SignalToNoiseLimit", "MagnitudeErrorLimit",
26 "RequireFlags", "RequireUnresolved",
27 "ScienceSourceSelectorConfig", "ScienceSourceSelectorTask",
28 "ReferenceSourceSelectorConfig", "ReferenceSourceSelectorTask",
29 ]
30
31import abc
32import numpy as np
33import astropy.units as u
34import pandas
35import astropy.table
36
37import lsst.pex.config as pexConfig
38import lsst.pipe.base as pipeBase
39
40
41class BaseSourceSelectorConfig(pexConfig.Config):
42 pass
43
44
45class BaseSourceSelectorTask(pipeBase.Task, metaclass=abc.ABCMeta):
46 """Base class for source selectors
47
48 Source selectors are classes that perform a selection on a catalog
49 object given a set of criteria or cuts. They return the selected catalog
50 and can optionally set a specified Flag field in the input catalog to
51 identify if the source was selected.
52
53 Register all source selectors with the sourceSelectorRegistry using:
54 sourceSelectorRegistry.register(name, class)
55
56 Attributes
57 ----------
58 usesMatches : `bool`
59 A boolean variable specify if the inherited source selector uses
60 matches to an external catalog, and thus requires the ``matches``
61 argument to ``run()``.
62 """
63
64 ConfigClass = BaseSourceSelectorConfig
65 _DefaultName = "sourceSelector"
66 usesMatches = False
67
68 def __init__(self, **kwargs):
69 pipeBase.Task.__init__(self, **kwargs)
70
71 def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None):
72 """Select sources and return them.
73
74 The input catalog must be contiguous in memory.
75
76 Parameters:
77 -----------
78 sourceCat : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
79 or `astropy.table.Table`
80 Catalog of sources to select from.
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.
84 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
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.
88 exposure : `lsst.afw.image.Exposure` or None
89 The exposure the catalog was built from; used for debug display.
90
91 Return
92 ------
93 struct : `lsst.pipe.base.Struct`
94 The struct contains the following data:
95
96 - sourceCat : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
97 or `astropy.table.Table`
98 The catalog of sources that were selected.
99 (may not be memory-contiguous)
100 - selected : `numpy.ndarray` of `bool``
101 Boolean array of sources that were selected, same length as
102 sourceCat.
103
104 Raises
105 ------
106 RuntimeError
107 Raised if ``sourceCat`` is not contiguous.
108 """
109 if hasattr(sourceCat, 'isContiguous'):
110 # Check for continuity on afwTable catalogs
111 if not sourceCat.isContiguous():
112 raise RuntimeError("Input catalogs for source selection must be contiguous.")
113
114 result = self.selectSourcesselectSources(sourceCat=sourceCat,
115 exposure=exposure,
116 matches=matches)
117
118 if sourceSelectedField is not None:
119 if isinstance(sourceCat, (pandas.DataFrame, astropy.table.Table)):
120 sourceCat[sourceSelectedField] = result.selected
121 else:
122 source_selected_key = \
123 sourceCat.getSchema()[sourceSelectedField].asKey()
124 # TODO: Remove for loop when DM-6981 is completed.
125 for source, flag in zip(sourceCat, result.selected):
126 source.set(source_selected_key, bool(flag))
127 return pipeBase.Struct(sourceCat=sourceCat[result.selected],
128 selected=result.selected)
129
130 @abc.abstractmethod
131 def selectSources(self, sourceCat, matches=None, exposure=None):
132 """Return a selection of sources selected by some criteria.
133
134 Parameters
135 ----------
136 sourceCat : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
137 or `astropy.table.Table`
138 Catalog of sources to select from.
139 This catalog must be contiguous in memory.
140 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
141 A list of lsst.afw.table.ReferenceMatch objects
142 exposure : `lsst.afw.image.Exposure` or None
143 The exposure the catalog was built from; used for debug display.
144
145 Return
146 ------
147 struct : `lsst.pipe.base.Struct`
148 The struct contains the following data:
149
150 - selected : `numpy.ndarray` of `bool``
151 Boolean array of sources that were selected, same length as
152 sourceCat.
153 """
154 raise NotImplementedError("BaseSourceSelectorTask is abstract")
155
156
157sourceSelectorRegistry = pexConfig.makeRegistry(
158 doc="A registry of source selectors (subclasses of "
159 "BaseSourceSelectorTask)",
160)
161
162
163class BaseLimit(pexConfig.Config):
164 """Base class for selecting sources by applying a limit
165
166 This object can be used as a `lsst.pex.config.Config` for configuring
167 the limit, and then the `apply` method can be used to identify sources
168 in the catalog that match the configured limit.
169
170 This provides the `maximum` and `minimum` fields in the Config, and
171 a method to apply the limits to an array of values calculated by the
172 subclass.
173 """
174 minimum = pexConfig.Field(dtype=float, optional=True, doc="Select objects with value greater than this")
175 maximum = pexConfig.Field(dtype=float, optional=True, doc="Select objects with value less than this")
176
177 def apply(self, values):
178 """Apply the limits to an array of values
179
180 Subclasses should calculate the array of values and then
181 return the result of calling this method.
182
183 Parameters
184 ----------
185 values : `numpy.ndarray`
186 Array of values to which to apply limits.
187
188 Returns
189 -------
190 selected : `numpy.ndarray`
191 Boolean array indicating for each source whether it is selected
192 (True means selected).
193 """
194 selected = np.ones(len(values), dtype=bool)
195 with np.errstate(invalid="ignore"): # suppress NAN warnings
196 if self.minimumminimum is not None:
197 selected &= values > self.minimumminimum
198 if self.maximummaximum is not None:
199 selected &= values < self.maximummaximum
200 return selected
201
202
204 """Select sources using a color limit
205
206 This object can be used as a `lsst.pex.config.Config` for configuring
207 the limit, and then the `apply` method can be used to identify sources
208 in the catalog that match the configured limit.
209
210 We refer to 'primary' and 'secondary' flux measurements; these are the
211 two components of the color, which is:
212
213 instFluxToMag(cat[primary]) - instFluxToMag(cat[secondary])
214 """
215 primary = pexConfig.Field(dtype=str, doc="Name of column with primary flux measurement")
216 secondary = pexConfig.Field(dtype=str, doc="Name of column with secondary flux measurement")
217
218 def apply(self, catalog):
219 """Apply the color limit to a catalog
220
221 Parameters
222 ----------
223 catalog : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
224 or `astropy.table.Table`
225 Catalog of sources to which the limit will be applied.
226
227 Returns
228 -------
229 selected : `numpy.ndarray`
230 Boolean array indicating for each source whether it is selected
231 (True means selected).
232 """
233 primary = _getFieldFromCatalog(catalog, self.primaryprimary)
234 secondary = _getFieldFromCatalog(catalog, self.secondarysecondary)
235
236 primary = (primary*u.nJy).to_value(u.ABmag)
237 secondary = (secondary*u.nJy).to_value(u.ABmag)
238 color = primary - secondary
239 return BaseLimit.apply(self, color)
240
241
243 """Select sources using a flux limit
244
245 This object can be used as a `lsst.pex.config.Config` for configuring
246 the limit, and then the `apply` method can be used to identify sources
247 in the catalog that match the configured limit.
248 """
249 fluxField = pexConfig.Field(dtype=str, default="slot_CalibFlux_instFlux",
250 doc="Name of the source flux field to use.")
251
252 def apply(self, catalog):
253 """Apply the flux limits to a catalog
254
255 Parameters
256 ----------
258 Catalog of sources to which the limit will be applied.
259
260 Returns
261 -------
262 selected : `numpy.ndarray`
263 Boolean array indicating for each source whether it is selected
264 (True means selected).
265 """
266 flagField = self.fluxFieldfluxField + "_flag"
267 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
268 flux = _getFieldFromCatalog(catalog, self.fluxFieldfluxField)
269
270 selected &= BaseLimit.apply(self, flux)
271 return selected
272
273
275 """Select sources using a magnitude limit
276
277 Note that this assumes that a zero-point has already been applied and
278 the fluxes are in AB fluxes in Jansky. It is therefore principally
279 intended for reference catalogs rather than catalogs extracted from
280 science images.
281
282 This object can be used as a `lsst.pex.config.Config` for configuring
283 the limit, and then the `apply` method can be used to identify sources
284 in the catalog that match the configured limit.
285 """
286 fluxField = pexConfig.Field(dtype=str, default="flux",
287 doc="Name of the source flux field to use.")
288
289 def apply(self, catalog):
290 """Apply the magnitude limits to a catalog
291
292 Parameters
293 ----------
295 Catalog of sources to which the limit will be applied.
296
297 Returns
298 -------
299 selected : `numpy.ndarray`
300 Boolean array indicating for each source whether it is selected
301 (True means selected).
302 """
303 flagField = self.fluxFieldfluxField + "_flag"
304 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
305 flux = _getFieldFromCatalog(catalog, self.fluxFieldfluxField)
306
307 magnitude = (flux*u.nJy).to_value(u.ABmag)
308 selected &= BaseLimit.apply(self, magnitude)
309 return selected
310
311
313 """Select sources using a flux signal-to-noise limit
314
315 This object can be used as a `lsst.pex.config.Config` for configuring
316 the limit, and then the `apply` method can be used to identify sources
317 in the catalog that match the configured limit.
318 """
319 fluxField = pexConfig.Field(dtype=str, default="flux",
320 doc="Name of the source flux field to use.")
321 errField = pexConfig.Field(dtype=str, default="flux_err",
322 doc="Name of the source flux error field to use.")
323
324 def apply(self, catalog):
325 """Apply the signal-to-noise limits to a catalog
326
327 Parameters
328 ----------
330 Catalog of sources to which the limit will be applied.
331
332 Returns
333 -------
334 selected : `numpy.ndarray`
335 Boolean array indicating for each source whether it is selected
336 (True means selected).
337 """
338 flagField = self.fluxFieldfluxField + "_flag"
339 selected = np.logical_not(_getFieldFromCatalog(catalog, flagField, isFlag=True))
340 flux = _getFieldFromCatalog(catalog, self.fluxFieldfluxField)
341 err = _getFieldFromCatalog(catalog, self.errFielderrField)
342
343 signalToNoise = flux/err
344 selected &= BaseLimit.apply(self, signalToNoise)
345 return selected
346
347
349 """Select sources using a magnitude error limit
350
351 Because the magnitude error is the inverse of the signal-to-noise
352 ratio, this also works to select sources by signal-to-noise when
353 you only have a magnitude.
354
355 This object can be used as a `lsst.pex.config.Config` for configuring
356 the limit, and then the `apply` method can be used to identify sources
357 in the catalog that match the configured limit.
358 """
359 magErrField = pexConfig.Field(dtype=str, default="mag_err",
360 doc="Name of the source flux error field to use.")
361
362 def apply(self, catalog):
363 """Apply the magnitude error limits to a catalog
364
365 Parameters
366 ----------
368 Catalog of sources to which the limit will be applied.
369
370 Returns
371 -------
372 selected : `numpy.ndarray`
373 Boolean array indicating for each source whether it is selected
374 (True means selected).
375 """
376 return BaseLimit.apply(self, catalog[self.magErrFieldmagErrField])
377
378
379class RequireFlags(pexConfig.Config):
380 """Select sources using flags
381
382 This object can be used as a `lsst.pex.config.Config` for configuring
383 the limit, and then the `apply` method can be used to identify sources
384 in the catalog that match the configured limit.
385 """
386 good = pexConfig.ListField(dtype=str, default=[],
387 doc="List of source flag fields that must be set for a source to be used.")
388 bad = pexConfig.ListField(dtype=str, default=[],
389 doc="List of source flag fields that must NOT be set for a source to be used.")
390
391 def apply(self, catalog):
392 """Apply the flag requirements to a catalog
393
394 Returns whether the source is selected.
395
396 Parameters
397 ----------
399 Catalog of sources to which the requirements will be applied.
400
401 Returns
402 -------
403 selected : `numpy.ndarray`
404 Boolean array indicating for each source whether it is selected
405 (True means selected).
406 """
407 selected = np.ones(len(catalog), dtype=bool)
408 for flag in self.goodgood:
409 selected &= catalog[flag]
410 for flag in self.badbad:
411 selected &= ~catalog[flag]
412 return selected
413
414
416 """Select sources using star/galaxy separation
417
418 This object can be used as a `lsst.pex.config.Config` for configuring
419 the limit, and then the `apply` method can be used to identify sources
420 in the catalog that match the configured limit.
421 """
422 name = pexConfig.Field(dtype=str, default="base_ClassificationExtendedness_value",
423 doc="Name of column for star/galaxy separation")
424
425 def setDefaults(self):
426 """Set default
427
428 ``base_ClassificationExtendedness_value < 0.5`` means unresolved.
429 """
430 self.maximummaximummaximum = 0.5
431
432 def apply(self, catalog):
433 """Apply the flag requirements to a catalog
434
435 Returns whether the source is selected.
436
437 Parameters
438 ----------
440 Catalog of sources to which the requirements will be applied.
441
442 Returns
443 -------
444 selected : `numpy.ndarray`
445 Boolean array indicating for each source whether it is selected
446 (True means selected).
447 """
448 value = catalog[self.namename]
449 return BaseLimit.apply(self, value)
450
451
452class RequireIsolated(pexConfig.Config):
453 """Select sources based on whether they are isolated
454
455 This object can be used as a `lsst.pex.config.Config` for configuring
456 the column names to check for "parent" and "nChild" keys.
457
458 Note that this should only be run on a catalog that has had the
459 deblender already run (or else deblend_nChild does not exist).
460 """
461 parentName = pexConfig.Field(dtype=str, default="parent",
462 doc="Name of column for parent")
463 nChildName = pexConfig.Field(dtype=str, default="deblend_nChild",
464 doc="Name of column for nChild")
465
466 def apply(self, catalog):
467 """Apply the isolation requirements to a catalog
468
469 Returns whether the source is selected.
470
471 Parameters
472 ----------
474 Catalog of sources to which the requirements will be applied.
475
476 Returns
477 -------
478 selected : `numpy.ndarray`
479 Boolean array indicating for each source whether it is selected
480 (True means selected).
481 """
482 selected = ((catalog[self.parentNameparentName] == 0)
483 & (catalog[self.nChildNamenChildName] == 0))
484 return selected
485
486
487class ScienceSourceSelectorConfig(pexConfig.Config):
488 """Configuration for selecting science sources"""
489 doFluxLimit = pexConfig.Field(dtype=bool, default=False, doc="Apply flux limit?")
490 doFlags = pexConfig.Field(dtype=bool, default=False, doc="Apply flag limitation?")
491 doUnresolved = pexConfig.Field(dtype=bool, default=False, doc="Apply unresolved limitation?")
492 doSignalToNoise = pexConfig.Field(dtype=bool, default=False, doc="Apply signal-to-noise limit?")
493 doIsolated = pexConfig.Field(dtype=bool, default=False, doc="Apply isolated limitation?")
494 fluxLimit = pexConfig.ConfigField(dtype=FluxLimit, doc="Flux limit to apply")
495 flags = pexConfig.ConfigField(dtype=RequireFlags, doc="Flags to require")
496 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc="Star/galaxy separation to apply")
497 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc="Signal-to-noise limit to apply")
498 isolated = pexConfig.ConfigField(dtype=RequireIsolated, doc="Isolated criteria to apply")
499
500 def setDefaults(self):
501 pexConfig.Config.setDefaults(self)
502 self.flagsflags.bad = ["base_PixelFlags_flag_edge", "base_PixelFlags_flag_saturated", "base_PsfFlux_flags"]
503 self.signalToNoisesignalToNoise.fluxField = "base_PsfFlux_instFlux"
504 self.signalToNoisesignalToNoise.errField = "base_PsfFlux_instFluxErr"
505
506
507@pexConfig.registerConfigurable("science", sourceSelectorRegistry)
509 """Science source selector
510
511 By "science" sources, we mean sources that are on images that we
512 are processing, as opposed to sources from reference catalogs.
513
514 This selects (science) sources by (optionally) applying each of a
515 magnitude limit, flag requirements and star/galaxy separation.
516 """
517 ConfigClass = ScienceSourceSelectorConfig
518
519 def selectSources(self, sourceCat, matches=None, exposure=None):
520 """Return a selection of sources selected by specified criteria.
521
522 Parameters
523 ----------
524 sourceCat : `lsst.afw.table.SourceCatalog`
525 Catalog of sources to select from.
526 This catalog must be contiguous in memory.
527 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
528 Ignored in this SourceSelector.
529 exposure : `lsst.afw.image.Exposure` or None
530 The exposure the catalog was built from; used for debug display.
531
532 Return
533 ------
534 struct : `lsst.pipe.base.Struct`
535 The struct contains the following data:
536
537 - selected : `array` of `bool``
538 Boolean array of sources that were selected, same length as
539 sourceCat.
540 """
541 selected = np.ones(len(sourceCat), dtype=bool)
542 if self.config.doFluxLimit:
543 selected &= self.config.fluxLimit.apply(sourceCat)
544 if self.config.doFlags:
545 selected &= self.config.flags.apply(sourceCat)
546 if self.config.doUnresolved:
547 selected &= self.config.unresolved.apply(sourceCat)
548 if self.config.doSignalToNoise:
549 selected &= self.config.signalToNoise.apply(sourceCat)
550 if self.config.doIsolated:
551 selected &= self.config.isolated.apply(sourceCat)
552
553 self.log.info("Selected %d/%d sources", selected.sum(), len(sourceCat))
554
555 return pipeBase.Struct(selected=selected)
556
557
558class ReferenceSourceSelectorConfig(pexConfig.Config):
559 doMagLimit = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude limit?")
560 doFlags = pexConfig.Field(dtype=bool, default=False, doc="Apply flag limitation?")
561 doUnresolved = pexConfig.Field(dtype=bool, default=False, doc="Apply unresolved limitation?")
562 doSignalToNoise = pexConfig.Field(dtype=bool, default=False, doc="Apply signal-to-noise limit?")
563 doMagError = pexConfig.Field(dtype=bool, default=False, doc="Apply magnitude error limit?")
564 magLimit = pexConfig.ConfigField(dtype=MagnitudeLimit, doc="Magnitude limit to apply")
565 flags = pexConfig.ConfigField(dtype=RequireFlags, doc="Flags to require")
566 unresolved = pexConfig.ConfigField(dtype=RequireUnresolved, doc="Star/galaxy separation to apply")
567 signalToNoise = pexConfig.ConfigField(dtype=SignalToNoiseLimit, doc="Signal-to-noise limit to apply")
568 magError = pexConfig.ConfigField(dtype=MagnitudeErrorLimit, doc="Magnitude error limit to apply")
569 colorLimits = pexConfig.ConfigDictField(keytype=str, itemtype=ColorLimit, default={},
570 doc="Color limits to apply; key is used as a label only")
571
572
573@pexConfig.registerConfigurable("references", sourceSelectorRegistry)
575 """Reference source selector
576
577 This selects reference sources by (optionally) applying each of a
578 magnitude limit, flag requirements and color limits.
579 """
580 ConfigClass = ReferenceSourceSelectorConfig
581
582 def selectSources(self, sourceCat, matches=None, exposure=None):
583 """Return a selection of reference sources selected by some criteria.
584
585 Parameters
586 ----------
587 sourceCat : `lsst.afw.table.SourceCatalog`
588 Catalog of sources to select from.
589 This catalog must be contiguous in memory.
590 matches : `list` of `lsst.afw.table.ReferenceMatch` or None
591 Ignored in this SourceSelector.
592 exposure : `lsst.afw.image.Exposure` or None
593 The exposure the catalog was built from; used for debug display.
594
595 Return
596 ------
597 struct : `lsst.pipe.base.Struct`
598 The struct contains the following data:
599
600 - selected : `array` of `bool``
601 Boolean array of sources that were selected, same length as
602 sourceCat.
603 """
604 selected = np.ones(len(sourceCat), dtype=bool)
605 if self.config.doMagLimit:
606 selected &= self.config.magLimit.apply(sourceCat)
607 if self.config.doFlags:
608 selected &= self.config.flags.apply(sourceCat)
609 if self.config.doUnresolved:
610 selected &= self.config.unresolved.apply(sourceCat)
611 if self.config.doSignalToNoise:
612 selected &= self.config.signalToNoise.apply(sourceCat)
613 if self.config.doMagError:
614 selected &= self.config.magError.apply(sourceCat)
615 for limit in self.config.colorLimits.values():
616 selected &= limit.apply(sourceCat)
617
618 self.log.info("Selected %d/%d references", selected.sum(), len(sourceCat))
619
620 return pipeBase.Struct(selected=selected)
621
622
623def _getFieldFromCatalog(catalog, field, isFlag=False):
624 """
625 Get a field from a catalog, for `lsst.afw.table` catalogs or
626 `pandas.DataFrame` or `astropy.table.Table` catalogs.
627
628 Parameters
629 ----------
630 catalog : `lsst.afw.table.SourceCatalog` or `pandas.DataFrame`
631 or `astropy.table.Table`
632 Catalog of sources to extract field array
633 field : `str`
634 Name of field
635 isFlag : `bool`, optional
636 Is this a flag column? If it does not exist, return array
637 of False.
638
639 Returns
640 -------
641 array : `np.ndarray`
642 Array of field values from the catalog.
643 """
644 found = False
645 if isinstance(catalog, (pandas.DataFrame, astropy.table.Table)):
646 if field in catalog.columns:
647 found = True
648 # Sequences must be converted to numpy arrays
649 arr = np.array(catalog[field])
650 else:
651 if field in catalog.schema:
652 found = True
653 arr = catalog[field]
654
655 if isFlag and not found:
656 arr = np.zeros(len(catalog), dtype=bool)
657 elif not found:
658 raise KeyError(f"Could not find field {field} in catalog.")
659
660 return arr
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
def selectSources(self, sourceCat, matches=None, exposure=None)
def run(self, sourceCat, sourceSelectedField=None, matches=None, exposure=None)
def selectSources(self, sourceCat, matches=None, exposure=None)
def selectSources(self, sourceCat, matches=None, exposure=None)
Lightweight representation of a geometric match between two records.
Definition: Match.h:67