BiasField.h
1 /*
2  * Developing brain Region Annotation With Expectation-Maximization (Draw-EM)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Maria Murgasova
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 _MIRTKBIASFIELD_H
21 
22 #define _MIRTKBIASFIELD_H
23 
24 //#include "mirtk/Geometry.h"
25 #include "mirtk/Point.h"
26 #include "mirtk/Matrix.h"
27 
28 #include "mirtk/Transformation.h"
29 
30 #define MIRTKBIASFIELD_MAGIC 815008
31 
32 #define MIRTKBIASFIELD_BSPLINE 1
33 #define MIRTKBIASFIELD_POLYNOMIAL 2
34 
35 namespace mirtk {
36 
37 class BiasField : public Object
38 {
39  mirtkAbstractMacro(BiasField);
40 
41 protected:
42 
43  /// Number of control points in x
44  int _x;
45 
46  /// Number of control points in y
47  int _y;
48 
49  /// Number of control points in z
50  int _z;
51 
52  /// Spacing of control points in x (in mm)
53  double _dx;
54 
55  /// Spacing of control points in y (in mm)
56  double _dy;
57 
58  /// Spacing of control points in z (in mm)
59  double _dz;
60 
61  /// Direction of x-axis
62  double _xaxis[3];
63 
64  /// Direction of y-axis
65  double _yaxis[3];
66 
67  /// Direction of z-axis
68  double _zaxis[3];
69 
70  /// Origin
71  Point _origin;
72 
73  /// Transformation matrix from lattice coordinates to world coordinates
74  Matrix _matL2W;
75 
76  /// Transformation matrix from world coordinates to lattice coordinates
77  Matrix _matW2L;
78 
79  /// Displacement at the control points
80  double ***_data;
81 
82  /// Allocate memory for control points
83  static double ***Allocate (double ***, int, int, int);
84 
85  /// Deallocate memory for control points
86  static double ***Deallocate(double ***, int, int, int);
87 
88  /// Update transformation matrix
89  virtual void UpdateMatrix();
90 
91 public:
92 
93  /** Approximate displacements: This function takes a set of points and a
94  set of displacements and find a FFD which approximates these
95  displacements. After approximatation the displacements replaced by
96  the residual displacement errors at the points */
97  virtual double Approximate(double *, double *, double *, double *, int) = 0;
98 
99  /// Calculate weighted least square fit to data
100  virtual void WeightedLeastSquares(double *x1, double *y1, double *z1, double *bias, double *weights, int no)=0;
101 
102 
103  /** Interpolates displacements: This function takes a set of displacements
104  defined at the control points and finds a FFD which interpolates these
105  displacements.
106  \param bias The bias at each control point. */
107  virtual void Interpolate(double* bias) = 0;
108 
109  /// Subdivide FFD
110  virtual void Subdivide() = 0;
111 
112  /// Returns the of control points in x
113  virtual int GetX() const;
114 
115  /// Returns the of control points in y
116  virtual int GetY() const;
117 
118  /// Returns the of control points in z
119  virtual int GetZ() const;
120 
121  /// Returns the number of parameters of the transformation
122  virtual int NumberOfDOFs() const;
123 
124  /// Get the control point spacing (in mm)
125  virtual void GetSpacing(double &, double &, double &) const;
126 
127  /// Put orientation of free-form deformation
128  virtual void PutOrientation(double *, double *, double *);
129 
130  /// Get orientation of free-form deformation
131  virtual void GetOrientation(double *, double *, double *) const;
132 
133  /// Puts a control point value
134  virtual void Put(int, double);
135 
136  /// Puts a control point value
137  virtual void Put(int, int, int, double);
138 
139  /// Gets a control point value
140  virtual double Get(int) const;
141 
142  /// Gets a control point value
143  virtual double Get(int, int, int) const;
144 
145  /// Transforms world coordinates (in mm) to FFD coordinates
146  virtual void WorldToLattice(double &, double &, double &) const;
147 
148  /// Transforms world coordinates (in mm) to FFD coordinates
149  virtual void WorldToLattice(Point &) const;
150 
151  /// Transforms FFD coordinates to world coordinates (in mm)
152  virtual void LatticeToWorld(double &, double &, double &) const;
153 
154  /// Transforms FFD coordinates to world coordinates (in mm)
155  virtual void LatticeToWorld(Point &) const;
156 
157  /// Transforms index of control points to FFD coordinates
158  virtual void IndexToLattice(int index, int& i, int& j, int& k) const;
159 
160  /// Transforms FFD coordinates to index of control point
161  virtual int LatticeToIndex(int i, int j, int k) const;
162 
163  /// Returns the control point location (in mm)
164  virtual void ControlPointLocation(int, double &, double &, double &) const;
165 
166  /// Returns the control point location (in mm)
167  virtual Point ControlPointLocation(int) const;
168 
169  /// Put the bounding box for FFD (in mm)
170  virtual void PutBoundingBox(Point, Point);
171 
172  /// Put the bounding box for FFD (in mm)
173  virtual void PutBoundingBox(double, double, double,
174  double, double, double);
175 
176  /// Returns the bounding box for FFD (in mm)
177  virtual void BoundingBox(Point &, Point &) const;
178 
179  /// Returns the bounding box for FFD (in mm)
180  virtual void BoundingBox(double &, double &, double &,
181  double &, double &, double &) const;
182 
183  /** Returns the bounding box for a control point (in mm). The last
184  * parameter specifies what fraction of the bounding box to return. The
185  * default is 1 which equals 100% of the bounding box.
186  */
187  virtual void BoundingBox(int, Point &, Point &, double = 1) const;
188 
189  /** Returns the bounding box for a control point (in mm). The last
190  * parameter specifies what fraction of the bounding box to return. The
191  * default is 1 which equals 100% of the bounding box.
192  */
193  virtual void BoundingBox(int, double &, double &, double &,
194  double &, double &, double &, double = 1) const;
195 
196  /** Returns the bounding box for a control point (in pixels). The last
197  * parameter specifies what fraction of the bounding box to return. The
198  * default is 1 which equals 100% of the bounding box.
199  */
200  virtual void BoundingBox(GreyImage *, int, int &, int &, int &,
201  int &, int &, int &, double = 1) const;
202 
203  /// Calculate value of bias field at a point
204  virtual double Bias(double, double, double) = 0;
205 
206  /// Reads a transformation from a file (abstract)
207  virtual void Read (char *) = 0;
208 
209  /// Writes a transformation to a file (abstract)
210  virtual void Write(char *) = 0;
211 
212  /// Prints info (abstract)
213  virtual void Print() = 0;
214 
215 };
216 
217 inline int BiasField::GetX() const
218 {
219  return _x;
220 }
221 
222 inline int BiasField::GetY() const
223 {
224  return _y;
225 }
226 
227 inline int BiasField::GetZ() const
228 {
229  return _z;
230 }
231 
232 inline int BiasField::NumberOfDOFs() const
233 {
234  return _x*_y*_z;
235 }
236 
237 inline double BiasField::Get(int index) const
238 {
239  int i, j, k;
240 
241  if (index >= _x*_y*_z) {
242  std::cerr << "BiasField::Get: No such dof" << std::endl;
243  exit(1);
244  }
245  i = index/(_y*_z);
246  j = index%(_y*_z)/_z;
247  k = index%(_y*_z)%_z;
248  return _data[k][j][i];
249 }
250 
251 inline double BiasField::Get(int i, int j, int k) const
252 {
253  if ((i < 0) || (i >= _x) || (j < 0) || (j >= _y) || (k < 0) || (k >= _z)) {
254  std::cerr << "BiasField::Get: No such dof" << std::endl;
255  exit(1);
256  }
257  return _data[k][j][i];
258 }
259 
260 inline void BiasField::Put(int index, double x)
261 {
262  Point p;
263  int i, j, k;
264 
265  if (index >= _x*_y*_z) {
266  std::cerr << "BiasField::Put: No such dof" << std::endl;
267  exit(1);
268  }
269  i = index/(_y*_z);
270  j = index%(_y*_z)/_z;
271  k = index%(_y*_z)%_z;
272  _data[k][j][i] = x;
273 }
274 
275 inline void BiasField::Put(int i, int j, int k, double x)
276 {
277  if ((i < 0) || (i >= _x) || (j < 0) || (j >= _y) || (k < 0) || (k >= _z)) {
278  std::cerr << "BiasField::Put: No such dof" << std::endl;
279  exit(1);
280  }
281  _data[k][j][i] = x;
282 }
283 
284 inline void BiasField::GetSpacing(double &dx, double &dy, double &dz) const
285 {
286  dx = _dx;
287  dy = _dy;
288  dz = _dz;
289 }
290 
291 inline void BiasField::PutOrientation(double *xaxis, double *yaxis, double *zaxis)
292 {
293  _xaxis[0] = xaxis[0];
294  _xaxis[1] = xaxis[1];
295  _xaxis[2] = xaxis[2];
296  _yaxis[0] = yaxis[0];
297  _yaxis[1] = yaxis[1];
298  _yaxis[2] = yaxis[2];
299  _zaxis[0] = zaxis[0];
300  _zaxis[1] = zaxis[1];
301  _zaxis[2] = zaxis[2];
302 
303  this->UpdateMatrix();
304 }
305 
306 inline void BiasField::GetOrientation(double *xaxis, double *yaxis, double *zaxis) const
307 {
308  xaxis[0] = _xaxis[0];
309  xaxis[1] = _xaxis[1];
310  xaxis[2] = _xaxis[2];
311  yaxis[0] = _yaxis[0];
312  yaxis[1] = _yaxis[1];
313  yaxis[2] = _yaxis[2];
314  zaxis[0] = _zaxis[0];
315  zaxis[1] = _zaxis[1];
316  zaxis[2] = _zaxis[2];
317 }
318 
319 inline void BiasField::PutBoundingBox(double x1, double y1, double z1, double x2, double y2, double z2)
320 {
321  // Initialize control point domain
322  _origin._x = (x2 + x1) / 2.0;
323  _origin._y = (y2 + y1) / 2.0;
324  _origin._z = (z2 + z1) / 2.0;
325 
326  double a = x1 * _xaxis[0] + y1 * _xaxis[1] + z1 * _xaxis[2];
327  double b = x1 * _yaxis[0] + y1 * _yaxis[1] + z1 * _yaxis[2];
328  double c = x1 * _zaxis[0] + y1 * _zaxis[1] + z1 * _zaxis[2];
329  x1 = a;
330  y1 = b;
331  z1 = c;
332  a = x2 * _xaxis[0] + y2 * _xaxis[1] + z2 * _xaxis[2];
333  b = x2 * _yaxis[0] + y2 * _yaxis[1] + z2 * _yaxis[2];
334  c = x2 * _zaxis[0] + y2 * _zaxis[1] + z2 * _zaxis[2];
335  x2 = a;
336  y2 = b;
337  z2 = c;
338 
339  // Initialize control point spacing
340 
341  _x = round((x2-x1)/_dx) +1;
342  _y = round((y2-y1)/_dy) +1;
343  _z = round((z2-z1)/_dz) +1;
344  _dx = (x2 - x1) / (_x - 1);
345  _dy = (y2 - y1) / (_y - 1);
346  if (z2 > z1) {
347  _dz = (z2 - z1) / (_z - 1);
348  } else {
349  _dz = 1;
350  }
351 
352  this->UpdateMatrix();
353 }
354 
355 inline void BiasField::PutBoundingBox(Point p1, Point p2)
356 {
357  this->PutBoundingBox(p1._x, p1._y, p1._z, p2._x, p2._y, p2._z);
358 }
359 
360 inline void BiasField::WorldToLattice(double &x, double &y, double &z) const
361 {
362  double a, b, c;
363 
364  // Pre-multiply point with transformation matrix
365  a = _matW2L(0, 0)*x+_matW2L(0, 1)*y+_matW2L(0, 2)*z+_matW2L(0, 3);
366  b = _matW2L(1, 0)*x+_matW2L(1, 1)*y+_matW2L(1, 2)*z+_matW2L(1, 3);
367  c = _matW2L(2, 0)*x+_matW2L(2, 1)*y+_matW2L(2, 2)*z+_matW2L(2, 3);
368 
369  // Copy result back
370  x = a;
371  y = b;
372  z = c;
373 }
374 
375 inline void BiasField::WorldToLattice(Point &p) const
376 {
377  this->WorldToLattice(p._x, p._y, p._z);
378 }
379 
380 inline void BiasField::LatticeToWorld(double &x, double &y, double &z) const
381 {
382  double a, b, c;
383 
384  // Pre-multiply point with transformation matrix
385  a = _matL2W(0, 0)*x+_matL2W(0, 1)*y+_matL2W(0, 2)*z+_matL2W(0, 3);
386  b = _matL2W(1, 0)*x+_matL2W(1, 1)*y+_matL2W(1, 2)*z+_matL2W(1, 3);
387  c = _matL2W(2, 0)*x+_matL2W(2, 1)*y+_matL2W(2, 2)*z+_matL2W(2, 3);
388 
389  // Copy result back
390  x = a;
391  y = b;
392  z = c;
393 }
394 
395 inline void BiasField::LatticeToWorld(Point &p) const
396 {
397  this->LatticeToWorld(p._x, p._y, p._z);
398 }
399 
400 inline void BiasField::IndexToLattice(int index, int& i, int& j, int& k) const
401 {
402 
403  if (index >= _x*_y*_z) {
404  index -= _x*_y*_z;
405  if (index >= _x*_y*_z) {
406  index -= _x*_y*_z;
407  }
408  }
409  i = index/(_y*_z);
410  j = index%(_y*_z)/_z;
411  k = index%(_y*_z)%_z;
412 }
413 
414 inline int BiasField::LatticeToIndex(int i, int j, int k) const
415 {
416  return i * _y * _z + j * _z + k;
417 }
418 
419 //#include "BSplineBiasField.h"
420 
421 }
422 
423 #endif
int Read(const char *name, UniquePtr< double[]> &data, int *dtype=nullptr, ImageAttributes *attr=nullptr, void *=nullptr, const char *scalars_name=nullptr, bool cell_data=false)
Read data sequence from any supported input file type.
string Get(const ParameterList &params, string name)
Get parameter value from parameters list.
Definition: Object.h:202
void Allocate(Type *&matrix, int n)
Allocate 1D array.
Definition: Allocate.h:62
Definition: IOConfig.h:41
void Deallocate(Type *&p)
Deallocate 1D array.
Definition: Deallocate.h:36
std::ostream & Print(std::ostream &os, T value)
Print single argument to output stream.
Definition: String.h:259