27 ConfigDictField, ConfigurableField
28 from ._geom
import makeTransform, makeIdentityTransform, \
31 __all__ = [
"transformRegistry",
"OneTransformConfig",
"TransformConfig",
32 "IdentityTransformConfig",
"AffineTransformConfig",
"RadialTransformConfig",
33 "MultiTransformConfig"]
35 transformRegistry = makeRegistry(
36 """"A registry of ``Transform`` factories
38 A ``Transform`` factory is a function that obeys these rules:
39 - has an attribute ``ConfigClass``
40 - takes one argument, ``config`` (an instance of ``ConfigClass``) by name
41 - returns a ``Transform``
47 """A Config representing a ``Transform`` that does nothing.
51 lsst.afw.geom.makeIdentityTransform
57 """Make an identity ``Transform``
62 identityFactory.ConfigClass = IdentityTransformConfig
63 transformRegistry.register(
"identity", identityFactory)
67 """A Config representing a single ``Transform`` in a compound ``Transform``.
71 lsst.afw.geom.MultiTransformConfig
73 transform = ConfigurableField(
74 doc=
"Transform factory",
75 target=identityFactory,
80 """Invert a ``Transform`` specified by config.
82 return config.transform.apply().inverted()
85 invertingFactory.ConfigClass = OneTransformConfig
86 transformRegistry.register(
"inverted", invertingFactory)
90 """A Config representing an affine ``Transform``.
94 lsst.afw.geom.makeTransform
97 doc=
"2x2 linear matrix in the usual numpy order; "
98 "to rotate a vector by theta use: cos(theta), sin(theta), "
99 "-sin(theta), cos(theta)",
102 default=(1, 0, 0, 1),
104 translation = ListField(
105 doc=
"x, y translation vector",
113 """Make an affine ``Transform``
115 linear = numpy.array(config.linear)
116 linear.shape = (2, 2)
117 translation = numpy.array(config.translation)
121 affineFactory.ConfigClass = AffineTransformConfig
122 transformRegistry.register(
"affine", affineFactory)
126 """A Config representing a radially symmetric ``Transform``.
130 lsst.afw.geom.makeRadialTransform
133 doc=
"Coefficients for the radial polynomial; coeff[0] must be 0",
140 if len(self.
coeffscoeffs) == 0:
142 if len(self.
coeffscoeffs) == 1
or self.
coeffscoeffs[0] != 0
or self.
coeffscoeffs[1] == 0:
144 f
"invalid radial transform coeffs {self.coeffs}: "
145 "need len(coeffs)=0 or len(coeffs)>1, coeffs[0]==0, "
150 """Make a radial ``Transform``
155 radialFactory.ConfigClass = RadialTransformConfig
156 transformRegistry.register(
"radial", radialFactory)
160 """A Config representing a chain of consecutive ``Transforms``.
162 transformDict = ConfigDictField(
163 doc=
"Dict of index: OneTransformConfig (a transform wrapper); "
164 "key order is transform order",
166 itemtype=OneTransformConfig,
171 """Concatenate multiple ``Transforms``
173 transformKeys = sorted(config.transformDict.keys())
174 transformList = [config.transformDict[key].transform.apply()
175 for key
in transformKeys]
178 def concat(transform1, transform2):
179 return transform1.then(transform2)
181 return functools.reduce(concat, transformList)
184 multiFactory.ConfigClass = MultiTransformConfig
185 transformRegistry.register(
"multi", multiFactory)
189 """Config that identifies ``Transforms`` by keyword.
194 `IdentityTransformConfig`
198 `AffineTransformConfig`
200 `RadialTransformConfig`
202 `MultiTransformConfig`
204 transform = transformRegistry.makeField(
205 doc=
"a Transform from the registry"
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.
std::shared_ptr< TransformPoint2ToPoint2 > makeRadialTransform(std::vector< double > const &coeffs)
A purely radial polynomial distortion.
std::shared_ptr< TransformPoint2ToPoint2 > makeIdentityTransform()
Trivial Transform x → x.