32 """!Configuration for propagating flags to coadd"""
33 flags = DictField(keytype=str, itemtype=float,
34 default={
"calib_psf_candidate": 0.2,
"calib_psf_used": 0.2,
"calib_psf_reserved": 0.2,
35 "calib_astrometry_used": 0.2,
"calib_photometry_used": 0.2,
36 "calib_photometry_reserved": 0.2, },
37 doc=(
"Source catalog flags to propagate, with the threshold of relative occurrence "
38 "(valid range: [0-1], default is 0.2). Coadd object will have flag set if the "
39 "fraction of input visits in which it is flagged is greater than the threshold."))
40 matchRadius = Field(dtype=float, default=0.2, doc=
"Source matching radius (arcsec)")
41 ccdName = Field(dtype=str, default=
'ccd', doc=
"Name of ccd to give to butler")
52 r"""!Task to propagate flags from single-frame measurements to coadd measurements
54\anchor PropagateVisitFlagsTask_
56\brief Propagate flags from individual visit measurements to coadd measurements
58\section pipe_tasks_propagateVisitFlagsTask_Contents Contents
60 - \ref pipe_tasks_propagateVisitFlagsTask_Description
61 - \ref pipe_tasks_propagateVisitFlagsTask_Initialization
62 - \ref pipe_tasks_propagateVisitFlagsTask_Config
63 - \ref pipe_tasks_propagateVisitFlagsTask_Use
64 - \ref pipe_tasks_propagateVisitFlagsTask_Example
66\section pipe_tasks_propagateVisitFlagsTask_Description Description
68\copybrief PropagateVisitFlagsTask
70We want to be able to set a flag for sources on the coadds using flags
71that were determined from the individual visits. A common example is sources
72that were used
for PSF determination, since we do
not do any PSF determination
73on the coadd but use the individual visits. This requires matching the coadd
74source catalog to each of the catalogs
from the inputs (see
75PropagateVisitFlagsConfig.matchRadius),
and thresholding on the number of
76times a source
is flagged on the input catalog.
78An important consideration
in this
is that the flagging of sources
in the
79individual visits can be somewhat stochastic, e.g., the same stars may
not
80always be used
for PSF determination because the field of view moves slightly
81between visits,
or the seeing changed. We there threshold on the relative
82occurrence of the flag
in the visits (see PropagateVisitFlagsConfig.flags).
83Flagging a source that
is always flagged
in inputs corresponds to a threshold
84of 1,
while flagging a source that
is flagged
in any of the input corresponds
85to a threshold of 0. But neither of these extrema are really useful
in
88Setting the threshold too high means that sources that are
not consistently
89flagged (e.g., due to chip gaps) will
not have the flag propagated. Setting
90that threshold too low means that random sources which are falsely flagged
in
91the inputs will start to dominate. If
in doubt, we suggest making this
92threshold relatively low, but
not zero (e.g., 0.1 to 0.2
or so). The more
93confidence
in the quality of the flagging, the lower the threshold can be.
95The relative occurrence accounts
for the edge of the field-of-view of the
96camera, but does
not include chip gaps, bad
or saturated pixels, etc.
98\section pipe_tasks_propagateVisitFlagsTask_Initialization Initialization
100Beyond the usual Task initialization, PropagateVisitFlagsTask also requires
101a schema
for the catalog that
is being constructed.
103\section pipe_tasks_propagateVisitFlagsTask_Config Configuration parameters
105See \ref PropagateVisitFlagsConfig
107\section pipe_tasks_propagateVisitFlagsTask_Use Use
109The
'run' method (described below)
is the entry-point
for operations. The
110'getCcdInputs' staticmethod
is provided
as a convenience
for retrieving the
111'ccdInputs' (CCD inputs table)
from an Exposure.
115\section pipe_tasks_propagateVisitFlagsTask_Example Example
124config.flags[
"calib_psf_used"] = 0.3
125config.matchRadius = 0.5
127ccdInputs = task.getCcdInputs(coaddExposure)
128task.run(butler, coaddCatalog, ccdInputs, coaddExposure.getWcs())
131 ConfigClass = PropagateVisitFlagsConfig
134 Task.__init__(self, **kwargs)
136 self.
_keys_keys = dict((f, self.
schemaschema.addField(f, type=
"Flag", doc=
"Propagated from visits"))
for
137 f
in self.config.flags)
141 """!Convenience method to retrieve the CCD inputs table from a coadd exposure"""
142 return coaddExposure.getInfo().getCoaddInputs().ccds
144 def run(self, butler, coaddSources, ccdInputs, coaddWcs, visitCatalogs=None, wcsUpdates=None):
145 """!Propagate flags from individual visit measurements to coadd
147 This requires matching the coadd source catalog to each of the catalogs
148 from the inputs,
and thresholding on the number of times a source
is
149 flagged on the input catalog. The threshold
is made on the relative
150 occurrence of the flag
in each source. Flagging a source that
is always
151 flagged
in inputs corresponds to a threshold of 1,
while flagging a
152 source that
is flagged
in any of the input corresponds to a threshold of
153 0. But neither of these extrema are really useful
in practise.
155 Setting the threshold too high means that sources that are
not consistently
156 flagged (e.g., due to chip gaps) will
not have the flag propagated. Setting
157 that threshold too low means that random sources which are falsely flagged
in
158 the inputs will start to dominate. If
in doubt, we suggest making this threshold
159 relatively low, but
not zero (e.g., 0.1 to 0.2
or so). The more confidence
in
160 the quality of the flagging, the lower the threshold can be.
162 The relative occurrence accounts
for the edge of the field-of-view of
163 the camera, but does
not include chip gaps, bad
or saturated pixels, etc.
165 @param[
in] butler Data butler,
for retrieving the input source catalogs
166 @param[
in,out] coaddSources Source catalog
from the coadd
167 @param[
in] ccdInputs Table of CCDs that contribute to the coadd
168 @param[
in] coaddWcs Wcs
for coadd
169 @param[
in] visitCatalogs List of loaded source catalogs
for each input ccd
in
170 the coadd. If provided this
is used instead of this
171 method loading
in the catalogs itself
172 @param[
in] wcsUpdates optional, If visitCatalogs
is a list of ccd catalogs, this
173 should be a list of updated wcs to apply
175 if len(self.config.flags) == 0:
178 flags = self.
_keys_keys.keys()
179 counts = dict((f, numpy.zeros(len(coaddSources), dtype=int))
for f
in flags)
180 indices = numpy.array([s.getId()
for s
in coaddSources])
181 radius = self.config.matchRadius*geom.arcseconds
183 def processCcd(ccdSources, wcsUpdate):
184 for sourceRecord
in ccdSources:
185 sourceRecord.updateCoord(wcsUpdate)
191 mc = afwTable.MatchControl()
192 mc.findOnlyClosest =
False
193 matches = afwTable.matchRaDec(coaddSources, ccdSources[ccdSources.get(flag)], radius, mc)
195 index = (numpy.where(indices == m.first.getId()))[0][0]
196 counts[flag][index] += 1
198 if visitCatalogs
is not None:
199 if wcsUpdates
is None:
200 raise pexExceptions.ValueError(
"If ccdInputs is a list of src catalogs, a list of wcs"
201 " updates for each catalog must be supplied in the "
202 "wcsUpdates parameter")
203 for i, ccdSource
in enumerate(visitCatalogs):
204 processCcd(ccdSource, wcsUpdates[i])
206 if ccdInputs
is None:
207 raise pexExceptions.ValueError(
"The visitCatalogs and ccdInput parameters can't both be None")
208 visitKey = ccdInputs.schema.find(
"visit").key
209 ccdKey = ccdInputs.schema.find(
"ccd").key
211 self.log.info(
"Propagating flags %s from inputs", flags)
214 for ccdRecord
in ccdInputs:
215 v = ccdRecord.get(visitKey)
216 c = ccdRecord.get(ccdKey)
217 dataId = {
"visit": int(v), self.config.ccdName: int(c)}
218 ccdSources = butler.get(
"src", dataId=dataId, immediate=
True)
219 processCcd(ccdSources, ccdRecord.getWcs())
223 key = self.
_keys_keys[f]
224 for s, num
in zip(coaddSources, counts[f]):
225 numOverlaps = len(ccdInputs.subsetContaining(s.getCentroid(), coaddWcs,
True))
226 s.setFlag(key, bool(num > numOverlaps*self.config.flags[f]))
227 self.log.info(
"Propagated %d sources with flag %s", sum(s.get(key)
for s
in coaddSources), f)
Configuration for propagating flags to coadd.
Task to propagate flags from single-frame measurements to coadd measurements.
def run(self, butler, coaddSources, ccdInputs, coaddWcs, visitCatalogs=None, wcsUpdates=None)
Propagate flags from individual visit measurements to coadd.
def getCcdInputs(coaddExposure)
Convenience method to retrieve the CCD inputs table from a coadd exposure.
def __init__(self, schema, **kwargs)