TransformationJacobian.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_TransformationJacobian_H
21 #define MIRTK_TransformationJacobian_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Math.h"
26 #include "mirtk/Matrix.h"
27 #include "mirtk/Vector3D.h"
28 #include "mirtk/OrderedMap.h"
29 
30 
31 namespace mirtk {
32 
33 
34 /**
35  * Sparse matrix for the transformation Jacobian of derivatives w.r.t the parameters.
36  *
37  * This matrix type only stores the non-zero columns of the Jacobian matrix of
38  * the transformation, which contains the derivatives of the transformation
39  * w.r.t the transformation parameters. The full Jacobian matrix has dimension
40  * 3xN, where N is the number of transformation parameters and the number of
41  * rows correspond to the deformation in each spatial dimension (T_x, T_y, T_z).
42  */
44 {
45  mirtkObjectMacro(TransformationJacobian);
46 
47 public:
49  typedef OrderedMap<int, ColumnType> SparseMatrixType;
50  typedef SparseMatrixType::iterator ColumnIterator;
51  typedef SparseMatrixType::const_iterator ConstColumnIterator;
52  typedef Matrix DenseMatrixType;
53 
54 protected:
55 
56  /// Non-zero columns of transformation Jacobian
57  SparseMatrixType _Columns;
58 
59 public:
60 
61  // ---------------------------------------------------------------------------
62  // Construction/Destruction
63 
64  /// Constructor
66 
67  /// Destructor
69 
70  /// Remove all non-zero columns
71  void Clear();
72 
73  // ---------------------------------------------------------------------------
74  // Element access
75 
76  /// Get number of non-zero columns
77  int NumberOfNonZeroColumns() const;
78 
79  /// Get iterator to first non-zero column
80  ColumnIterator Begin();
81 
82  /// Get iterator to first non-zero column
83  ConstColumnIterator Begin() const;
84 
85  /// Get iterator to position after last non-zero column
86  ColumnIterator End();
87 
88  /// Get iterator to position after last non-zero column
89  ConstColumnIterator End() const;
90 
91  /// Get iterator to i-th non-zero column
92  ColumnIterator GetNonZeroColumn(int);
93 
94  /// Get iterator to i-th non-zero column
95  ConstColumnIterator GetNonZeroColumn(int) const;
96 
97  /// Get i-th non-zero column vector
98  ColumnType &operator [](int);
99 
100  /// Get i-th non-zero column vector
101  const ColumnType &operator [](int) const;
102 
103  /// Get i-th column vector
104  ColumnType &operator ()(int);
105 
106  /// Get column index of the i-th non-zero column.
107  int ColumnIndex(int) const;
108 
109  /// Get i-th non-zero column vector.
110  ColumnType &ColumnVector(int);
111 
112  /// Get i-th non-zero column vector.
113  const ColumnType &ColumnVector(int) const;
114 
115  /// Get i-th column vector, inserts new zero column if necessary.
116  ColumnType &Column(int);
117 
118  /// Get iterator to i-th column.
119  ColumnIterator Find(int);
120 
121  /// Get iterator to i-th column.
122  ConstColumnIterator Find(int) const;
123 
124  // ---------------------------------------------------------------------------
125  // Operators
126 
127  /// Add transformation Jacobian to this Jacobian matrix
129 
130  /// Multiply this transformation Jacobian by a scalar
131  TransformationJacobian &operator *=(const double);
132 
133  /// Pre-multiply (!) this transformation Jacobian with the given 3x3 matrix
135 
136  // ---------------------------------------------------------------------------
137  // Mathematical operations
138 
139  /// Add scaled transformation Jacobian to this Jacobian matrix
141 
142 };
143 
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 // Inline definitions
147 ////////////////////////////////////////////////////////////////////////////////
148 
149 // =============================================================================
150 // Construction/Destruction
151 // =============================================================================
152 
153 // -----------------------------------------------------------------------------
155 {
156 }
157 
158 // -----------------------------------------------------------------------------
160 {
161 }
162 
163 // =============================================================================
164 // Element access
165 // =============================================================================
166 
167 // -----------------------------------------------------------------------------
169 {
170  return _Columns.clear();
171 }
172 
173 // -----------------------------------------------------------------------------
175 {
176  return static_cast<int>(_Columns.size());
177 }
178 
179 // -----------------------------------------------------------------------------
180 inline TransformationJacobian::ColumnIterator TransformationJacobian::Begin()
181 {
182  return _Columns.begin();
183 }
184 
185 // -----------------------------------------------------------------------------
186 inline TransformationJacobian::ConstColumnIterator TransformationJacobian::Begin() const
187 {
188  return _Columns.begin();
189 }
190 
191 // -----------------------------------------------------------------------------
192 inline TransformationJacobian::ColumnIterator TransformationJacobian::End()
193 {
194  return _Columns.end();
195 }
196 
197 // -----------------------------------------------------------------------------
198 inline TransformationJacobian::ConstColumnIterator TransformationJacobian::End() const
199 {
200  return _Columns.end();
201 }
202 
203 // -----------------------------------------------------------------------------
204 inline TransformationJacobian::ColumnIterator TransformationJacobian::GetNonZeroColumn(int i)
205 {
206  ColumnIterator it = _Columns.begin();
207  for (int j = 0; j < i; j++) {
208  ++it;
209  if (it == _Columns.end()) {
210  cerr << "TransformationJacobian::GetNonZeroColumn: Index is out of bounds: " << i << endl;
211  exit(1);
212  }
213  }
214  return it;
215 }
216 
217 // -----------------------------------------------------------------------------
218 inline TransformationJacobian::ConstColumnIterator TransformationJacobian::GetNonZeroColumn(int i) const
219 {
220  ConstColumnIterator it = _Columns.begin();
221  for (int j = 0; j < i; j++) {
222  ++it;
223  if (it == _Columns.end()) {
224  cerr << "TransformationJacobian::GetNonZeroColumn: Index is out of bounds: " << i << endl;
225  exit(1);
226  }
227  }
228  return it;
229 }
230 
231 // -----------------------------------------------------------------------------
232 inline int TransformationJacobian::ColumnIndex(int i) const
233 {
234  return GetNonZeroColumn(i)->first;
235 }
236 
237 // -----------------------------------------------------------------------------
239 {
240  return GetNonZeroColumn(i)->second;
241 }
242 
243 // -----------------------------------------------------------------------------
245 {
246  return GetNonZeroColumn(i)->second;
247 }
248 
249 // -----------------------------------------------------------------------------
251 {
252  return _Columns[c];
253 }
254 
255 // -----------------------------------------------------------------------------
257 {
258  return GetNonZeroColumn(i)->second;
259 }
260 
261 // -----------------------------------------------------------------------------
263 {
264  return GetNonZeroColumn(i)->second;
265 }
266 
267 // -----------------------------------------------------------------------------
269 {
270  return Column(i);
271 }
272 
273 // -----------------------------------------------------------------------------
274 inline TransformationJacobian::ColumnIterator TransformationJacobian::Find(int c)
275 {
276  return _Columns.find(c);
277 }
278 
279 // -----------------------------------------------------------------------------
280 inline TransformationJacobian::ConstColumnIterator TransformationJacobian::Find(int c) const
281 {
282  return _Columns.find(c);
283 }
284 
285 // =============================================================================
286 // Unary operators
287 // =============================================================================
288 
289 // -----------------------------------------------------------------------------
291 {
292  for (ConstColumnIterator it = b.Begin(); it != b.End(); ++it) {
293  _Columns[it->first] += it->second;
294  }
295  return *this;
296 }
297 
298 // -----------------------------------------------------------------------------
300 {
301  for (ColumnIterator it = Begin(); it != End(); ++it) it->second *= s;
302  return *this;
303 }
304 
305 // -----------------------------------------------------------------------------
307 {
308  // Note: Read this operator as: a * (*this)!
309  ColumnType v;
310  for (ColumnIterator it = Begin(); it != End(); ++it) {
311  v._x = a(0, 0) * it->second._x + a(0, 1) * it->second._y + a(0, 2) * it->second._z;
312  v._y = a(1, 0) * it->second._x + a(1, 1) * it->second._y + a(1, 2) * it->second._z;
313  v._z = a(2, 0) * it->second._x + a(2, 1) * it->second._y + a(2, 2) * it->second._z;
314  it->second = v;
315  }
316  return *this;
317 }
318 
319 // =============================================================================
320 // Binary operators
321 // =============================================================================
322 
323 // -----------------------------------------------------------------------------
324 /// Calculate column-by-column sum of transformation Jacobian
326 {
328  c += b;
329  return c;
330 }
331 
332 // -----------------------------------------------------------------------------
333 /// Multiply transformation Jacobian and scalar
334 inline TransformationJacobian operator *(TransformationJacobian &a, double s)
335 {
337  b *= s;
338  return b;
339 }
340 
341 // -----------------------------------------------------------------------------
342 /// Multiply transformation Jacobian and scalar
343 inline TransformationJacobian operator *(double s, TransformationJacobian &a)
344 {
345  return a * s;
346 }
347 
348 // -----------------------------------------------------------------------------
349 /// Calculate product of 3x3 matrix and transformation Jacobian
351 {
353  c *= a;
354  return c;
355 }
356 
357 // =============================================================================
358 // Mathematical operations
359 // =============================================================================
360 
361 // -----------------------------------------------------------------------------
363 {
364  for (ConstColumnIterator it = b.Begin(); it != b.End(); ++it) {
365  _Columns[it->first] += it->second * s;
366  }
367  return *this;
368 }
369 
370 // =============================================================================
371 // Debugging
372 // =============================================================================
373 
374 inline bool has_nan(const TransformationJacobian &a)
375 {
376  for (TransformationJacobian::ConstColumnIterator it = a.Begin(); it != a.End(); ++it) {
377  if (IsNaN(it->second._x) || IsNaN(it->second._y) || IsNaN(it->second._z)) {
378  cerr << "TransformationJacobian::has_nan: Found NaN in column " << it->first << endl;
379  return true;
380  }
381  }
382  return false;
383 }
384 
385 
386 } // namespace mirtk
387 
388 #endif // MIRTK_TransformationJacobian_H
ColumnType & ColumnVector(int)
Get i-th non-zero column vector.
ColumnIterator End()
Get iterator to position after last non-zero column.
ColumnIterator Begin()
Get iterator to first non-zero column.
MIRTKCU_API bool IsNaN(double x)
Check if floating point value is not a number (NaN)
Definition: Math.h:91
ColumnIterator GetNonZeroColumn(int)
Get iterator to i-th non-zero column.
ColumnType & Column(int)
Get i-th column vector, inserts new zero column if necessary.
Definition: IOConfig.h:41
ColumnType & operator[](int)
Get i-th non-zero column vector.
TransformationJacobian & operator*=(const double)
Multiply this transformation Jacobian by a scalar.
int NumberOfNonZeroColumns() const
Get number of non-zero columns.
ColumnType & operator()(int)
Get i-th column vector.
T _z
The z component.
Definition: Vector3D.h:60
T _y
The y component.
Definition: Vector3D.h:59
ColumnIterator Find(int)
Get iterator to i-th column.
TransformationJacobian & add(const TransformationJacobian &, double)
Add scaled transformation Jacobian to this Jacobian matrix.
TransformationJacobian & operator+=(const TransformationJacobian &)
Add transformation Jacobian to this Jacobian matrix.
SparseMatrixType _Columns
Non-zero columns of transformation Jacobian.
T _x
The x component.
Definition: Vector3D.h:58
void Clear()
Remove all non-zero columns.
int ColumnIndex(int) const
Get column index of the i-th non-zero column.