Coverage for python/lsst/pipe/tasks/setPrimaryFlags.py : 75%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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#
23import numpy
24from lsst.pex.config import Config, Field, ListField
25from lsst.pipe.base import Task
26from lsst.geom import Box2D
29class 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")
36class SetPrimaryFlagsTask(Task):
37 """Add isPrimaryKey to a given schema.
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 """
49 ConfigClass = SetPrimaryFlagsConfig
51 def __init__(self, schema, isSingleFrame=False, **kwargs):
52 Task.__init__(self, **kwargs)
53 self.schema = schema
54 self.isSingleFrame = isSingleFrame
55 if not self.isSingleFrame: 55 ↛ 68line 55 didn't jump to line 68, because the condition on line 55 was never false
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.isPatchInnerKey = self.schema.addField(
60 "detect_isPatchInner", type="Flag",
61 doc="true if source is in the inner region of a coadd patch",
62 )
63 self.isTractInnerKey = self.schema.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.isPrimaryKey = self.schema.addField(
70 "detect_isPrimary", type="Flag",
71 doc=primaryDoc,
72 )
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.
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: 99 ↛ 103line 99 didn't jump to line 103, because the condition on line 99 was never false
100 nChildKey = self.schema.find(self.config.nChildKeyName).key
102 # coadd case
103 if not self.isSingleFrame: 103 ↛ 151line 103 didn't jump to line 151, because the condition on line 103 was never false
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())
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)
115 pseudoFilterKeys = []
116 for filt in self.config.pseudoFilterList:
117 try:
118 pseudoFilterKeys.append(self.schema.find("merge_peak_%s" % filt).getKey())
119 except Exception:
120 self.log.warn("merge_peak is not set for pseudo-filter %s" % filt)
122 tractId = tractInfo.getId()
123 for source in sources:
124 centroidPos = source.getCentroid()
125 if numpy.any(numpy.isnan(centroidPos)): 125 ↛ 126line 125 didn't jump to line 126, because the condition on line 125 was never true
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.isPatchInnerKey, isPatchInner)
134 skyPos = source.getCoord()
135 sourceInnerTractId = skyMap.findTract(skyPos).getId()
136 isTractInner = sourceInnerTractId == tractId
137 source.setFlag(self.isTractInnerKey, isTractInner)
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
147 source.setFlag(self.isPrimaryKey, isPatchInner and isTractInner and not isPseudo)
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.isPrimaryKey, hasNoChildren and not isSkySource)