lsst.pipe.tasks  21.0.0-46-g880d6fab+d14224996b
setPrimaryFlags.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # LSST Data Management System
4 # Copyright 2008-2016 LSST/AURA
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 <http://www.lsstcorp.org/LegalNotices/>.
22 #
23 import numpy
24 from lsst.pex.config import Config, Field, ListField
25 from lsst.pipe.base import Task
26 from lsst.geom import Box2D
27 
28 
29 class SetPrimaryFlagsConfig(Config):
30  nChildKeyName = Field(dtype=str, default="deblend_nChild",
31  doc="Name of field in schema with number of deblended children")
32  pseudoFilterList = ListField(dtype=str, default=['sky'],
33  doc="Names of filters which should never be primary")
34 
35 
36 class SetPrimaryFlagsTask(Task):
37  """Add isPrimaryKey to a given schema.
38 
39  Parameters
40  ----------
41  schema : `lsst.afw.table.Schema`
42  The input schema.
43  isSingleFrame : `bool`
44  Flag specifying if task is operating with single frame imaging.
45  kwargs :
46  Keyword arguments passed to the task.
47  """
48 
49  ConfigClass = SetPrimaryFlagsConfig
50 
51  def __init__(self, schema, isSingleFrame=False, **kwargs):
52  Task.__init__(self, **kwargs)
53  self.schemaschema = schema
54  self.isSingleFrameisSingleFrame = isSingleFrame
55  if not self.isSingleFrameisSingleFrame:
56  primaryDoc = ("true if source has no children and is in the inner region of a coadd patch "
57  "and is in the inner region of a coadd tract "
58  "and is not \"detected\" in a pseudo-filter (see config.pseudoFilterList)")
59  self.isPatchInnerKeyisPatchInnerKey = self.schemaschema.addField(
60  "detect_isPatchInner", type="Flag",
61  doc="true if source is in the inner region of a coadd patch",
62  )
63  self.isTractInnerKeyisTractInnerKey = self.schemaschema.addField(
64  "detect_isTractInner", type="Flag",
65  doc="true if source is in the inner region of a coadd tract",
66  )
67  else:
68  primaryDoc = "true if source has no children and is not a sky source"
69  self.isPrimaryKeyisPrimaryKey = self.schemaschema.addField(
70  "detect_isPrimary", type="Flag",
71  doc=primaryDoc,
72  )
73 
74  def run(self, sources, skyMap=None, tractInfo=None, patchInfo=None,
75  includeDeblend=True):
76  """Set is-patch-inner, is-tract-inner and is-primary flags on sources.
77  For coadded imaging, the is-primary flag returns True when an object
78  has no children, is in the inner region of a coadd patch, is in the
79  inner region of a coadd trach, and is not detected in a pseudo-filter
80  (e.g., a sky_object).
81  For single frame imaging, the is-primary flag returns True when a
82  source has no children and is not a sky source.
83 
84  Parameters
85  ----------
86  sources : `lsst.afw.table.SourceCatalog`
87  A sourceTable. Reads in centroid fields and an nChild field.
88  Writes is-patch-inner, is-tract-inner, and is-primary flags.
89  skyMap : `lsst.skymap.BaseSkyMap`
90  Sky tessellation object
91  tractInfo : `lsst.skymap.TractInfo`
92  Tract object
93  patchInfo : `lsst.skymap.PatchInfo`
94  Patch object
95  includeDeblend : `bool`
96  Include deblend information in isPrimary?
97  """
98  nChildKey = None
99  if includeDeblend:
100  nChildKey = self.schemaschema.find(self.config.nChildKeyName).key
101 
102  # coadd case
103  if not self.isSingleFrameisSingleFrame:
104  # set inner flags for each source and set primary flags for sources with no children
105  # (or all sources if deblend info not available)
106  innerFloatBBox = Box2D(patchInfo.getInnerBBox())
107 
108  # When the centroider fails, we can still fall back to the peak, but we don't trust
109  # that quite as much - so we use a slightly smaller box for the patch comparison.
110  # That's trickier for the tract comparison, so we just use the peak without extra
111  # care there.
112  shrunkInnerFloatBBox = Box2D(innerFloatBBox)
113  shrunkInnerFloatBBox.grow(-1)
114 
115  pseudoFilterKeys = []
116  for filt in self.config.pseudoFilterList:
117  try:
118  pseudoFilterKeys.append(self.schemaschema.find("merge_peak_%s" % filt).getKey())
119  except Exception:
120  self.log.warn("merge_peak is not set for pseudo-filter %s" % filt)
121 
122  tractId = tractInfo.getId()
123  for source in sources:
124  centroidPos = source.getCentroid()
125  if numpy.any(numpy.isnan(centroidPos)):
126  continue
127  if source.getCentroidFlag():
128  # Use a slightly smaller box to guard against bad centroids (see above)
129  isPatchInner = shrunkInnerFloatBBox.contains(centroidPos)
130  else:
131  isPatchInner = innerFloatBBox.contains(centroidPos)
132  source.setFlag(self.isPatchInnerKeyisPatchInnerKey, isPatchInner)
133 
134  skyPos = source.getCoord()
135  sourceInnerTractId = skyMap.findTract(skyPos).getId()
136  isTractInner = sourceInnerTractId == tractId
137  source.setFlag(self.isTractInnerKeyisTractInnerKey, isTractInner)
138 
139  if nChildKey is None or source.get(nChildKey) == 0:
140  for pseudoFilterKey in pseudoFilterKeys:
141  if source.get(pseudoFilterKey):
142  isPseudo = True
143  break
144  else:
145  isPseudo = False
146 
147  source.setFlag(self.isPrimaryKeyisPrimaryKey, isPatchInner and isTractInner and not isPseudo)
148 
149  # single frame case
150  else:
151  hasSkySources = True if "sky_source" in sources.schema else False
152  for source in sources:
153  hasNoChildren = True if nChildKey is None or source.get(nChildKey) == 0 else False
154  isSkySource = False
155  if hasSkySources:
156  if source["sky_source"]:
157  isSkySource = True
158  source.setFlag(self.isPrimaryKeyisPrimaryKey, hasNoChildren and not isSkySource)
def __init__(self, schema, isSingleFrame=False, **kwargs)
def run(self, sources, skyMap=None, tractInfo=None, patchInfo=None, includeDeblend=True)