22"""Definition of measurement plugins.
24This module defines and registers a series of pure-Python measurement plugins
25which have trivial implementations. It also wraps measurement algorithms
26defined in C++ to expose them to the measurement framework.
37from ._measBaseLib
import (ApertureFluxControl, ApertureFluxTransform,
38 BaseTransform, BlendednessAlgorithm,
39 BlendednessControl, CircularApertureFluxAlgorithm,
40 GaussianFluxAlgorithm, GaussianFluxControl,
41 GaussianFluxTransform, LocalBackgroundAlgorithm,
42 LocalBackgroundControl, LocalBackgroundTransform,
44 PeakLikelihoodFluxAlgorithm,
45 PeakLikelihoodFluxControl,
46 PeakLikelihoodFluxTransform, PixelFlagsAlgorithm,
47 PixelFlagsControl, PsfFluxAlgorithm, PsfFluxControl,
48 PsfFluxTransform, ScaledApertureFluxAlgorithm,
49 ScaledApertureFluxControl,
50 ScaledApertureFluxTransform, SdssCentroidAlgorithm,
51 SdssCentroidControl, SdssCentroidTransform,
52 SdssShapeAlgorithm, SdssShapeControl,
55from .baseMeasurement
import BaseMeasurementPluginConfig
56from .forcedMeasurement
import ForcedPlugin, ForcedPluginConfig
57from .pluginRegistry
import register
58from .pluginsBase
import BasePlugin
59from .sfm
import SingleFramePlugin, SingleFramePluginConfig
60from .transforms
import SimpleCentroidTransform
61from .wrappers
import GenericPlugin, wrapSimpleAlgorithm, wrapTransform
64 "SingleFrameFPPositionConfig",
"SingleFrameFPPositionPlugin",
65 "SingleFrameJacobianConfig",
"SingleFrameJacobianPlugin",
66 "VarianceConfig",
"SingleFrameVariancePlugin",
"ForcedVariancePlugin",
67 "InputCountConfig",
"SingleFrameInputCountPlugin",
"ForcedInputCountPlugin",
68 "SingleFramePeakCentroidConfig",
"SingleFramePeakCentroidPlugin",
69 "SingleFrameSkyCoordConfig",
"SingleFrameSkyCoordPlugin",
70 "SingleFrameClassificationSizeExtendednessConfig",
71 "SingleFrameClassificationSizeExtendednessPlugin",
72 "ForcedPeakCentroidConfig",
"ForcedPeakCentroidPlugin",
73 "ForcedTransformedCentroidConfig",
"ForcedTransformedCentroidPlugin",
74 "ForcedTransformedCentroidFromCoordConfig",
75 "ForcedTransformedCentroidFromCoordPlugin",
76 "ForcedTransformedShapeConfig",
"ForcedTransformedShapePlugin",
77 "EvaluateLocalPhotoCalibPlugin",
"EvaluateLocalPhotoCalibPluginConfig",
78 "EvaluateLocalWcsPlugin",
"EvaluateLocalWcsPluginConfig",
83 TransformClass=PsfFluxTransform, executionOrder=BasePlugin.FLUX_ORDER,
84 shouldApCorr=
True, hasLogName=
True)
86 TransformClass=PeakLikelihoodFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
88 TransformClass=GaussianFluxTransform, executionOrder=BasePlugin.FLUX_ORDER,
91 TransformClass=SdssCentroidTransform, executionOrder=BasePlugin.CENTROID_ORDER)
93 executionOrder=BasePlugin.FLUX_ORDER)
95 TransformClass=SdssShapeTransform, executionOrder=BasePlugin.SHAPE_ORDER)
97 TransformClass=ScaledApertureFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
100 TransformClass=ApertureFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
102 TransformClass=BaseTransform, executionOrder=BasePlugin.SHAPE_ORDER)
105 TransformClass=LocalBackgroundTransform, executionOrder=BasePlugin.FLUX_ORDER)
116log = logging.getLogger(__name__)
120 """Configuration for the focal plane position measurement algorithm.
126 """Algorithm to calculate the position of a centroid on the focal plane.
130 config : `SingleFrameFPPositionConfig`
131 Plugin configuration.
134 schema : `lsst.afw.table.Schema`
135 The schema for the measurement output catalog. New fields will be
136 added to hold measurements produced by this plugin.
137 metadata : `lsst.daf.base.PropertySet`
138 Plugin metadata that will be attached to the output catalog
141 ConfigClass = SingleFrameFPPositionConfig
147 def __init__(self, config, name, schema, metadata):
148 SingleFramePlugin.__init__(self, config, name, schema, metadata)
149 self.
focalValue = lsst.afw.table.Point2DKey.addFields(schema, name,
"Position on the focal plane",
151 self.
focalFlag = schema.addField(name +
"_flag", type=
"Flag", doc=
"Set to True for any fatal failure")
152 self.
detectorFlag = schema.addField(name +
"_missingDetector_flag", type=
"Flag",
153 doc=
"Set to True if detector object is missing")
156 det = exposure.getDetector()
161 center = measRecord.getCentroid()
162 fp = det.transform(center, lsst.afw.cameraGeom.PIXELS, lsst.afw.cameraGeom.FOCAL_PLANE)
165 def fail(self, measRecord, error=None):
170 """Configuration for the Jacobian calculation plugin.
173 pixelScale = lsst.pex.config.Field(dtype=float, default=0.5, doc=
"Nominal pixel size (arcsec)")
176@register("base_Jacobian")
178 """Compute the Jacobian and its ratio with a nominal pixel area.
180 This enables one to compare relative, rather than absolute, pixel areas.
184 config : `SingleFrameJacobianConfig`
185 Plugin configuration.
188 schema : `lsst.afw.table.Schema`
189 The schema for the measurement output catalog. New fields will be
190 added to hold measurements produced by this plugin.
191 metadata : `lsst.daf.base.PropertySet`
192 Plugin metadata that will be attached to the output catalog
195 ConfigClass = SingleFrameJacobianConfig
201 def __init__(self, config, name, schema, metadata):
202 SingleFramePlugin.__init__(self, config, name, schema, metadata)
203 self.
jacValue = schema.addField(name +
'_value', type=
"D", doc=
"Jacobian correction")
204 self.
jacFlag = schema.addField(name +
'_flag', type=
"Flag", doc=
"Set to 1 for any fatal failure")
210 center = measRecord.getCentroid()
213 result = np.abs(self.
scale*exposure.getWcs().linearizePixelToSky(
215 lsst.geom.arcseconds).getLinear().computeDeterminant())
216 measRecord.set(self.
jacValue, result)
218 def fail(self, measRecord, error=None):
219 measRecord.set(self.
jacFlag,
True)
223 """Configuration for the variance calculation plugin.
225 scale = lsst.pex.config.Field(dtype=float, default=5.0, optional=
True,
226 doc=
"Scale factor to apply to shape for aperture")
227 mask = lsst.pex.config.ListField(doc=
"Mask planes to ignore", dtype=str,
228 default=[
"DETECTED",
"DETECTED_NEGATIVE",
"BAD",
"SAT"])
232 """Compute the median variance corresponding to a footprint.
234 The aim here is to measure the background variance, rather than that of
235 the object itself. In order to achieve this, the variance is calculated
236 over an area scaled up from the shape of the input footprint.
240 config : `VarianceConfig`
241 Plugin configuration.
244 schema : `lsst.afw.table.Schema`
245 The schema for the measurement output catalog. New fields will be
246 added to hold measurements produced by this plugin.
247 metadata : `lsst.daf.base.PropertySet`
248 Plugin metadata that will be attached to the output catalog
251 ConfigClass = VarianceConfig
253 FAILURE_BAD_CENTROID = 1
254 """Denotes failures due to bad centroiding (`int`).
257 FAILURE_EMPTY_FOOTPRINT = 2
258 """Denotes failures due to a lack of usable pixels (`int`).
263 return BasePlugin.FLUX_ORDER
265 def __init__(self, config, name, schema, metadata):
266 GenericPlugin.__init__(self, config, name, schema, metadata)
267 self.
varValue = schema.addField(name +
'_value', type=
"D", doc=
"Variance at object position")
269 doc=
"Set to True when the footprint has no usable pixels")
274 schema.getAliasMap().set(name +
'_flag_badCentroid', schema.getAliasMap().apply(
"slot_Centroid_flag"))
276 def measure(self, measRecord, exposure, center):
280 if not np.all(np.isfinite(measRecord.getCentroid())):
282 aperture = lsst.afw.geom.Ellipse(measRecord.getShape(), measRecord.getCentroid())
283 aperture.scale(self.
config.scale)
286 foot.clipTo(exposure.getBBox(lsst.afw.image.PARENT))
289 maskedImage = exposure.getMaskedImage()
291 maskBits = maskedImage.getMask().getPlaneBitMask(self.
config.mask)
292 logicalMask = np.logical_not(pixels.getMaskArray() & maskBits)
297 if np.any(logicalMask):
298 medVar = np.median(pixels.getVarianceArray()[logicalMask])
299 measRecord.set(self.
varValue, medVar)
301 raise MeasurementError(
"Footprint empty, or all pixels are masked, can't compute median",
304 def fail(self, measRecord, error=None):
307 if isinstance(error, MeasurementError):
312 measRecord.set(self.
varValue, np.nan)
313 GenericPlugin.fail(self, measRecord, error)
316SingleFrameVariancePlugin = VariancePlugin.makeSingleFramePlugin(
"base_Variance")
317"""Single-frame version of `VariancePlugin`.
320ForcedVariancePlugin = VariancePlugin.makeForcedPlugin(
"base_Variance")
321"""Forced version of `VariancePlugin`.
326 """Configuration for the input image counting plugin.
330class InputCountPlugin(GenericPlugin):
331 """Count the number of input images which contributed to a source.
335 config : `InputCountConfig`
336 Plugin configuration.
339 schema : `lsst.afw.table.Schema`
340 The schema for the measurement output catalog. New fields will be
341 added to hold measurements produced by this plugin.
342 metadata : `lsst.daf.base.PropertySet`
343 Plugin metadata that will be attached to the output catalog
347 Information is derived from the image's `~lsst.afw.image.CoaddInputs`.
348 Note these limitation:
350 - This records the number of images which contributed to the pixel in the
351 center of the source footprint, rather than to any or all pixels in the
353 - Clipping in the coadd is not taken into account.
356 ConfigClass = InputCountConfig
358 FAILURE_BAD_CENTROID = 1
359 """Denotes failures due to bad centroiding (`int`).
362 FAILURE_NO_INPUTS = 2
363 """Denotes failures due to the image not having coadd inputs. (`int`)
368 return BasePlugin.SHAPE_ORDER
370 def __init__(self, config, name, schema, metadata):
371 GenericPlugin.__init__(self, config, name, schema, metadata)
372 self.
numberKey = schema.addField(name +
'_value', type=
"I",
373 doc=
"Number of images contributing at center, not including any"
375 self.
noInputsFlag = schema.addField(name +
'_flag_noInputs', type=
"Flag",
376 doc=
"No coadd inputs available")
380 schema.getAliasMap().set(name +
'_flag_badCentroid', schema.getAliasMap().apply(
"slot_Centroid_flag"))
382 def measure(self, measRecord, exposure, center):
383 if not (coaddInputs := exposure.getInfo().getCoaddInputs()):
385 if not np.all(np.isfinite(center)):
388 count = len(coaddInputs.subset_containing_ccds(center, exposure.wcs))
391 def fail(self, measRecord, error=None):
392 if error
is not None:
397 GenericPlugin.fail(self, measRecord, error)
400SingleFrameInputCountPlugin = InputCountPlugin.makeSingleFramePlugin(
"base_InputCount")
401"""Single-frame version of `InputCoutPlugin`.
404ForcedInputCountPlugin = InputCountPlugin.makeForcedPlugin(
"base_InputCount")
405"""Forced version of `InputCoutPlugin`.
410 """Configuration for the variance calculation plugin.
414class EvaluateLocalPhotoCalibPlugin(GenericPlugin):
415 """Evaluate the local value of the Photometric Calibration in the exposure.
417 The aim is to store the local calib value within the catalog for later
418 use in the Science Data Model functors.
420 ConfigClass = EvaluateLocalPhotoCalibPluginConfig
424 return BasePlugin.FLUX_ORDER
426 def __init__(self, config, name, schema, metadata):
427 GenericPlugin.__init__(self, config, name, schema, metadata)
431 doc=
"Local approximation of the PhotoCalib calibration factor at "
432 "the location of the src.")
436 doc=
"Error on the local approximation of the PhotoCalib "
437 "calibration factor at the location of the src.")
439 def measure(self, measRecord, exposure, center):
440 photoCalib = exposure.getPhotoCalib()
441 if photoCalib
is None:
443 "%s: photoCalib is None. Setting localPhotoCalib to NaN for record %d",
451 calib = photoCalib.getLocalCalibration(center)
452 calibErr = photoCalib.getCalibrationErr()
453 measRecord.set(self.
photoKey, calib)
457SingleFrameEvaluateLocalPhotoCalibPlugin = EvaluateLocalPhotoCalibPlugin.makeSingleFramePlugin(
458 "base_LocalPhotoCalib")
459"""Single-frame version of `EvaluatePhotoCalibPlugin`.
462ForcedEvaluateLocalPhotoCalibPlugin = EvaluateLocalPhotoCalibPlugin.makeForcedPlugin(
463 "base_LocalPhotoCalib")
464"""Forced version of `EvaluatePhotoCalibPlugin`.
469 """Configuration for the variance calculation plugin.
473class EvaluateLocalWcsPlugin(GenericPlugin):
474 """Evaluate the local, linear approximation of the Wcs.
476 The aim is to store the local calib value within the catalog for later
477 use in the Science Data Model functors.
479 ConfigClass = EvaluateLocalWcsPluginConfig
480 _scale = (1.0 * lsst.geom.arcseconds).asDegrees()
484 return BasePlugin.FLUX_ORDER
486 def __init__(self, config, name, schema, metadata):
487 GenericPlugin.__init__(self, config, name, schema, metadata)
489 f
"{name}_CDMatrix_1_1",
491 doc=
"(1, 1) element of the CDMatrix for the linear approximation "
492 "of the WCS at the src location. Gives units in radians.")
494 f
"{name}_CDMatrix_1_2",
496 doc=
"(1, 2) element of the CDMatrix for the linear approximation "
497 "of the WCS at the src location. Gives units in radians.")
499 f
"{name}_CDMatrix_2_1",
501 doc=
"(2, 1) element of the CDMatrix for the linear approximation "
502 "of the WCS at the src location. Gives units in radians.")
504 f
"{name}_CDMatrix_2_2",
506 doc=
"(2, 2) element of the CDMatrix for the linear approximation "
507 "of the WCS at the src location. Gives units in radians.")
509 def measure(self, measRecord, exposure, center):
510 wcs = exposure.getWcs()
513 "%s: WCS is None. Setting localWcs matrix values to NaN for record %d",
517 localMatrix = np.array([[np.nan, np.nan], [np.nan, np.nan]])
527 """Create a local, linear approximation of the wcs transformation
530 The approximation is created as if the center is at RA=0, DEC=0. All
531 comparing x,y coordinate are relative to the position of center. Matrix
532 is initially calculated with units arcseconds and then converted to
533 radians. This yields higher precision results due to quirks in AST.
537 wcs : `lsst.afw.geom.SkyWcs`
539 center : `lsst.geom.Point2D`
540 Point at which to evaluate the LocalWcs.
544 localMatrix : `numpy.ndarray`
545 Matrix representation the local wcs approximation with units
548 skyCenter = wcs.pixelToSky(center)
551 measurementToLocalGnomonic = wcs.getTransform().then(
552 localGnomonicWcs.getTransform().inverted()
554 localMatrix = measurementToLocalGnomonic.getJacobian(center)
555 return np.radians(localMatrix / 3600)
558SingleFrameEvaluateLocalWcsPlugin = EvaluateLocalWcsPlugin.makeSingleFramePlugin(
"base_LocalWcs")
559"""Single-frame version of `EvaluateLocalWcsPlugin`.
562ForcedEvaluateLocalWcsPlugin = EvaluateLocalWcsPlugin.makeForcedPlugin(
"base_LocalWcs")
563"""Forced version of `EvaluateLocalWcsPlugin`.
568 """Configuration for the single frame peak centroiding algorithm.
574 """Record the highest peak in a source footprint as its centroid.
576 This is of course a relatively poor measure of the true centroid of the
577 object; this algorithm is provided mostly for testing and debugging.
581 config : `SingleFramePeakCentroidConfig`
582 Plugin configuration.
585 schema : `lsst.afw.table.Schema`
586 The schema for the measurement output catalog. New fields will be
587 added to hold measurements produced by this plugin.
588 metadata : `lsst.daf.base.PropertySet`
589 Plugin metadata that will be attached to the output catalog
592 ConfigClass = SingleFramePeakCentroidConfig
598 def __init__(self, config, name, schema, metadata):
599 SingleFramePlugin.__init__(self, config, name, schema, metadata)
600 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixel")
601 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixel")
602 self.
flag = schema.addField(name +
"_flag", type=
"Flag", doc=
"Centroiding failed")
605 peak = measRecord.getFootprint().getPeaks()[0]
606 measRecord.set(self.
keyX, peak.getFx())
607 measRecord.set(self.
keyY, peak.getFy())
609 def fail(self, measRecord, error=None):
610 measRecord.set(self.
flag,
True)
614 return SimpleCentroidTransform
618 """Configuration for the sky coordinates algorithm.
624 """Record the sky position and uncertainties of an object based on its
625 centroid slot and WCS.
627 The position is recorded in the ``coord`` field, which is part of the
628 `~lsst.afw.table.SourceCatalog` minimal schema. The associated
629 uncertainty fields propagate the centroid covariance through a Jacobian
630 taken in a local tangent (gnomonic) plane centered on the source.
634 config : `SingleFrameSkyCoordConfig`
635 Plugin configuration.
638 schema : `lsst.afw.table.Schema`
639 The schema for the measurement output catalog. New fields will be
640 added to hold measurements produced by this plugin.
641 metadata : `lsst.daf.base.PropertySet`
642 Plugin metadata that will be attached to the output catalog
645 ConfigClass = SingleFrameSkyCoordConfig
651 def __init__(self, config, name, schema, metadata):
652 SingleFramePlugin.__init__(self, config, name, schema, metadata)
653 if "coord_raErr" not in schema:
660 if not exposure.hasWcs():
661 raise RuntimeError(
"Wcs not attached to exposure. Required for " + self.
name +
" algorithm")
662 measRecord.updateCoord(exposure.getWcs())
664 def fail(self, measRecord, error=None):
672class SingleFrameClassificationSizeExtendednessConfig(SingleFramePluginConfig):
673 """Configuration for moments-based star-galaxy classifier."""
675 exponent = lsst.pex.config.Field[float](
676 doc=
"Exponent to raise the PSF size squared (Ixx + Iyy) to, "
677 "in the likelihood normalization",
682@register("base_ClassificationSizeExtendedness")
684 """Classify objects by comparing their moments-based trace radius to PSF's.
686 The plugin computes chi^2 as ((T_obj - T_psf)/T_psf^exponent)^2, where
687 T_obj is the sum of Ixx and Iyy moments of the object, and T_psf is the
688 sum of Ixx and Iyy moments of the PSF. The exponent is configurable.
689 The measure of being a galaxy is then 1 - exp(-0.5*chi^2).
693 config : `SingleFrameClassificationSizeExtendednessConfig`
694 Plugin configuration.
697 schema : `~lsst.afw.table.Schema`
698 The schema for the measurement output catalog. New fields will be
699 added to hold measurements produced by this plugin.
700 metadata : `~lsst.daf.base.PropertySet`
701 Plugin metadata that will be attached to the output catalog.
705 The ``measure`` method of the plugin requires a value for the ``exposure``
706 argument to maintain consistent API, but it is not used in the measurement.
709 ConfigClass = SingleFrameClassificationSizeExtendednessConfig
711 FAILURE_BAD_SHAPE = 1
712 """Denotes failures due to bad shape (`int`).
719 def __init__(self, config, name, schema, metadata):
720 SingleFramePlugin.__init__(self, config, name, schema, metadata)
721 self.
key = schema.addField(name +
"_value",
723 doc=
"Measure of being a galaxy based on trace of second order moments",
725 self.
flag = schema.addField(name +
"_flag", type=
"Flag", doc=
"Moments-based classification failed")
727 def measure(self, measRecord, exposure) -> None:
730 if measRecord.getShapeFlag():
732 "Shape flag is set. Required for " + self.
name +
" algorithm",
736 shape = measRecord.getShape()
737 psf_shape = measRecord.getPsfShape()
741 ixx_psf = psf_shape.getIxx()
742 iyy_psf = psf_shape.getIyy()
745 psf_t = ixx_psf + iyy_psf
747 chi_sq = ((object_t - psf_t)/(psf_t**self.
config.exponent))**2.
748 likelihood = 1. - np.exp(-0.5*chi_sq)
749 measRecord.set(self.
key, likelihood)
751 def fail(self, measRecord, error=None) -> None:
753 measRecord.set(self.
key, np.nan)
754 measRecord.set(self.
flag,
True)
758 """Configuration for the forced peak centroid algorithm.
764 """Record the highest peak in a source footprint as its centroid.
766 This is of course a relatively poor measure of the true centroid of the
767 object; this algorithm is provided mostly for testing and debugging.
769 This is similar to `SingleFramePeakCentroidPlugin`, except that transforms
770 the peak coordinate from the original (reference) coordinate system to the
771 coordinate system of the exposure being measured.
775 config : `ForcedPeakCentroidConfig`
776 Plugin configuration.
779 schemaMapper : `lsst.afw.table.SchemaMapper`
780 A mapping from reference catalog fields to output
781 catalog fields. Output fields are added to the output schema.
782 metadata : `lsst.daf.base.PropertySet`
783 Plugin metadata that will be attached to the output catalog.
786 ConfigClass = ForcedPeakCentroidConfig
792 def __init__(self, config, name, schemaMapper, metadata):
793 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
794 schema = schemaMapper.editOutputSchema()
795 self.
keyX = schema.addField(name +
"_x", type=
"D", doc=
"peak centroid", units=
"pixel")
796 self.
keyY = schema.addField(name +
"_y", type=
"D", doc=
"peak centroid", units=
"pixel")
798 def measure(self, measRecord, exposure, refRecord, refWcs):
799 targetWcs = exposure.getWcs()
800 peak = refRecord.getFootprint().getPeaks()[0]
802 result = targetWcs.skyToPixel(refWcs.pixelToSky(result))
803 measRecord.set(self.
keyX, result.getX())
804 measRecord.set(self.
keyY, result.getY())
808 return SimpleCentroidTransform
812 """Configuration for the forced transformed centroid algorithm.
816@
register(
"base_TransformedCentroid")
818 """Record the transformation of the reference catalog centroid.
820 The centroid recorded in the reference catalog is tranformed to the
821 measurement coordinate system and stored.
825 config : `ForcedTransformedCentroidConfig`
829 schemaMapper : `lsst.afw.table.SchemaMapper`
830 A mapping from reference catalog fields to output
831 catalog fields. Output fields are added to the output schema.
832 metadata : `lsst.daf.base.PropertySet`
833 Plugin metadata that will be attached to the output catalog.
837 This is used as the slot centroid by default in forced measurement,
838 allowing subsequent measurements to simply refer to the slot value just as
839 they would in single-frame measurement.
842 ConfigClass = ForcedTransformedCentroidConfig
848 def __init__(self, config, name, schemaMapper, metadata):
849 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
850 schema = schemaMapper.editOutputSchema()
853 xKey = schema.addField(name +
"_x", type=
"D", doc=
"transformed reference centroid column",
855 yKey = schema.addField(name +
"_y", type=
"D", doc=
"transformed reference centroid row",
861 if "slot_Centroid_flag" in schemaMapper.getInputSchema():
862 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
863 doc=
"whether the reference centroid is marked as bad")
867 def measure(self, measRecord, exposure, refRecord, refWcs):
868 targetWcs = exposure.getWcs()
869 if not refWcs == targetWcs:
870 targetPos = targetWcs.skyToPixel(refWcs.pixelToSky(refRecord.getCentroid()))
873 measRecord.set(self.
centroidKey, refRecord.getCentroid())
875 measRecord.set(self.
flagKey, refRecord.getCentroidFlag())
879 """Configuration for the forced transformed coord algorithm.
883@
register(
"base_TransformedCentroidFromCoord")
885 """Record the transformation of the reference catalog coord.
887 The coord recorded in the reference catalog is tranformed to the
888 measurement coordinate system and stored.
892 config : `ForcedTransformedCentroidFromCoordConfig`
896 schemaMapper : `lsst.afw.table.SchemaMapper`
897 A mapping from reference catalog fields to output
898 catalog fields. Output fields are added to the output schema.
899 metadata : `lsst.daf.base.PropertySet`
900 Plugin metadata that will be attached to the output catalog.
904 This can be used as the slot centroid in forced measurement when only a
905 reference coord exist, allowing subsequent measurements to simply refer to
906 the slot value just as they would in single-frame measurement.
909 ConfigClass = ForcedTransformedCentroidFromCoordConfig
911 def measure(self, measRecord, exposure, refRecord, refWcs):
912 targetWcs = exposure.getWcs()
914 targetPos = targetWcs.skyToPixel(refRecord.getCoord())
918 measRecord.set(self.
flagKey, refRecord.getCentroidFlag())
922 """Configuration for the forced transformed shape algorithm.
928 """Record the transformation of the reference catalog shape.
930 The shape recorded in the reference catalog is tranformed to the
931 measurement coordinate system and stored.
935 config : `ForcedTransformedShapeConfig`
939 schemaMapper : `lsst.afw.table.SchemaMapper`
940 A mapping from reference catalog fields to output
941 catalog fields. Output fields are added to the output schema.
942 metadata : `lsst.daf.base.PropertySet`
943 Plugin metadata that will be attached to the output catalog.
947 This is used as the slot shape by default in forced measurement, allowing
948 subsequent measurements to simply refer to the slot value just as they
949 would in single-frame measurement.
952 ConfigClass = ForcedTransformedShapeConfig
958 def __init__(self, config, name, schemaMapper, metadata):
959 ForcedPlugin.__init__(self, config, name, schemaMapper, metadata)
960 schema = schemaMapper.editOutputSchema()
963 xxKey = schema.addField(name +
"_xx", type=
"D", doc=
"transformed reference shape x^2 moment",
965 yyKey = schema.addField(name +
"_yy", type=
"D", doc=
"transformed reference shape y^2 moment",
967 xyKey = schema.addField(name +
"_xy", type=
"D", doc=
"transformed reference shape xy moment",
973 if "slot_Shape_flag" in schemaMapper.getInputSchema():
974 self.
flagKey = schema.addField(name +
"_flag", type=
"Flag",
975 doc=
"whether the reference shape is marked as bad")
979 def measure(self, measRecord, exposure, refRecord, refWcs):
980 targetWcs = exposure.getWcs()
981 if not refWcs == targetWcs:
984 measRecord.set(self.
shapeKey, refRecord.getShape().transform(localTransform.getLinear()))
986 measRecord.set(self.
shapeKey, refRecord.getShape())
988 measRecord.set(self.
flagKey, refRecord.getShapeFlag())
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, lsst::geom::Point2I offset=lsst::geom::Point2I())
static ErrorKey addErrorFields(Schema &schema)
Exception to be thrown when a measurement algorithm experiences a known failure mode.
__init__(self, config, name, schema, metadata)
measure(self, measRecord, exposure, center)
__init__(self, config, name, schema, metadata)
measure(self, measRecord, exposure, center)
makeLocalTransformMatrix(self, wcs, center)
measure(self, measRecord, exposure, refRecord, refWcs)
__init__(self, config, name, schemaMapper, metadata)
None fail(self, measRecord, error=None)
__init__(self, config, name, schema, metadata)
None measure(self, measRecord, exposure)
fail(self, measRecord, error=None)
measure(self, measRecord, exposure)
__init__(self, config, name, schema, metadata)
measure(self, measRecord, exposure)
fail(self, measRecord, error=None)
__init__(self, config, name, schema, metadata)
fail(self, measRecord, error=None)
__init__(self, config, name, schema, metadata)
measure(self, measRecord, exposure)
__init__(self, config, name, schema, metadata)
fail(self, measRecord, error=None)
measure(self, measRecord, exposure)
int FAILURE_EMPTY_FOOTPRINT
__init__(self, config, name, schema, metadata)
fail(self, measRecord, error=None)
measure(self, measRecord, exposure, center)
HeavyFootprint< ImagePixelT, MaskPixelT, VariancePixelT > makeHeavyFootprint(Footprint const &foot, lsst::afw::image::MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > const &img, HeavyFootprintCtrl const *ctrl=nullptr)
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
lsst::geom::AffineTransform linearizeTransform(TransformPoint2ToPoint2 const &original, lsst::geom::Point2D const &inPoint)
register(name, shouldApCorr=False, apCorrList=())
wrapTransform(transformClass, hasLogName=False)
wrapSimpleAlgorithm(AlgClass, executionOrder, name=None, needsMetadata=False, hasMeasureN=False, hasLogName=False, deprecated=None, **kwds)