26 "GeneralPsfFitterComponentConfig",
27 "GeneralPsfFitterConfig"
33 GeneralPsfFitterControl, GeneralPsfFitterComponentControl,
34 GeneralPsfFitter, GeneralPsfFitterAlgorithm,
35 DoubleShapeletPsfApproxAlgorithm, DoubleShapeletPsfApproxControl
39lsst.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
48GeneralPsfFitterComponentConfig = lsst.pex.config.makeConfigClass(
49 GeneralPsfFitterComponentControl,
50 module=
'lsst.meas.modelfit'
52GeneralPsfFitterConfig = lsst.pex.config.makeConfigClass(
53 GeneralPsfFitterControl,
54 module=
'lsst.meas.modelfit'
56GeneralPsfFitter.ConfigClass = GeneralPsfFitterConfig
62 itemtype=GeneralPsfFitterConfig,
63 doc=
"a dictionary of models that can be used to fit the PSF",
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:
134 fitter = GeneralPsfFitterAlgorithm(
137 schema[name][m].getPrefix()
139 self.
sequencesequence.
append((fitter, 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())
158 for fitter, name
in self.
sequencesequence:
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):
187class 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)
Exception to be thrown when a measurement algorithm experiences a fatal error.
Exception to be thrown when a measurement algorithm experiences a known failure mode.
def __init__(self, config, name, schemaMapper, metadata)
def fail(self, measRecord, error=None)
def measure(self, measRecord, exposure, refRecord, refWcs)
def fail(self, measRecord, error=None)
def measure(self, measRecord, exposure)
def __init__(self, config, name, schema)
def __init__(self, config, name, schema, metadata)
def measure(self, measRecord, exposure)
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.
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.