1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #include <iostream>
20 
21 #include "itkTransform.h"
22 
23 namespace itk
24 {
25 namespace itkTransformTestHelpers
26 {
27 
28 template <
29   typename TScalar,
30   unsigned int NInputDimensions,
31   unsigned int NOutputDimensions>
32 class TransformTestHelper :
33   public Transform< TScalar, NInputDimensions, NOutputDimensions >
34 {
35 public:
36   using Self = TransformTestHelper;
37   using Superclass = Transform< TScalar, NInputDimensions, NOutputDimensions >;
38   using Pointer = SmartPointer< Self >;
39   using ConstPointer = SmartPointer< const Self >;
40 
41   itkNewMacro( Self );
42   itkTypeMacro( TransformTestHelper, Transform );
43 
44   using JacobianType = typename Superclass::JacobianType;
45   using JacobianPositionType = typename Superclass::JacobianPositionType;
46 
47   using ParametersType = typename Superclass::ParametersType;
48   using InputPointType = typename Superclass::InputPointType;
49   using OutputPointType = typename Superclass::OutputPointType;
50   using InputVectorType = typename Superclass::InputVectorType;
51   using OutputVectorType = typename Superclass::OutputVectorType;
52   using InputVectorPixelType = typename Superclass::InputVectorPixelType;
53   using OutputVectorPixelType = typename Superclass::OutputVectorPixelType;
54   using InputVnlVectorType = typename Superclass::InputVnlVectorType;
55   using OutputVnlVectorType = typename Superclass::OutputVnlVectorType;
56   using InputCovariantVectorType = typename Superclass::InputCovariantVectorType;
57   using OutputCovariantVectorType = typename Superclass::OutputCovariantVectorType;
58 
59   using InputDiffusionTensor3DType = typename Superclass::InputDiffusionTensor3DType;
60   using OutputDiffusionTensor3DType = typename Superclass::OutputDiffusionTensor3DType;
61 
62   using InputSymmetricSecondRankTensorType = typename Superclass::InputSymmetricSecondRankTensorType;
63   using OutputSymmetricSecondRankTensorType = typename Superclass::OutputSymmetricSecondRankTensorType;
64 
TransformPoint(const InputPointType & itkNotUsed (inputPoint)) const65   OutputPointType TransformPoint(const InputPointType  & itkNotUsed(inputPoint) ) const override
66   {
67     OutputPointType outPoint;
68     outPoint.Fill( 22.0 );
69     return outPoint;
70   }
71 
72   using Superclass::TransformVector;
TransformVector(const InputVectorType & itkNotUsed (inputVector)) const73   OutputVectorType TransformVector(const InputVectorType  & itkNotUsed(inputVector) ) const override
74   {
75     OutputVectorType outVector;
76     outVector.Fill( 12.2 );
77     return outVector;
78   }
79 
TransformVector(const InputVnlVectorType & itkNotUsed (inputVector)) const80   OutputVnlVectorType TransformVector(const InputVnlVectorType  & itkNotUsed(inputVector) ) const override
81   {
82     OutputVnlVectorType outVector( 15.0 );
83     return outVector;
84   }
85 
TransformVector(const InputVectorPixelType & itkNotUsed (inputVector)) const86   OutputVectorPixelType TransformVector(const InputVectorPixelType  & itkNotUsed(inputVector) ) const override
87   {
88     OutputVectorPixelType outVector;
89     outVector.Fill( 88.8 );
90     return outVector;
91   }
92 
93   using Superclass::TransformCovariantVector;
TransformCovariantVector(const InputCovariantVectorType & itkNotUsed (inputVector)) const94   OutputCovariantVectorType TransformCovariantVector(const InputCovariantVectorType  & itkNotUsed(inputVector) ) const override
95   {
96     OutputCovariantVectorType outVector;
97     outVector.Fill( 8.9 );
98     return outVector;
99   }
100 
TransformCovariantVector(const InputVectorPixelType & itkNotUsed (inputVector)) const101   OutputVectorPixelType TransformCovariantVector(const InputVectorPixelType  & itkNotUsed(inputVector) ) const override
102   {
103     OutputVectorPixelType outVector;
104     outVector.Fill( 6.9 );
105     return outVector;
106   }
107 
108   using Superclass::TransformDiffusionTensor3D;
TransformDiffusionTensor3D(const InputDiffusionTensor3DType & itkNotUsed (tensor)) const109   OutputDiffusionTensor3DType TransformDiffusionTensor3D( const InputDiffusionTensor3DType & itkNotUsed( tensor ) ) const override
110   {
111     OutputDiffusionTensor3DType outTensor;
112     outTensor.Fill( 2.1 );
113     return outTensor;
114   }
115 
TransformDiffusionTensor3D(const InputVectorPixelType & itkNotUsed (tensor)) const116   OutputVectorPixelType TransformDiffusionTensor3D( const InputVectorPixelType & itkNotUsed( tensor ) ) const override
117   {
118     OutputVectorPixelType outTensor;
119     outTensor.Fill( 29.1 );
120     return outTensor;
121   }
122 
123   using Superclass::TransformSymmetricSecondRankTensor;
TransformSymmetricSecondRankTensor(const InputSymmetricSecondRankTensorType & itkNotUsed (tensor)) const124   OutputSymmetricSecondRankTensorType TransformSymmetricSecondRankTensor(
125     const InputSymmetricSecondRankTensorType & itkNotUsed( tensor ) ) const override
126   {
127     OutputSymmetricSecondRankTensorType outTensor;
128     outTensor.Fill( 10.0 );
129     return outTensor;
130   }
131 
TransformSymmetricSecondRankTensor(const InputVectorPixelType & itkNotUsed (tensor)) const132   OutputVectorPixelType TransformSymmetricSecondRankTensor(
133     const InputVectorPixelType & itkNotUsed( tensor ) ) const override
134   {
135     OutputVectorPixelType outTensor;
136     outTensor.Fill( 55.9 );
137     return outTensor;
138   }
139 
SetParameters(const ParametersType &)140   void SetParameters(const ParametersType &) override
141   {
142   }
143 
SetFixedParameters(const ParametersType &)144   void SetFixedParameters(const ParametersType &) override
145   {
146   }
147 
ComputeJacobianWithRespectToParameters(const InputPointType &,JacobianType & jacobian) const148   void ComputeJacobianWithRespectToParameters(const InputPointType &,
149                                                       JacobianType & jacobian) const override
150   {
151     jacobian.SetSize(3, 6);
152     jacobian.Fill(1);
153   }
154 
155   using Superclass::ComputeJacobianWithRespectToPosition;
ComputeJacobianWithRespectToPosition(const InputPointType &,JacobianPositionType & jacobian) const156   void ComputeJacobianWithRespectToPosition(
157     const InputPointType &,
158     JacobianPositionType & jacobian ) const override
159   {
160     jacobian.fill(1.0);
161   }
162 
163 };
164 
165 template <
166   typename TScalar,
167   unsigned int NInputDimensions,
168   unsigned int NOutputDimensions>
169 class TransformTester
170 {
171 public:
172   using Self = TransformTester;
173 
174   using TransformType = TransformTestHelper<double, NInputDimensions, NOutputDimensions>;
175 
176   using JacobianType = typename TransformType::JacobianType;
177   using ParametersType = typename TransformType::ParametersType;
178   using InputPointType = typename TransformType::InputPointType;
179   using OutputPointType = typename TransformType::OutputPointType;
180   using InputVectorType = typename TransformType::InputVectorType;
181   using OutputVectorType = typename TransformType::OutputVectorType;
182   using InputVectorPixelType = typename TransformType::InputVectorPixelType;
183   using OutputVectorPixelType = typename TransformType::OutputVectorPixelType;
184   using InputVnlVectorType = typename TransformType::InputVnlVectorType;
185   using OutputVnlVectorType = typename TransformType::OutputVnlVectorType;
186   using InputCovariantVectorType = typename TransformType::InputCovariantVectorType;
187   using OutputCovariantVectorType = typename TransformType::OutputCovariantVectorType;
188 
189   using InputDiffusionTensor3DType = typename TransformType::InputDiffusionTensor3DType;
190   using OutputDiffusionTensor3DType = typename TransformType::OutputDiffusionTensor3DType;
191 
192   using InputSymmetricSecondRankTensorType = typename TransformType::InputSymmetricSecondRankTensorType;
193   using OutputSymmetricSecondRankTensorType = typename TransformType::OutputSymmetricSecondRankTensorType;
194 
RunTests()195   bool RunTests()
196   {
197     std::cout << "Testing itkTransform<" << NInputDimensions << "," << NOutputDimensions << ">" << std::endl;
198     typename TransformType::Pointer transform = TransformType::New();
199 
200     InputPointType pnt;
201     pnt.Fill(2.9);
202 
203     transform->TransformPoint(pnt);
204     std::cout << "TransformPoint()                              OK" << std::endl;
205 
206     InputVectorType vec;
207     transform->TransformVector(vec);
208     transform->TransformVector(vec,pnt);
209 
210     InputVectorPixelType vecpix;
211     vecpix.SetSize( NInputDimensions );
212     vecpix.Fill(1.7);
213     transform->TransformVector(vecpix);
214     transform->TransformVector(vecpix,pnt);
215 
216     InputVnlVectorType vec_vnl;
217     transform->TransformVector(vec_vnl);
218     transform->TransformVector(vec_vnl,pnt);
219     std::cout << "TransformVector()                             OK" << std::endl;
220 
221     InputCovariantVectorType covec;
222     transform->TransformCovariantVector(covec);
223     transform->TransformCovariantVector(vecpix);
224     transform->TransformCovariantVector(covec,pnt);
225     transform->TransformCovariantVector(vecpix,pnt);
226     std::cout << "TransformCovariantVector()                    OK" << std::endl;
227 
228     InputDiffusionTensor3DType difften;
229     vecpix.SetSize( 6 );
230     vecpix.Fill(1.7);
231     transform->TransformDiffusionTensor3D(difften);
232     transform->TransformDiffusionTensor3D(difften,pnt);
233     transform->TransformDiffusionTensor3D(vecpix);
234     transform->TransformDiffusionTensor3D(vecpix,pnt);
235     std::cout << "TransformDiffusionTensor3D()                  OK" << std::endl;
236 
237     InputSymmetricSecondRankTensorType ssrten;
238     vecpix.SetSize(NInputDimensions*NInputDimensions);
239     vecpix.Fill(0);
240     transform->TransformSymmetricSecondRankTensor(ssrten);
241     transform->TransformSymmetricSecondRankTensor(ssrten,pnt);
242     transform->TransformSymmetricSecondRankTensor(vecpix);
243     transform->TransformSymmetricSecondRankTensor(vecpix,pnt);
244     std::cout << "TransformSymmetricSecondRankTensor()          OK" << std::endl;
245 
246     typename TransformType::ParametersType parameters(6);
247     try
248       {
249       transform->SetParameters(parameters);
250       }
251     catch( itk::ExceptionObject & e )
252       {
253       std::cerr << e << std::endl;
254       }
255 
256     try
257       {
258       transform->GetParameters();
259       }
260     catch( itk::ExceptionObject & e )
261       {
262       std::cerr << e << std::endl;
263       }
264 
265     typename TransformType::JacobianType jacobian;
266     try
267       {
268       transform->ComputeJacobianWithRespectToParameters(pnt, jacobian);
269       }
270     catch( itk::ExceptionObject & e )
271       {
272       std::cerr << e << std::endl;
273       }
274 
275     typename TransformType::JacobianPositionType jacobian_position;
276     try
277       {
278       transform->ComputeJacobianWithRespectToPosition(pnt, jacobian_position);
279       }
280     catch( itk::ExceptionObject & e )
281       {
282       std::cerr << e << std::endl;
283       }
284 
285     typename TransformType::InverseJacobianPositionType inv_jacobian_position;
286     try
287       {
288       transform->ComputeInverseJacobianWithRespectToPosition(pnt, inv_jacobian_position);
289       }
290     catch( itk::ExceptionObject & e )
291       {
292       std::cerr << e << std::endl;
293       }
294 
295     typename TransformType::DerivativeType update( transform->GetNumberOfParameters() );
296     update.Fill(1);
297     try
298       {
299     transform->UpdateTransformParameters( update );
300       }
301     catch( itk::ExceptionObject & e )
302       {
303       std::cerr << e << std::endl;
304       }
305 
306     // Exercise some methods
307     transform->Print( std::cout );
308     std::cout <<  transform->GetNameOfClass() << std::endl;
309 
310     return true;
311   }
312 
313 };
314 
315 
316 }
317 }
318 
itkTransformTest(int,char * [])319 int itkTransformTest(int, char * [] )
320 {
321   itk::itkTransformTestHelpers::TransformTester<double,3,3> tester33;
322   tester33.RunTests();
323   std::cout << "passed 3 3" << std::endl;
324 
325   itk::itkTransformTestHelpers::TransformTester<double,3,2> tester32;
326   tester32.RunTests();
327   std::cout << "passed 3 2" << std::endl;
328 
329   itk::itkTransformTestHelpers::TransformTester<double,2,3> tester23;
330   tester23.RunTests();
331   std::cout << "passed 2 3" << std::endl;
332 
333 
334   std::cout << "[ PASSED ]" << std::endl;
335   return EXIT_SUCCESS;
336 
337 }
338