LSSTApplications  17.0+11,17.0+34,17.0+56,17.0+57,17.0+59,17.0+7,17.0-1-g377950a+33,17.0.1-1-g114240f+2,17.0.1-1-g4d4fbc4+28,17.0.1-1-g55520dc+49,17.0.1-1-g5f4ed7e+52,17.0.1-1-g6dd7d69+17,17.0.1-1-g8de6c91+11,17.0.1-1-gb9095d2+7,17.0.1-1-ge9fec5e+5,17.0.1-1-gf4e0155+55,17.0.1-1-gfc65f5f+50,17.0.1-1-gfc6fb1f+20,17.0.1-10-g87f9f3f+1,17.0.1-11-ge9de802+16,17.0.1-16-ga14f7d5c+4,17.0.1-17-gc79d625+1,17.0.1-17-gdae4c4a+8,17.0.1-2-g26618f5+29,17.0.1-2-g54f2ebc+9,17.0.1-2-gf403422+1,17.0.1-20-g2ca2f74+6,17.0.1-23-gf3eadeb7+1,17.0.1-3-g7e86b59+39,17.0.1-3-gb5ca14a,17.0.1-3-gd08d533+40,17.0.1-30-g596af8797,17.0.1-4-g59d126d+4,17.0.1-4-gc69c472+5,17.0.1-6-g5afd9b9+4,17.0.1-7-g35889ee+1,17.0.1-7-gc7c8782+18,17.0.1-9-gc4bbfb2+3,w.2019.22
LSSTDataManagementBasePackage
transformConfig.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import functools
24 import numpy
25 
26 import lsst.geom
27 from lsst.pex.config import Config, ListField, makeRegistry, \
28  ConfigDictField, ConfigurableField
29 from .transformFactory import makeTransform, makeIdentityTransform, \
30  makeRadialTransform
31 
32 __all__ = ["transformRegistry", "OneTransformConfig", "TransformConfig",
33  "IdentityTransformConfig", "AffineTransformConfig", "RadialTransformConfig",
34  "MultiTransformConfig"]
35 
36 transformRegistry = makeRegistry(
37  """"A registry of ``Transform`` factories
38 
39  A ``Transform`` factory is a function that obeys these rules:
40  - has an attribute ``ConfigClass``
41  - takes one argument, ``config`` (an instance of ``ConfigClass``) by name
42  - returns a ``Transform``
43  """
44 )
45 
46 
48  """A Config representing a ``Transform`` that does nothing.
49 
50  See Also
51  --------
52  lsst.afw.geom.makeIdentityTransform
53  """
54  pass
55 
56 
57 def identityFactory(config):
58  """Make an identity ``Transform``
59  """
60  return makeIdentityTransform()
61 
62 
63 identityFactory.ConfigClass = IdentityTransformConfig
64 transformRegistry.register("identity", identityFactory)
65 
66 
68  """A Config representing a single ``Transform`` in a compound ``Transform``.
69 
70  See Also
71  --------
72  lsst.afw.geom.MultiTransformConfig
73  """
74  transform = ConfigurableField(
75  doc="Transform factory",
76  target=identityFactory,
77  )
78 
79 
80 def invertingFactory(config):
81  """Invert a ``Transform`` specified by config.
82  """
83  return config.transform.apply().inverted()
84 
85 
86 invertingFactory.ConfigClass = OneTransformConfig
87 transformRegistry.register("inverted", invertingFactory)
88 
89 
91  """A Config representing an affine ``Transform``.
92 
93  See Also
94  --------
95  lsst.afw.geom.makeTransform
96  """
97  linear = ListField(
98  doc="2x2 linear matrix in the usual numpy order; "
99  "to rotate a vector by theta use: cos(theta), sin(theta), "
100  "-sin(theta), cos(theta)",
101  dtype=float,
102  length=4,
103  default=(1, 0, 0, 1),
104  )
105  translation = ListField(
106  doc="x, y translation vector",
107  dtype=float,
108  length=2,
109  default=(0, 0),
110  )
111 
112 
113 def affineFactory(config):
114  """Make an affine ``Transform``
115  """
116  linear = numpy.array(config.linear)
117  linear.shape = (2, 2)
118  translation = numpy.array(config.translation)
119  return makeTransform(lsst.geom.AffineTransform(linear, translation))
120 
121 
122 affineFactory.ConfigClass = AffineTransformConfig
123 transformRegistry.register("affine", affineFactory)
124 
125 
127  """A Config representing a radially symmetric ``Transform``.
128 
129  See Also
130  --------
131  lsst.afw.geom.makeRadialTransform
132  """
133  coeffs = ListField(
134  doc="Coefficients for the radial polynomial; coeff[0] must be 0",
135  dtype=float,
136  minLength=1,
137  optional=False,
138  )
139 
140  def validate(self):
141  if len(self.coeffs) == 0:
142  return
143  if len(self.coeffs) == 1 or self.coeffs[0] != 0 or self.coeffs[1] == 0:
144  raise RuntimeError(
145  "invalid radial transform coeffs %s: " % (self.coeffs,) +
146  "need len(coeffs)=0 or len(coeffs)>1, coeffs[0]==0, "
147  "and coeffs[1]!=0")
148 
149 
150 def radialFactory(config):
151  """Make a radial ``Transform``
152  """
153  return makeRadialTransform(config.coeffs._list)
154 
155 
156 radialFactory.ConfigClass = RadialTransformConfig
157 transformRegistry.register("radial", radialFactory)
158 
159 
161  """A Config representing a chain of consecutive ``Transforms``.
162  """
163  transformDict = ConfigDictField(
164  doc="Dict of index: OneTransformConfig (a transform wrapper); "
165  "key order is transform order",
166  keytype=int,
167  itemtype=OneTransformConfig,
168  )
169 
170 
171 def multiFactory(config):
172  """Concatenate multiple ``Transforms``
173  """
174  transformKeys = sorted(config.transformDict.keys())
175  transformList = [config.transformDict[key].transform.apply()
176  for key in transformKeys]
177 
178  # Can't use then(self, other) directly because no single Transform class
179  def concat(transform1, transform2):
180  return transform1.then(transform2)
181 
182  return functools.reduce(concat, transformList)
183 
184 
185 multiFactory.ConfigClass = MultiTransformConfig
186 transformRegistry.register("multi", multiFactory)
187 
188 
190  """Config that identifies ``Transforms`` by keyword.
191 
192  Supported configs:
193 
194  ``"identity"``
195  `IdentityTransformConfig`
196  ``"inverted"``
197  `OneTransformConfig`
198  ``"affine"``
199  `AffineTransformConfig`
200  ``"radial"``
201  `RadialTransformConfig`
202  ``"multi"``
203  `MultiTransformConfig`
204  """
205  transform = transformRegistry.makeField(
206  doc="a Transform from the registry"
207  )
std::shared_ptr< TransformPoint2ToPoint2 > makeIdentityTransform()
Trivial Transform x → x.
std::shared_ptr< TransformPoint2ToPoint2 > makeRadialTransform(std::vector< double > const &coeffs)
A purely radial polynomial distortion.
An affine coordinate transformation consisting of a linear transformation and an offset.
def makeRegistry(doc, configBaseType=Config)
Definition: registry.py:331
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.