LSSTApplications  16.0-10-g0ee56ad+5,16.0-11-ga33d1f2+5,16.0-12-g3ef5c14+3,16.0-12-g71e5ef5+18,16.0-12-gbdf3636+3,16.0-13-g118c103+3,16.0-13-g8f68b0a+3,16.0-15-gbf5c1cb+4,16.0-16-gfd17674+3,16.0-17-g7c01f5c+3,16.0-18-g0a50484+1,16.0-20-ga20f992+8,16.0-21-g0e05fd4+6,16.0-21-g15e2d33+4,16.0-22-g62d8060+4,16.0-22-g847a80f+4,16.0-25-gf00d9b8+1,16.0-28-g3990c221+4,16.0-3-gf928089+3,16.0-32-g88a4f23+5,16.0-34-gd7987ad+3,16.0-37-gc7333cb+2,16.0-4-g10fc685+2,16.0-4-g18f3627+26,16.0-4-g5f3a788+26,16.0-5-gaf5c3d7+4,16.0-5-gcc1f4bb+1,16.0-6-g3b92700+4,16.0-6-g4412fcd+3,16.0-6-g7235603+4,16.0-69-g2562ce1b+2,16.0-8-g14ebd58+4,16.0-8-g2df868b+1,16.0-8-g4cec79c+6,16.0-8-gadf6c7a+1,16.0-8-gfc7ad86,16.0-82-g59ec2a54a+1,16.0-9-g5400cdc+2,16.0-9-ge6233d7+5,master-g2880f2d8cf+3,v17.0.rc1
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.