136 def run(self, exposure, catalog):
137 """Measure aperture correction
141 exposure : `lsst.afw.image.Exposure`
142 Exposure aperture corrections are being measured on. The
143 bounding box is retrieved from it, and it is passed to the
144 sourceSelector. The output aperture correction map is *not*
145 added to the exposure; this is left to the caller.
146 catalog : `lsst.afw.table.SourceCatalog`
147 SourceCatalog containing measurements to be used to
148 compute aperture corrections.
152 Struct : `lsst.pipe.base.Struct`
153 Contains the following:
156 aperture correction map (`lsst.afw.image.ApCorrMap`)
157 that contains two entries for each flux field:
158 - flux field (e.g. base_PsfFlux_instFlux): 2d model
159 - flux sigma field (e.g. base_PsfFlux_instFluxErr): 2d model of error
161 bbox = exposure.getBBox()
166 self.log.
info(
"Measuring aperture corrections for %d flux fields", len(self.toCorrect))
169 subset1 = [record
for record
in self.sourceSelector.
run(catalog, exposure=exposure).sourceCat
170 if (
not record.get(self.refFluxKeys.flag)
171 and numpy.isfinite(record.get(self.refFluxKeys.flux)))]
173 apCorrMap = ApCorrMap()
176 for name, keys
in self.toCorrect.
items():
177 fluxName = name +
"_instFlux"
178 fluxErrName = name +
"_instFluxErr"
182 fluxes = numpy.fromiter((record.get(keys.flux)
for record
in subset1), float)
183 with numpy.errstate(invalid=
"ignore"):
184 isGood = numpy.logical_and.reduce([
185 numpy.fromiter((
not record.get(keys.flag)
for record
in subset1), bool),
186 numpy.isfinite(fluxes),
189 subset2 = [record
for record, good
in zip(subset1, isGood)
if good]
193 if len(subset2) - 1 < self.config.minDegreesOfFreedom:
194 if name
in self.config.allowFailure:
195 self.log.
warning(
"Unable to measure aperture correction for '%s': "
196 "only %d sources, but require at least %d.",
197 name, len(subset2), self.config.minDegreesOfFreedom + 1)
199 raise RuntimeError(
"Unable to measure aperture correction for required algorithm '%s': "
200 "only %d sources, but require at least %d." %
201 (name, len(subset2), self.config.minDegreesOfFreedom + 1))
204 ctrl = self.config.fitConfig.makeControl()
205 while len(subset2) - ctrl.computeSize() < self.config.minDegreesOfFreedom:
212 x = numpy.zeros(len(subset2), dtype=float)
213 y = numpy.zeros(len(subset2), dtype=float)
214 apCorrData = numpy.zeros(len(subset2), dtype=float)
215 indices = numpy.arange(len(subset2), dtype=int)
216 for n, record
in enumerate(subset2):
219 apCorrData[n] = record.get(self.refFluxKeys.flux)/record.get(keys.flux)
221 for _i
in range(self.config.numIter):
224 apCorrField = ChebyshevBoundedField.fit(bbox, x, y, apCorrData, ctrl)
227 plotApCorr(bbox, x, y, apCorrData, apCorrField,
"%s, iteration %d" % (name, _i), doPause)
231 apCorrDiffs = apCorrField.evaluate(x, y)
232 apCorrDiffs -= apCorrData
233 apCorrErr = numpy.mean(apCorrDiffs**2)**0.5
236 apCorrDiffLim = self.config.numSigmaClip * apCorrErr
237 with numpy.errstate(invalid=
"ignore"):
238 keep = numpy.fabs(apCorrDiffs) <= apCorrDiffLim
241 apCorrData = apCorrData[keep]
242 indices = indices[keep]
245 apCorrField = ChebyshevBoundedField.fit(bbox, x, y, apCorrData, ctrl)
247 self.log.
info(
"Aperture correction for %s: RMS %f from %d",
248 name, numpy.mean((apCorrField.evaluate(x, y) - apCorrData)**2)**0.5, len(indices))
251 plotApCorr(bbox, x, y, apCorrData, apCorrField,
"%s, final" % (name,), doPause)
257 apCorrMap[fluxName] = apCorrField
258 apCorrErrCoefficients = numpy.array([[apCorrErr]], dtype=float)
259 apCorrMap[fluxErrName] = ChebyshevBoundedField(bbox, apCorrErrCoefficients)
263 subset2[i].
set(keys.used,
True)
std::vector< SchemaItem< Flag > > * items
daf::base::PropertySet * set
def run(self, coaddExposures, bbox, wcs)
def plotApCorr(bbox, xx, yy, zzMeasure, field, title, doPause)