26 "GeneralPsfFitterComponentConfig",
27 "GeneralPsfFitterConfig" 30 import lsst.pex.config
33 GeneralPsfFitterControl, GeneralPsfFitterComponentControl,
34 GeneralPsfFitter, GeneralPsfFitterAlgorithm,
35 DoubleShapeletPsfApproxAlgorithm, DoubleShapeletPsfApproxControl
39 lsst.meas.base.wrapSimpleAlgorithm(
40 DoubleShapeletPsfApproxAlgorithm,
41 Control=DoubleShapeletPsfApproxControl,
42 module=
'lsst.meas.modelfit',
43 name=
'modelfit_DoubleShapeletPsfApprox',
44 executionOrder=lsst.meas.base.BasePlugin.SHAPE_ORDER
48 GeneralPsfFitterComponentConfig = lsst.pex.config.makeConfigClass(
49 GeneralPsfFitterComponentControl,
50 module=
'lsst.meas.modelfit' 52 GeneralPsfFitterConfig = lsst.pex.config.makeConfigClass(
53 GeneralPsfFitterControl,
54 module=
'lsst.meas.modelfit' 56 GeneralPsfFitter.ConfigClass = GeneralPsfFitterConfig
60 models = lsst.pex.config.ConfigDictField(
62 itemtype=GeneralPsfFitterConfig,
63 doc=
"a dictionary of models that can be used to fit the PSF",
66 sequence = lsst.pex.config.ListField(
68 doc=(
"a sequence of model names indicating which models should be fit," 70 default=[
"DoubleShapelet"]
74 super(GeneralShapeletPsfApproxConfig, self).
setDefaults()
76 self.models[
"SingleGaussian"].inner.order = -1
77 self.models[
"SingleGaussian"].primary.order = 0
78 self.models[
"SingleGaussian"].wings.order = -1
79 self.models[
"SingleGaussian"].outer.order = -1
81 self.models[
"DoubleGaussian"].inner.order = -1
82 self.models[
"DoubleGaussian"].primary.order = 0
83 self.models[
"DoubleGaussian"].wings.order = 0
84 self.models[
"DoubleGaussian"].outer.order = -1
86 self.models[
"DoubleShapelet"].inner.order = -1
87 self.models[
"DoubleShapelet"].primary.order = 2
88 self.models[
"DoubleShapelet"].wings.order = 1
89 self.models[
"DoubleShapelet"].outer.order = -1
91 self.models[
"Full"].inner.order = 0
92 self.models[
"Full"].primary.order = 4
93 self.models[
"Full"].wings.order = 4
94 self.models[
"Full"].outer.order = 0
97 super(GeneralShapeletPsfApproxConfig, self).
validate()
98 if len(self.sequence) < 1:
99 raise ValueError(
"sequence must have at least one element")
100 for m
in self.sequence:
101 if m
not in self.models:
103 "All elements in sequence must be keys in models dict" 108 """Mixin base class for fitting shapelet approximations to the PSF model 110 This class does almost all of the work for its two derived classes, 111 GeneralShapeletPsfApproxSingleFramePlugin and 112 GeneralShapeletPsfApproxForcedPlugin, which simply adapt it to the 113 slightly different interfaces for single-frame and forced measurement. It 114 in turn delegates its work to the C++ GeneralPsfFitter class; it holds 115 sequence of these corresponding to different models (generally with 116 increasing complexity). Each GeneralPsfFitter starts with the result of 117 the previous one as an input, using GeneralPsfFitter::adapt to hopefully 118 allow these previous fits to reduce the time spent on the next one. 120 At present, this plugin does not define any failure flags, which will 121 almost certainly have to be changed in the future. So far, however, I 122 haven't actually seen it fail on any PSFs I've given it, so I'll wait 123 until we can run on large enough data volumes to see what the actual 124 failure modes are, instead of trying to guess them in advance. 128 """Initialize the plugin, creating a sequence of GeneralPsfFitter 129 instances to do the fitting and MultiShapeletFunctionKey instances to 130 save the results to a record. 133 for m
in config.sequence:
137 schema[name][m].getPrefix()
142 """Fit the configured sequence of models the given Exposure's Psf, as 143 evaluated at measRecord.getCentroid(), then save the results to 146 if not exposure.hasPsf():
148 "GeneralShapeletPsfApprox requires Exposure to have a Psf")
149 psf = exposure.getPsf()
150 psfImage = psf.computeKernelImage(measRecord.getCentroid())
151 psfShape = psf.computeShape(measRecord.getCentroid())
160 if lastModel
is None:
161 fitter.measure(measRecord, psfImage, psfShape)
163 fitter.measure(measRecord, psfImage,
164 fitter.adapt(lastResult, lastModel))
165 lastResult = measRecord.get(fitter.getKey())
166 lastModel = fitter.getModel()
167 except lsst.meas.base.baseMeasurement.FATAL_EXCEPTIONS:
170 fitter.fail(measRecord, error.cpp)
172 except Exception
as error:
173 fitter.fail(measRecord)
178 if lastError
is not None:
183 def fail(self, measRecord, error=None):
187 class GeneralShapeletPsfApproxSingleFrameConfig(
189 GeneralShapeletPsfApproxConfig
193 lsst.meas.base.SingleFramePluginConfig.setDefaults(self)
194 GeneralShapeletPsfApproxConfig.setDefaults(self)
197 @lsst.meas.base.register(
"modelfit_GeneralShapeletPsfApprox")
200 GeneralShapeletPsfApproxMixin
202 """Minimal subclass of GeneralShapeletPsfApproxMixin to conform to the 203 single-frame measurement API. 205 This class simply provides __init__ and measure methods that matched the 206 SingleFramePlugin signatures and delegate to the 207 GeneralShapeletPsfApproxMixin's implementations. 209 ConfigClass = GeneralShapeletPsfApproxSingleFrameConfig
215 def __init__(self, config, name, schema, metadata):
216 GeneralShapeletPsfApproxMixin.__init__(self, config, name, schema)
217 lsst.meas.base.SingleFramePlugin.__init__(self, config, name, schema,
221 GeneralShapeletPsfApproxMixin.measure(self, measRecord, exposure)
223 def fail(self, measRecord, error=None):
224 GeneralShapeletPsfApproxMixin.fail(self, measRecord, error)
229 GeneralShapeletPsfApproxConfig
233 lsst.meas.base.ForcedPluginConfig.setDefaults(self)
234 GeneralShapeletPsfApproxConfig.setDefaults(self)
237 @lsst.meas.base.register(
"modelfit_GeneralShapeletPsfApprox")
240 GeneralShapeletPsfApproxMixin
242 """Minimal subclass of GeneralShapeletPsfApproxMixin to conform to the 243 forced measurement API. 245 This class simply provides __init__ and measure methods that matched the 246 ForcedPlugin signatures and delegate to the 247 GeneralShapeletPsfApproxMixin's implementations. 249 ConfigClass = GeneralShapeletPsfApproxForcedConfig
255 def __init__(self, config, name, schemaMapper, metadata):
256 GeneralShapeletPsfApproxMixin.__init__(self, config, name,
257 schemaMapper.editOutputSchema())
258 lsst.meas.base.ForcedPlugin.__init__(self, config, name, schemaMapper,
261 def measure(self, measRecord, exposure, refRecord, refWcs):
262 GeneralShapeletPsfApproxMixin.measure(self, measRecord, exposure)
264 def fail(self, measRecord, error=None):
265 GeneralShapeletPsfApproxMixin.fail(self, measRecord, error)
def __init__(self, config, name, schemaMapper, metadata)
def fail(self, measRecord, error=None)
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
Exception to be thrown when a measurement algorithm experiences a fatal error.
def measure(self, measRecord, exposure)
def __init__(self, config, name, schema, metadata)
def __init__(self, config, name, schema)
def measure(self, measRecord, exposure)
def measure(self, measRecord, exposure, refRecord, refWcs)
def fail(self, measRecord, error=None)
def fail(self, measRecord, error=None)