22 from __future__
import absolute_import, division, print_function
25 from builtins
import object
28 import lsst.pex.config
29 import lsst.pex.exceptions
32 from .apCorrRegistry
import getApCorrNameSet
38 UseNaiveFluxSigma =
True 40 __all__ = (
"ApplyApCorrConfig",
"ApplyApCorrTask")
44 """!Catalog field names and keys needed to aperture correct a particular flux 48 """!Construct an ApCorrInfo and add fields to the schema 50 The aperture correction can be derived from the meaasurements in the 51 column being aperture-corrected or from measurements in a different 52 column (a "proxy"). In the first case, we will add columns to contain 53 the aperture correction values; in the second case (using a proxy), 54 we will add an alias to the proxy's aperture correction values. In 55 all cases, we add a flag. 57 @param[in,out] schema source catalog schema; 58 three fields are used to generate keys: 62 three fields are added: 63 - {name}_apCorr (only if not already added by proxy) 64 - {name}_apCorrSigma (only if not already added by proxy) 66 @param[in] model field name prefix for flux with aperture correction model, e.g. "base_PsfFlux" 67 @param[in] name field name prefix for flux needing aperture correction; may be None if it's the 68 same as for the 'model' parameter 70 ApCorrInfo has the following attributes: 71 - name: field name prefix for flux needing aperture correction 72 - modelName: field name for aperture correction model for flux 73 - modelSigmaName: field name for aperture correction model for fluxSigma 74 - doApCorrColumn: should we write the aperture correction values? (not if they're already being 76 - fluxName: name of flux field 77 - fluxSigmaName: name of flux sigma field 78 - fluxKey: key to flux field 79 - fluxSigmaKey: key to flux sigma field 80 - fluxFlagKey: key to flux flag field 81 - apCorrKey: key to new aperture correction field 82 - apCorrSigmaKey: key to new aperture correction sigma field 83 - apCorrFlagKey: key to new aperture correction flag field 101 doc=
"aperture correction applied to %s" % (name,),
105 name +
"_apCorrSigma",
106 doc=
"aperture correction applied to %s" % (name,),
110 aliases = schema.getAliasMap()
111 aliases.set(name +
"_apCorr", model +
"_apCorr")
112 aliases.set(name +
"_apCorrSigma", model +
"_apCorrSigma")
113 self.
apCorrKey = schema.find(name +
"_apCorr").key
117 name +
"_flag_apCorr",
118 doc=
"set if unable to aperture correct %s" % (name,),
124 ignoreList = lsst.pex.config.ListField(
125 doc=
"flux measurement algorithms in getApCorrNameSet() to ignore; " 126 "if a name is listed that does not appear in getApCorrNameSet() then a warning is logged",
131 doFlagApCorrFailures = lsst.pex.config.Field(
132 doc=
"set the general failure flag for a flux when it cannot be aperture-corrected?",
136 proxies = lsst.pex.config.DictField(
137 doc=
"flux measurement algorithms to be aperture-corrected by reference to another algorithm; " 138 "this is a mapping alg1:alg2, where 'alg1' is the algorithm being corrected, and 'alg2' " 139 "is the algorithm supplying the corrections",
147 """!Apply aperture corrections 149 ConfigClass = ApplyApCorrConfig
150 _DefaultName =
"applyApCorr" 153 """Construct an instance of this task 155 lsst.pipe.base.Task.__init__(self, **kwds)
159 ignoreSet = set(self.config.ignoreList)
160 missingNameSet = ignoreSet - set(apCorrNameSet)
162 self.log.warn(
"Fields in ignoreList that are not in fluxCorrectList: %s",
163 sorted(list(missingNameSet)))
164 for name
in apCorrNameSet - ignoreSet:
165 if name +
"_flux" not in schema:
170 for name, model
in self.config.proxies.items():
171 if name
in apCorrNameSet:
174 if name +
"_flux" not in schema:
179 def run(self, catalog, apCorrMap):
180 """Apply aperture corrections to a catalog of sources 182 @param[in,out] catalog catalog of sources 183 @param[in] apCorrMap aperture correction map (an lsst.afw.image.ApCorrMap) 185 If you show debug-level log messages then you will see statistics for the effects of 188 self.log.info(
"Applying aperture corrections to %d flux fields", len(self.
apCorrInfoDict))
189 if UseNaiveFluxSigma:
190 self.log.debug(
"Use naive flux sigma computation")
192 self.log.debug(
"Use complex flux sigma computation that double-counts photon noise " 193 "and thus over-estimates flux uncertainty")
195 apCorrModel = apCorrMap.get(apCorrInfo.modelName)
196 apCorrSigmaModel = apCorrMap.get(apCorrInfo.modelSigmaName)
197 if None in (apCorrModel, apCorrSigmaModel):
198 missingNames = [(apCorrInfo.modelName, apCorrInfo.modelSigmaName)[i]
199 for i, model
in enumerate((apCorrModel, apCorrSigmaModel))
if model
is None]
200 self.log.warn(
"Cannot aperture correct %s because could not find %s in apCorrMap" %
201 (apCorrInfo.name,
" or ".join(missingNames),))
202 for source
in catalog:
203 source.set(apCorrInfo.apCorrFlagKey,
True)
206 for source
in catalog:
207 center = source.getCentroid()
209 source.set(apCorrInfo.apCorrFlagKey,
True)
210 oldFluxFlagState =
False 211 if self.config.doFlagApCorrFailures:
212 oldFluxFlagState = source.get(apCorrInfo.fluxFlagKey)
213 source.set(apCorrInfo.fluxFlagKey,
True)
218 apCorr = apCorrModel.evaluate(center)
219 if not UseNaiveFluxSigma:
220 apCorrSigma = apCorrSigmaModel.evaluate(center)
221 except lsst.pex.exceptions.DomainError:
224 if apCorrInfo.doApCorrColumn:
225 source.set(apCorrInfo.apCorrKey, apCorr)
226 source.set(apCorrInfo.apCorrSigmaKey, apCorrSigma)
228 if apCorr <= 0.0
or apCorrSigma < 0.0:
231 flux = source.get(apCorrInfo.fluxKey)
232 fluxSigma = source.get(apCorrInfo.fluxSigmaKey)
233 source.set(apCorrInfo.fluxKey, flux*apCorr)
234 if UseNaiveFluxSigma:
235 source.set(apCorrInfo.fluxSigmaKey, fluxSigma*apCorr)
238 b = apCorrSigma/apCorr
239 source.set(apCorrInfo.fluxSigmaKey, abs(flux*apCorr)*math.sqrt(a*a + b*b))
240 source.set(apCorrInfo.apCorrFlagKey,
False)
241 if self.config.doFlagApCorrFailures:
242 source.set(apCorrInfo.fluxFlagKey, oldFluxFlagState)
244 if self.log.getLevel() <= self.log.DEBUG:
246 apCorrArr = numpy.array([s.get(apCorrInfo.apCorrKey)
for s
in catalog])
247 apCorrSigmaArr = numpy.array([s.get(apCorrInfo.apCorrSigmaKey)
for s
in catalog])
248 self.log.debug(
"For flux field %r: mean apCorr=%s, stdDev apCorr=%s, " 249 "mean apCorrSigma=%s, stdDev apCorrSigma=%s for %s sources",
250 apCorrInfo.name, apCorrArr.mean(), apCorrArr.std(),
251 apCorrSigmaArr.mean(), apCorrSigmaArr.std(), len(catalog))
Apply aperture corrections.
def __init__(self, schema, kwds)
def getApCorrNameSet()
Return a copy of the set of field name prefixes for fluxes that should be aperture corrected...
def __init__(self, schema, model, name=None)
Construct an ApCorrInfo and add fields to the schema.
Catalog field names and keys needed to aperture correct a particular flux.
def run(self, catalog, apCorrMap)