lsst.pipe.tasks  13.0-66-gfbf2f2ce+5
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 
24 from __future__ import absolute_import, division, print_function
25 import numpy
26 from lsst.pex.config import Config, Field, ListField
27 from lsst.pipe.base import Task
28 from lsst.afw.geom import Box2D
29 
30 
31 class SetPrimaryFlagsConfig(Config):
32  nChildKeyName = Field(dtype=str, default="deblend_nChild",
33  doc="Name of field in schema with number of deblended children")
34  pseudoFilterList = ListField(dtype=str, default=['sky'],
35  doc="Names of filters which should never be primary")
36 
37 
38 class SetPrimaryFlagsTask(Task):
39  ConfigClass = SetPrimaryFlagsConfig
40 
41  def __init__(self, schema, **kwargs):
42  Task.__init__(self, **kwargs)
43  self.schema = schema
44  self.isPatchInnerKey = self.schema.addField(
45  "detect_isPatchInner", type="Flag",
46  doc="true if source is in the inner region of a coadd patch",
47  )
48  self.isTractInnerKey = self.schema.addField(
49  "detect_isTractInner", type="Flag",
50  doc="true if source is in the inner region of a coadd tract",
51  )
52  self.isPrimaryKey = self.schema.addField(
53  "detect_isPrimary", type="Flag",
54  doc="true if source has no children and is in the inner region of a coadd patch "
55  + "and is in the inner region of a coadd tract "
56  "and is not \"detected\" in a pseudo-filter (see config.pseudoFilterList)",
57  )
58 
59  def run(self, sources, skyMap, tractInfo, patchInfo, includeDeblend=True):
60  """Set is-primary and related flags on sources
61 
62  @param[in,out] sources a SourceTable
63  - reads centroid fields and an nChild field
64  - writes is-patch-inner, is-tract-inner and is-primary flags
65  @param[in] skyMap sky tessellation object (subclass of lsst.skymap.BaseSkyMap)
66  @param[in] tractInfo tract object (subclass of lsst.skymap.TractInfo)
67  @param[in] patchInfo patch object (subclass of lsst.skymap.PatchInfo)
68  @param[in] includeDeblend include deblend information in isPrimary?
69  """
70  nChildKey = None
71  if includeDeblend:
72  nChildKey = self.schema.find(self.config.nChildKeyName).key
73 
74  # set inner flags for each source and set primary flags for sources with no children
75  # (or all sources if deblend info not available)
76  innerFloatBBox = Box2D(patchInfo.getInnerBBox())
77 
78  # When the centroider fails, we can still fall back to the peak, but we don't trust
79  # that quite as much - so we use a slightly smaller box for the patch comparison.
80  # That's trickier for the tract comparison, so we just use the peak without extra
81  # care there.
82  shrunkInnerFloatBBox = Box2D(innerFloatBBox)
83  shrunkInnerFloatBBox.grow(-1)
84 
85  pseudoFilterKeys = []
86  for filt in self.config.pseudoFilterList:
87  try:
88  pseudoFilterKeys.append(self.schema.find("merge_peak_%s" % filt).getKey())
89  except Exception:
90  self.log.warn("merge_peak is not set for pseudo-filter %s" % filt)
91 
92  tractId = tractInfo.getId()
93  for source in sources:
94  centroidPos = source.getCentroid()
95  if numpy.any(numpy.isnan(centroidPos)):
96  continue
97  if source.getCentroidFlag():
98  # Use a slightly smaller box to guard against bad centroids (see above)
99  isPatchInner = shrunkInnerFloatBBox.contains(centroidPos)
100  else:
101  isPatchInner = innerFloatBBox.contains(centroidPos)
102  source.setFlag(self.isPatchInnerKey, isPatchInner)
103 
104  skyPos = source.getCoord()
105  sourceInnerTractId = skyMap.findTract(skyPos).getId()
106  isTractInner = sourceInnerTractId == tractId
107  source.setFlag(self.isTractInnerKey, isTractInner)
108 
109  if nChildKey is None or source.get(nChildKey) == 0:
110  for pseudoFilterKey in pseudoFilterKeys:
111  if source.get(pseudoFilterKey):
112  isPseudo = True
113  break
114  else:
115  isPseudo = False
116 
117  source.setFlag(self.isPrimaryKey, isPatchInner and isTractInner and not isPseudo)
def run(self, sources, skyMap, tractInfo, patchInfo, includeDeblend=True)