24 Definitions and registration of pure-Python plugins with trivial implementations,
25 and automatic plugin-from-algorithm calls for those implemented in C++.
34 from .baseLib
import *
36 from .forcedMeasurement
import *
37 from .wrappers
import *
46 wrapSimpleAlgorithm(GaussianCentroidAlgorithm, Control=GaussianCentroidControl, executionOrder=0.0)
47 wrapSimpleAlgorithm(NaiveCentroidAlgorithm, Control=NaiveCentroidControl, executionOrder=0.0)
52 wrapSimpleAlgorithm(CircularApertureFluxAlgorithm, needsMetadata=
True, Control=ApertureFluxControl)
59 SingleFramePluginConfig.setDefaults(self)
65 A centroid algorithm that simply uses the first (i.e. highest) Peak in the Source's
66 Footprint as the centroid. This is of course a relatively poor measure of the true
67 centroid of the object; this algorithm is provided mostly for testing and debugging.
70 ConfigClass = SingleFramePeakCentroidConfig
72 def __init__(self, config, name, schema, metadata):
73 SingleFramePlugin.__init__(self, config, name, schema, metadata)
74 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixels")
75 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixels")
78 peak = measRecord.getFootprint().getPeaks()[0]
79 measRecord.set(self.
keyX, peak.getFx())
80 measRecord.set(self.
keyY, peak.getFy())
86 SingleFramePluginConfig.setDefaults(self)
92 A measurement plugin that sets the "coord" field (part of the Source minimal schema)
93 using the slot centroid and the Wcs attached to the Exposure.
95 ConfigClass = SingleFrameSkyCoordConfig
100 if not exposure.hasWcs():
101 raise Exception(
"Wcs not attached to exposure. Required for " + self.name +
" algorithm")
102 measRecord.updateCoord(exposure.getWcs())
104 def fail(self, measRecord, error=None):
110 class SingleFrameClassificationConfig(SingleFramePluginConfig):
112 fluxRatio = lsst.pex.config.Field(dtype=float, default=.925, optional=
True,
113 doc=
"critical ratio of model to psf flux")
114 modelErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=
True,
115 doc=
"correction factor for modelFlux error")
116 psfErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=
True,
117 doc=
"correction factor for psfFlux error")
119 SingleFramePluginConfig.setDefaults(self)
122 @
register(
"base_ClassificationExtendedness")
125 A binary measure of the extendedness of a source, based a simple cut on the ratio of the
126 PSF flux to the model flux.
128 Because the fluxes on which this algorithm is based are slot measurements, they can be provided
129 by different algorithms, and the "fluxRatio" threshold used by this algorithm should generally
130 be set differently for different algorithms. To do this, plot the difference between the PSF
131 magnitude and the model magnitude vs. the PSF magnitude, and look for where the cloud of galaxies
134 ConfigClass = SingleFrameClassificationConfig
136 def __init__(self, config, name, schema, metadata):
137 SingleFramePlugin.__init__(self, config, name, schema, metadata)
139 doc=
"Set to 1 for extended sources, 0 for point sources.")
142 modelFlux = measRecord.getModelFlux()
143 modelFluxErr = measRecord.getModelFluxErr()
144 psfFlux = measRecord.getPsfFlux()
145 psfFluxErr = measRecord.getPsfFluxErr()
146 flux1 = self.config.fluxRatio*modelFlux + self.config.modelErrFactor*modelFluxErr
147 flux2 = psfFlux + self.config.psfErrFactor*psfFluxErr
153 def fail(self, measRecord, error=None):
161 class ForcedPeakCentroidConfig(ForcedPluginConfig):
164 ForcedPluginConfig.setDefaults(self)
170 The forced peak centroid is like the SFM peak centroid plugin, except that it must transform
171 the peak coordinate from the original (reference) coordinate system to the coordinate system
172 of the exposure being measured.
174 ConfigClass = ForcedPeakCentroidConfig
176 def __init__(self, config, name, schemaMapper, metadata):
177 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
178 schema = schemaMapper.editOutputSchema()
179 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixels")
180 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixels")
182 def measure(self, measRecord, exposure, refRecord, refWcs):
183 targetWcs = exposure.getWcs()
184 peak = refRecord.getFootprint().getPeaks()[0]
186 if not refWcs == targetWcs:
187 result = targetWcs.skyToPixel(refWcs.pixelToSky(result))
188 measRecord.set(self.
keyX, result.getX())
189 measRecord.set(self.
keyY, result.getY())
195 ForcedPluginConfig.setDefaults(self)
198 @
register(
"base_TransformedCentroid")
200 """A centroid pseudo-algorithm for forced measurement that simply transforms the centroid
201 from the reference catalog to the measurement coordinate system. This is used as
202 the slot centroid by default in forced measurement, allowing subsequent measurements
203 to simply refer to the slot value just as they would in single-frame measurement.
206 ConfigClass = ForcedTransformedCentroidConfig
208 def __init__(self, config, name, schemaMapper, metadata):
209 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
210 schema = schemaMapper.editOutputSchema()
212 xKey = schema.addField(name +
"_x", type=
"D", doc=
"transformed reference centroid column",
214 yKey = schema.addField(name +
"_y", type=
"D", doc=
"transformed reference centroid row",
220 if "slot_Centroid_flag" in schemaMapper.getInputSchema():
221 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
222 doc=
"whether the reference centroid is marked as bad")
226 def measure(self, measRecord, exposure, refRecord, refWcs):
227 targetWcs = exposure.getWcs()
228 if not refWcs == targetWcs:
229 targetPos = targetWcs.skyToPixel(refWcs.pixelToSky(refRecord.getCentroid()))
232 measRecord.set(self.
centroidKey, refRecord.getCentroid())
234 measRecord.set(self.
flagKey, refRecord.getCentroidFlag())
240 ForcedPluginConfig.setDefaults(self)
245 """A shape pseudo-algorithm for forced measurement that simply transforms the shape
246 from the reference catalog to the measurement coordinate system. This is used as
247 the slot shape by default in forced measurement, allowing subsequent measurements
248 to simply refer to the slot value just as they would in single-frame measurement.
251 ConfigClass = ForcedTransformedShapeConfig
253 def __init__(self, config, name, schemaMapper, metadata):
254 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
255 schema = schemaMapper.editOutputSchema()
257 xxKey = schema.addField(name +
"_xx", type=
"D", doc=
"transformed reference shape x^2 moment",
259 yyKey = schema.addField(name +
"_yy", type=
"D", doc=
"transformed reference shape y^2 moment",
261 xyKey = schema.addField(name +
"_xy", type=
"D", doc=
"transformed reference shape xy moment",
267 if "slot_Shape_flag" in schemaMapper.getInputSchema():
268 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
269 doc=
"whether the reference shape is marked as bad")
273 def measure(self, measRecord, exposure, refRecord, refWcs):
274 targetWcs = exposure.getWcs()
275 if not refWcs == targetWcs:
277 localTransform = fullTransform.linearizeForwardTransform(refRecord.getCentroid())
278 measRecord.set(self.
shapeKey, refRecord.getShape().transform(localTransform.getLinear()))
280 measRecord.set(self.
shapeKey, refRecord.getShape())
282 measRecord.set(self.
flagKey, refRecord.getShapeFlag())
def wrapSimpleAlgorithm
Wrap a C++ SimpleAlgorithm class into both a Python SingleFramePlugin and ForcedPlugin classes...
def register
A Python decorator that registers a class, using the given name, in its base class's PluginRegistry...
A FunctorKey used to get or set a geom::ellipses::Quadrupole from an (xx,yy,xy) tuple of Keys...