26 import lsst.pex.config
30 from .apCorrRegistry
import getApCorrNameSet
36 UseNaiveFluxErr =
True 38 __all__ = (
"ApplyApCorrConfig",
"ApplyApCorrTask")
42 """Catalog field names and keys needed to aperture correct a particular 47 schema : `lsst.afw.table` 48 Source catalog schema. Three fields are used to generate keys: 50 - ``{name}_instFluxErr`` 52 Three fields are added: 53 - ``{name}_apCorr`` (only if not already added by proxy) 54 - ``{name}_apCorrErr`` (only if not already added by proxy) 55 - ``{name}_flag_apCorr`` 57 Field name prefix for instFlux with aperture correction model, e.g. 60 Field name prefix for instFlux needing aperture correction; may be 61 `None` if it is the same as ``model`` 65 The aperture correction can be derived from the meaasurements in the 66 column being aperture-corrected or from measurements in a different 67 column (a "proxy"). In the first case, we will add columns to contain 68 the aperture correction values; in the second case (using a proxy), 69 we will add an alias to the proxy's aperture correction values. In 70 all cases, we add a flag. 74 """Field name prefix for flux needing aperture correction (`str`). 78 """Field name for aperture correction model for flux (`str`). 82 """Field name for aperture correction model for fluxErr (`str`). 86 """Should we write the aperture correction values (`bool`)? 88 They should not be written if they're already being written by a proxy. 92 """Name of ``instFlux`` field (`str`). 95 instFluxErrName =
None 96 """Name of ``instFlux`` sigma field (`str`). 100 """Key to ``instFlux`` field (`lsst.afw.table.schema.Key`). 103 instFluxErrKey =
None 104 """Key to ``instFlux`` sigma field (`lsst.afw.table.schema.Key`). 108 """Key to the flux flag field (`lsst.afw.table.schema.Key`). 112 """Key to new aperture correction field (`lsst.afw.table.schema.Key`). 116 """Key to new aperture correction sigma field (`lsst.afw.table.schema.Key`). 120 """Key to new aperture correction flag field (`lsst.afw.table.schema.Key`). 136 self.
doApCorrColumn = (name == model
or model +
"_apCorr" not in schema)
140 doc=
"aperture correction applied to %s" % (name,),
145 doc=
"standard deviation of aperture correction applied to %s" % (name,),
149 aliases = schema.getAliasMap()
150 aliases.set(name +
"_apCorr", model +
"_apCorr")
151 aliases.set(name +
"_apCorrErr", model +
"_apCorrErr")
152 self.
apCorrKey = schema.find(name +
"_apCorr").key
153 self.
apCorrErrKey = schema.find(name +
"_apCorrErr").key
156 name +
"_flag_apCorr",
157 doc=
"set if unable to aperture correct %s" % (name,),
163 """Aperture correction configuration. 166 ignoreList = lsst.pex.config.ListField(
167 doc=
"flux measurement algorithms in getApCorrNameSet() to ignore; " 168 "if a name is listed that does not appear in getApCorrNameSet() then a warning is logged",
173 doFlagApCorrFailures = lsst.pex.config.Field(
174 doc=
"set the general failure flag for a flux when it cannot be aperture-corrected?",
178 proxies = lsst.pex.config.DictField(
179 doc=
"flux measurement algorithms to be aperture-corrected by reference to another algorithm; " 180 "this is a mapping alg1:alg2, where 'alg1' is the algorithm being corrected, and 'alg2' " 181 "is the algorithm supplying the corrections",
189 """Apply aperture corrections. 193 schema : `lsst.afw.table.Schema` 195 ConfigClass = ApplyApCorrConfig
196 _DefaultName =
"applyApCorr" 199 lsst.pipe.base.Task.__init__(self, **kwds)
203 ignoreSet = set(self.config.ignoreList)
204 missingNameSet = ignoreSet - set(apCorrNameSet)
206 self.log.warn(
"Fields in ignoreList that are not in fluxCorrectList: %s",
207 sorted(list(missingNameSet)))
208 for name
in sorted(list(apCorrNameSet - ignoreSet)):
209 if name +
"_instFlux" not in schema:
214 for name, model
in self.config.proxies.items():
215 if name
in apCorrNameSet:
218 if name +
"_instFlux" not in schema:
223 def run(self, catalog, apCorrMap):
224 """Apply aperture corrections to a catalog of sources. 228 catalog : `lsst.afw.table.SourceCatalog` 229 Catalog of sources. Will be updated in place. 230 apCorrMap : `lsst.afw.image.ApCorrMap` 231 Aperture correction map 235 If you show debug-level log messages then you will see statistics for 236 the effects of aperture correction. 238 self.log.info(
"Applying aperture corrections to %d instFlux fields", len(self.
apCorrInfoDict))
240 self.log.debug(
"Use naive instFlux sigma computation")
242 self.log.debug(
"Use complex instFlux sigma computation that double-counts photon noise " 243 "and thus over-estimates instFlux uncertainty")
245 apCorrModel = apCorrMap.get(apCorrInfo.modelName)
246 apCorrErrModel = apCorrMap.get(apCorrInfo.modelSigmaName)
247 if None in (apCorrModel, apCorrErrModel):
248 missingNames = [(apCorrInfo.modelName, apCorrInfo.modelSigmaName)[i]
249 for i, model
in enumerate((apCorrModel, apCorrErrModel))
if model
is None]
250 self.log.warn(
"Cannot aperture correct %s because could not find %s in apCorrMap" %
251 (apCorrInfo.name,
" or ".join(missingNames),))
252 for source
in catalog:
253 source.set(apCorrInfo.apCorrFlagKey,
True)
256 for source
in catalog:
257 center = source.getCentroid()
259 source.set(apCorrInfo.apCorrFlagKey,
True)
260 oldFluxFlagState =
False 261 if self.config.doFlagApCorrFailures:
262 oldFluxFlagState = source.get(apCorrInfo.fluxFlagKey)
263 source.set(apCorrInfo.fluxFlagKey,
True)
268 apCorr = apCorrModel.evaluate(center)
269 if not UseNaiveFluxErr:
270 apCorrErr = apCorrErrModel.evaluate(center)
274 if apCorrInfo.doApCorrColumn:
275 source.set(apCorrInfo.apCorrKey, apCorr)
276 source.set(apCorrInfo.apCorrErrKey, apCorrErr)
278 if apCorr <= 0.0
or apCorrErr < 0.0:
281 instFlux = source.get(apCorrInfo.instFluxKey)
282 instFluxErr = source.get(apCorrInfo.instFluxErrKey)
283 source.set(apCorrInfo.instFluxKey, instFlux*apCorr)
285 source.set(apCorrInfo.instFluxErrKey, instFluxErr*apCorr)
287 a = instFluxErr/instFlux
289 source.set(apCorrInfo.instFluxErrKey, abs(instFlux*apCorr)*math.sqrt(a*a + b*b))
290 source.set(apCorrInfo.apCorrFlagKey,
False)
291 if self.config.doFlagApCorrFailures:
292 source.set(apCorrInfo.fluxFlagKey, oldFluxFlagState)
294 if self.log.getLevel() <= self.log.DEBUG:
296 apCorrArr = np.array([s.get(apCorrInfo.apCorrKey)
for s
in catalog])
297 apCorrErrArr = np.array([s.get(apCorrInfo.apCorrErrKey)
for s
in catalog])
298 self.log.debug(
"For instFlux field %r: mean apCorr=%s, stdDev apCorr=%s, " 299 "mean apCorrErr=%s, stdDev apCorrErr=%s for %s sources",
300 apCorrInfo.name, apCorrArr.mean(), apCorrArr.std(),
301 apCorrErrArr.mean(), apCorrErrArr.std(), len(catalog))
def __init__(self, schema, kwds)
def __init__(self, schema, model, name=None)
def run(self, catalog, apCorrMap)