24 Definitions and registration of pure-Python plugins with trivial implementations,
25 and automatic plugin-from-algorithm calls for those implemented in C++.
32 from .pluginRegistry
import register
33 from .
import baseLib
as bl
34 from .baseMeasurement
import BasePlugin
35 from .sfm
import SingleFramePluginConfig, SingleFramePlugin
36 from .forcedMeasurement
import ForcedPluginConfig, ForcedPlugin
37 from .wrappers
import wrapSimpleAlgorithm
38 from .transforms
import SimpleCentroidTransform
41 "SingleFramePeakCentroidConfig",
"SingleFramePeakCentroidPlugin",
42 "SingleFrameSkyCoordConfig",
"SingleFrameSkyCoordPlugin",
43 "SingleFrameClassificationConfig",
"SingleFrameClassificationPlugin",
44 "ForcedPeakCentroidConfig",
"ForcedPeakCentroidPlugin",
45 "ForcedTransformedCentroidConfig",
"ForcedTransformedCentroidPlugin",
46 "ForcedTransformedShapeConfig",
"ForcedTransformedShapePlugin",
52 TransformClass=bl.PsfFluxTransform, executionOrder=BasePlugin.FLUX_ORDER, shouldApCorr=
True)
54 TransformClass=bl.PeakLikelihoodFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
56 TransformClass=bl.GaussianFluxTransform, executionOrder=BasePlugin.FLUX_ORDER, shouldApCorr=
True)
58 TransformClass=bl.GaussianCentroidTransform, executionOrder=BasePlugin.CENTROID_ORDER)
60 TransformClass=bl.NaiveCentroidTransform, executionOrder=BasePlugin.CENTROID_ORDER)
62 TransformClass=bl.SdssCentroidTransform, executionOrder=BasePlugin.CENTROID_ORDER)
63 wrapSimpleAlgorithm(bl.PixelFlagsAlgorithm, Control=bl.PixelFlagsControl, executionOrder=BasePlugin.FLUX_ORDER)
65 TransformClass=bl.SdssShapeTransform, executionOrder=BasePlugin.SHAPE_ORDER)
67 wrapSimpleAlgorithm(bl.CircularApertureFluxAlgorithm, needsMetadata=
True, Control=bl.ApertureFluxControl,
68 TransformClass=bl.ApertureFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
78 A centroid algorithm that simply uses the first (i.e. highest) Peak in the Source's
79 Footprint as the centroid. This is of course a relatively poor measure of the true
80 centroid of the object; this algorithm is provided mostly for testing and debugging.
83 ConfigClass = SingleFramePeakCentroidConfig
87 return cls.CENTROID_ORDER
89 def __init__(self, config, name, schema, metadata):
90 SingleFramePlugin.__init__(self, config, name, schema, metadata)
91 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixels")
92 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixels")
95 peak = measRecord.getFootprint().getPeaks()[0]
96 measRecord.set(self.
keyX, peak.getFx())
97 measRecord.set(self.
keyY, peak.getFy())
101 return SimpleCentroidTransform
109 A measurement plugin that sets the "coord" field (part of the Source minimal schema)
110 using the slot centroid and the Wcs attached to the Exposure.
113 ConfigClass = SingleFrameSkyCoordConfig
117 return cls.SHAPE_ORDER
122 if not exposure.hasWcs():
123 raise Exception(
"Wcs not attached to exposure. Required for " + self.name +
" algorithm")
124 measRecord.updateCoord(exposure.getWcs())
126 def fail(self, measRecord, error=None):
133 class SingleFrameClassificationConfig(SingleFramePluginConfig):
135 fluxRatio = lsst.pex.config.Field(dtype=float, default=.925, optional=
True,
136 doc=
"critical ratio of model to psf flux")
137 modelErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=
True,
138 doc=
"correction factor for modelFlux error")
139 psfErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=
True,
140 doc=
"correction factor for psfFlux error")
142 @
register(
"base_ClassificationExtendedness")
145 A binary measure of the extendedness of a source, based a simple cut on the ratio of the
146 PSF flux to the model flux.
148 Because the fluxes on which this algorithm is based are slot measurements, they can be provided
149 by different algorithms, and the "fluxRatio" threshold used by this algorithm should generally
150 be set differently for different algorithms. To do this, plot the difference between the PSF
151 magnitude and the model magnitude vs. the PSF magnitude, and look for where the cloud of galaxies
155 ConfigClass = SingleFrameClassificationConfig
159 return cls.CLASSIFY_ORDER
161 def __init__(self, config, name, schema, metadata):
162 SingleFramePlugin.__init__(self, config, name, schema, metadata)
164 doc=
"Set to 1 for extended sources, 0 for point sources.")
165 self.
keyFlag = schema.addField(name +
"_flag", type=
"Flag", doc=
"Set to 1 for any fatal failure.")
168 modelFlux = measRecord.getModelFlux()
169 psfFlux = measRecord.getPsfFlux()
170 modelFluxFlag = (measRecord.getModelFluxFlag()
171 if measRecord.table.getModelFluxFlagKey().isValid()
173 psfFluxFlag = (measRecord.getPsfFluxFlag()
174 if measRecord.table.getPsfFluxFlagKey().isValid()
176 flux1 = self.config.fluxRatio*modelFlux
177 if not self.config.modelErrFactor == 0:
178 flux1 += self.config.modelErrFactor*measRecord.getModelFluxErr()
180 if not self.config.psfErrFactor == 0:
181 flux2 += self.config.psfErrFactor*measRecord.getPsfFluxErr()
187 if numpy.isnan(flux1)
or numpy.isnan(flux2)
or modelFluxFlag
or psfFluxFlag:
188 self.
fail(measRecord)
195 def fail(self, measRecord, error=None):
198 measRecord.set(self.
keyFlag,
True)
209 The forced peak centroid is like the SFM peak centroid plugin, except that it must transform
210 the peak coordinate from the original (reference) coordinate system to the coordinate system
211 of the exposure being measured.
214 ConfigClass = ForcedPeakCentroidConfig
218 return cls.CENTROID_ORDER
220 def __init__(self, config, name, schemaMapper, metadata):
221 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
222 schema = schemaMapper.editOutputSchema()
223 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixels")
224 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixels")
226 def measure(self, measRecord, exposure, refRecord, refWcs):
227 targetWcs = exposure.getWcs()
228 peak = refRecord.getFootprint().getPeaks()[0]
230 if not refWcs == targetWcs:
231 result = targetWcs.skyToPixel(refWcs.pixelToSky(result))
232 measRecord.set(self.
keyX, result.getX())
233 measRecord.set(self.
keyY, result.getY())
237 return SimpleCentroidTransform
242 @
register(
"base_TransformedCentroid")
244 """A centroid pseudo-algorithm for forced measurement that simply transforms the centroid
245 from the reference catalog to the measurement coordinate system. This is used as
246 the slot centroid by default in forced measurement, allowing subsequent measurements
247 to simply refer to the slot value just as they would in single-frame measurement.
250 ConfigClass = ForcedTransformedCentroidConfig
254 return cls.CENTROID_ORDER
256 def __init__(self, config, name, schemaMapper, metadata):
257 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
258 schema = schemaMapper.editOutputSchema()
260 xKey = schema.addField(name +
"_x", type=
"D", doc=
"transformed reference centroid column",
262 yKey = schema.addField(name +
"_y", type=
"D", doc=
"transformed reference centroid row",
268 if "slot_Centroid_flag" in schemaMapper.getInputSchema():
269 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
270 doc=
"whether the reference centroid is marked as bad")
274 def measure(self, measRecord, exposure, refRecord, refWcs):
275 targetWcs = exposure.getWcs()
276 if not refWcs == targetWcs:
277 targetPos = targetWcs.skyToPixel(refWcs.pixelToSky(refRecord.getCentroid()))
280 measRecord.set(self.
centroidKey, refRecord.getCentroid())
282 measRecord.set(self.
flagKey, refRecord.getCentroidFlag())
290 """A shape pseudo-algorithm for forced measurement that simply transforms the shape
291 from the reference catalog to the measurement coordinate system. This is used as
292 the slot shape by default in forced measurement, allowing subsequent measurements
293 to simply refer to the slot value just as they would in single-frame measurement.
296 ConfigClass = ForcedTransformedShapeConfig
300 return cls.SHAPE_ORDER
302 def __init__(self, config, name, schemaMapper, metadata):
303 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
304 schema = schemaMapper.editOutputSchema()
306 xxKey = schema.addField(name +
"_xx", type=
"D", doc=
"transformed reference shape x^2 moment",
308 yyKey = schema.addField(name +
"_yy", type=
"D", doc=
"transformed reference shape y^2 moment",
310 xyKey = schema.addField(name +
"_xy", type=
"D", doc=
"transformed reference shape xy moment",
316 if "slot_Shape_flag" in schemaMapper.getInputSchema():
317 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
318 doc=
"whether the reference shape is marked as bad")
322 def measure(self, measRecord, exposure, refRecord, refWcs):
323 targetWcs = exposure.getWcs()
324 if not refWcs == targetWcs:
326 localTransform = fullTransform.linearizeForwardTransform(refRecord.getCentroid())
327 measRecord.set(self.
shapeKey, refRecord.getShape().transform(localTransform.getLinear()))
329 measRecord.set(self.
shapeKey, refRecord.getShape())
331 measRecord.set(self.
flagKey, refRecord.getShapeFlag())
def wrapSimpleAlgorithm
Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes...
A FunctorKey used to get or set a geom::ellipses::Quadrupole from a tuple of constituent Keys...