LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
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 import numpy
25 from lsst.pex.config import Config, Field, ListField
26 from lsst.pipe.base import Task
27 from lsst.afw.geom import Box2D
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 class SetPrimaryFlagsTask(Task):
36  ConfigClass = SetPrimaryFlagsConfig
37 
38  def __init__(self, schema, **kwargs):
39  Task.__init__(self, **kwargs)
40  self.schema = schema
41  self.isPatchInnerKey = self.schema.addField(
42  "detect_isPatchInner", type="Flag",
43  doc="true if source is in the inner region of a coadd patch",
44  )
45  self.isTractInnerKey = self.schema.addField(
46  "detect_isTractInner", type="Flag",
47  doc="true if source is in the inner region of a coadd tract",
48  )
49  self.isPrimaryKey = self.schema.addField(
50  "detect_isPrimary", type="Flag",
51  doc="true if source has no children and is in the inner region of a coadd patch " \
52  + "and is in the inner region of a coadd tract "
53  "and is not \"detected\" in a pseudo-filter (see config.pseudoFilterList)",
54  )
55 
56  def run(self, sources, skyMap, tractInfo, patchInfo, includeDeblend=True):
57  """Set is-primary and related flags on sources
58 
59  @param[in,out] sources a SourceTable
60  - reads centroid fields and an nChild field
61  - writes is-patch-inner, is-tract-inner and is-primary flags
62  @param[in] skyMap sky tessellation object (subclass of lsst.skymap.BaseSkyMap)
63  @param[in] tractInfo tract object (subclass of lsst.skymap.TractInfo)
64  @param[in] patchInfo patch object (subclass of lsst.skymap.PatchInfo)
65  @param[in] includeDeblend include deblend information in isPrimary?
66  """
67  nChildKey = None
68  if includeDeblend:
69  nChildKey = self.schema.find(self.config.nChildKeyName).key
70 
71  # set inner flags for each source and set primary flags for sources with no children
72  # (or all sources if deblend info not available)
73  innerFloatBBox = Box2D(patchInfo.getInnerBBox())
74 
75  # When the centroider fails, we can still fall back to the peak, but we don't trust
76  # that quite as much - so we use a slightly smaller box for the patch comparison.
77  # That's trickier for the tract comparison, so we just use the peak without extra
78  # care there.
79  shrunkInnerFloatBBox = Box2D(innerFloatBBox)
80  shrunkInnerFloatBBox.grow(-1)
81 
82  pseudoFilterKeys = []
83  for filt in self.config.pseudoFilterList:
84  try:
85  pseudoFilterKeys.append(self.schema.find("merge_peak_%s" % filt).getKey())
86  except Exception:
87  self.log.warn("merge_peak is not set for pseudo-filter %s" % filt)
88 
89  tractId = tractInfo.getId()
90  for source in sources:
91  centroidPos = source.getCentroid()
92  if numpy.any(numpy.isnan(centroidPos)):
93  continue
94  if source.getCentroidFlag():
95  # Use a slightly smaller box to guard against bad centroids (see above)
96  isPatchInner = shrunkInnerFloatBBox.contains(centroidPos)
97  else:
98  isPatchInner = innerFloatBBox.contains(centroidPos)
99  source.setFlag(self.isPatchInnerKey, isPatchInner)
100 
101  skyPos = source.getCoord()
102  sourceInnerTractId = skyMap.findTract(skyPos).getId()
103  isTractInner = sourceInnerTractId == tractId
104  source.setFlag(self.isTractInnerKey, isTractInner)
105 
106  if nChildKey is None or source.get(nChildKey) == 0:
107  for pseudoFilterKey in pseudoFilterKeys:
108  if source.get(pseudoFilterKey):
109  isPseudo = True
110  break
111  else:
112  isPseudo = False
113 
114  source.setFlag(self.isPrimaryKey, isPatchInner and isTractInner and not isPseudo)
115 
A floating-point coordinate rectangle geometry.
Definition: Box.h:271