31 """!Configuration for propagating flags to coadd""" 32 flags = DictField(keytype=str, itemtype=float,
33 default={
"calib_psf_candidate": 0.2,
"calib_psf_used": 0.2,
"calib_psf_reserved": 0.2,
34 "calib_astrometry_used": 0.2,
"calib_photometry_used": 0.2,
35 "calib_photometry_reserved": 0.2, },
36 doc=(
"Source catalog flags to propagate, with the threshold of relative occurrence " 37 "(valid range: [0-1], default is 0.2). Coadd object will have flag set if the " 38 "fraction of input visits in which it is flagged is greater than the threshold."))
39 matchRadius = Field(dtype=float, default=0.2, doc=
"Source matching radius (arcsec)")
40 ccdName = Field(dtype=str, default=
'ccd', doc=
"Name of ccd to give to butler")
51 r"""!Task to propagate flags from single-frame measurements to coadd measurements 53 \anchor PropagateVisitFlagsTask_ 55 \brief Propagate flags from individual visit measurements to coadd measurements 57 \section pipe_tasks_propagateVisitFlagsTask_Contents Contents 59 - \ref pipe_tasks_propagateVisitFlagsTask_Description 60 - \ref pipe_tasks_propagateVisitFlagsTask_Initialization 61 - \ref pipe_tasks_propagateVisitFlagsTask_Config 62 - \ref pipe_tasks_propagateVisitFlagsTask_Use 63 - \ref pipe_tasks_propagateVisitFlagsTask_Example 65 \section pipe_tasks_propagateVisitFlagsTask_Description Description 67 \copybrief PropagateVisitFlagsTask 69 We want to be able to set a flag for sources on the coadds using flags 70 that were determined from the individual visits. A common example is sources 71 that were used for PSF determination, since we do not do any PSF determination 72 on the coadd but use the individual visits. This requires matching the coadd 73 source catalog to each of the catalogs from the inputs (see 74 PropagateVisitFlagsConfig.matchRadius), and thresholding on the number of 75 times a source is flagged on the input catalog. 77 An important consideration in this is that the flagging of sources in the 78 individual visits can be somewhat stochastic, e.g., the same stars may not 79 always be used for PSF determination because the field of view moves slightly 80 between visits, or the seeing changed. We there threshold on the relative 81 occurrence of the flag in the visits (see PropagateVisitFlagsConfig.flags). 82 Flagging a source that is always flagged in inputs corresponds to a threshold 83 of 1, while flagging a source that is flagged in any of the input corresponds 84 to a threshold of 0. But neither of these extrema are really useful in 87 Setting the threshold too high means that sources that are not consistently 88 flagged (e.g., due to chip gaps) will not have the flag propagated. Setting 89 that threshold too low means that random sources which are falsely flagged in 90 the inputs will start to dominate. If in doubt, we suggest making this 91 threshold relatively low, but not zero (e.g., 0.1 to 0.2 or so). The more 92 confidence in the quality of the flagging, the lower the threshold can be. 94 The relative occurrence accounts for the edge of the field-of-view of the 95 camera, but does not include chip gaps, bad or saturated pixels, etc. 97 \section pipe_tasks_propagateVisitFlagsTask_Initialization Initialization 99 Beyond the usual Task initialization, PropagateVisitFlagsTask also requires 100 a schema for the catalog that is being constructed. 102 \section pipe_tasks_propagateVisitFlagsTask_Config Configuration parameters 104 See \ref PropagateVisitFlagsConfig 106 \section pipe_tasks_propagateVisitFlagsTask_Use Use 108 The 'run' method (described below) is the entry-point for operations. The 109 'getCcdInputs' staticmethod is provided as a convenience for retrieving the 110 'ccdInputs' (CCD inputs table) from an Exposure. 114 \section pipe_tasks_propagateVisitFlagsTask_Example Example 118 # * butler: data butler, for retrieving the CCD catalogs 119 # * coaddCatalog: catalog of source measurements on the coadd (lsst.afw.table.SourceCatalog) 120 # * coaddExposure: coadd (lsst.afw.image.Exposure) 121 from lsst.pipe.tasks.propagateVisitFlags import PropagateVisitFlagsTask, PropagateVisitFlagsConfig 122 config = PropagateVisitFlagsConfig() 123 config.flags["calib_psf_used"] = 0.3 # Relative threshold for this flag 124 config.matchRadius = 0.5 # Matching radius in arcsec 125 task = PropagateVisitFlagsTask(coaddCatalog.schema, config=config) 126 ccdInputs = task.getCcdInputs(coaddExposure) 127 task.run(butler, coaddCatalog, ccdInputs, coaddExposure.getWcs()) 130 ConfigClass = PropagateVisitFlagsConfig
133 Task.__init__(self, **kwargs)
135 self.
_keys = dict((f, self.
schema.addField(f, type=
"Flag", doc=
"Propagated from visits"))
for 136 f
in self.config.flags)
140 """!Convenience method to retrieve the CCD inputs table from a coadd exposure""" 141 return coaddExposure.getInfo().getCoaddInputs().ccds
143 def run(self, butler, coaddSources, ccdInputs, coaddWcs):
144 """!Propagate flags from individual visit measurements to coadd 146 This requires matching the coadd source catalog to each of the catalogs 147 from the inputs, and thresholding on the number of times a source is 148 flagged on the input catalog. The threshold is made on the relative 149 occurrence of the flag in each source. Flagging a source that is always 150 flagged in inputs corresponds to a threshold of 1, while flagging a 151 source that is flagged in any of the input corresponds to a threshold of 152 0. But neither of these extrema are really useful in practise. 154 Setting the threshold too high means that sources that are not consistently 155 flagged (e.g., due to chip gaps) will not have the flag propagated. Setting 156 that threshold too low means that random sources which are falsely flagged in 157 the inputs will start to dominate. If in doubt, we suggest making this threshold 158 relatively low, but not zero (e.g., 0.1 to 0.2 or so). The more confidence in 159 the quality of the flagging, the lower the threshold can be. 161 The relative occurrence accounts for the edge of the field-of-view of 162 the camera, but does not include chip gaps, bad or saturated pixels, etc. 164 @param[in] butler Data butler, for retrieving the input source catalogs 165 @param[in,out] coaddSources Source catalog from the coadd 166 @param[in] ccdInputs Table of CCDs that contribute to the coadd 167 @param[in] coaddWcs Wcs for coadd 169 if len(self.config.flags) == 0:
172 flags = self.
_keys.keys()
173 visitKey = ccdInputs.schema.find(
"visit").key
174 ccdKey = ccdInputs.schema.find(
"ccd").key
175 radius = self.config.matchRadius*afwGeom.arcseconds
177 self.log.info(
"Propagating flags %s from inputs" % (flags,))
179 counts = dict((f, numpy.zeros(len(coaddSources), dtype=int))
for f
in flags)
180 indices = numpy.array([s.getId()
for s
in coaddSources])
183 for ccdRecord
in ccdInputs:
184 v = ccdRecord.get(visitKey)
185 c = ccdRecord.get(ccdKey)
186 dataId = {
"visit": int(v), self.config.ccdName: int(c)}
187 ccdSources = butler.get(
"src", dataId=dataId, immediate=
True)
188 for sourceRecord
in ccdSources:
189 sourceRecord.updateCoord(ccdRecord.getWcs())
195 mc = afwTable.MatchControl()
196 mc.findOnlyClosest =
False 197 matches = afwTable.matchRaDec(coaddSources, ccdSources[ccdSources.get(flag)], radius, mc)
199 index = (numpy.where(indices == m.first.getId()))[0][0]
200 counts[flag][index] += 1
205 for s, num
in zip(coaddSources, counts[f]):
206 numOverlaps = len(ccdInputs.subsetContaining(s.getCentroid(), coaddWcs,
True))
207 s.setFlag(key, bool(num > numOverlaps*self.config.flags[f]))
208 self.log.info(
"Propagated %d sources with flag %s" % (sum(s.get(key)
for s
in coaddSources), f))
Task to propagate flags from single-frame measurements to coadd measurements.
def __init__(self, schema, kwargs)
def getCcdInputs(coaddExposure)
Convenience method to retrieve the CCD inputs table from a coadd exposure.
Configuration for propagating flags to coadd.
def run(self, butler, coaddSources, ccdInputs, coaddWcs)
Propagate flags from individual visit measurements to coadd.