FreeFormTransformation4D.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2015 Imperial College London
5  * Copyright 2008-2013 Daniel Rueckert, Julia Schnabel
6  * Copyright 2013-2015 Andreas Schuh
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef MIRTK_FreeFormTransformation4D_H
22 #define MIRTK_FreeFormTransformation4D_H
23 
24 #include "mirtk/FreeFormTransformation.h"
25 
26 #include <cstdlib>
27 #include <iostream>
28 
29 
30 namespace mirtk {
31 
32 
33 /**
34  * Base class for 4D free-form transformations.
35  */
37 {
38  mirtkAbstractTransformationMacro(FreeFormTransformation4D);
39 
40  // ---------------------------------------------------------------------------
41  // Construction/Destruction
42 
43 protected:
44 
45  /// Default constructor
47 
48  /// Copy Constructor
50 
51 public:
52 
53  /// Destructor
54  virtual ~FreeFormTransformation4D();
55 
56  // Import other Initialize overloades from base class
58 
59  /// Initialize free-form transformation
60  virtual void Initialize(const ImageAttributes &);
61 
62  // ---------------------------------------------------------------------------
63  // Derivatives
66 
67  /// Calculates the Jacobian of the transformation w.r.t a control point
68  virtual void JacobianDOFs(Matrix &, int, int, int, int,
69  double, double, double, double, double = NaN) const;
70 
71  /// Calculates the Jacobian of the transformation w.r.t a control point
72  virtual void JacobianDOFs(Matrix &, int, double, double, double, double, double = NaN) const;
73 
74  /// Calculates the Jacobian of the transformation w.r.t a control point
75  virtual void JacobianDOFs(double [3], int, int, int, int, double, double, double, double, double = NaN) const;
76 
77  /// Calculates the Jacobian of the transformation w.r.t a transformation parameter
78  virtual void JacobianDOFs(double [3], int, double, double, double, double, double = NaN) const;
79 
80  /// Applies the chain rule to convert spatial non-parametric gradient
81  /// to a gradient w.r.t the parameters of this transformation
82  ///
83  /// The temporal coordinate t used for the computation of the Jacobian of the transformation
84  /// w.r.t the transformation parameters for all spatial (x, y, z) voxel coordinates in world
85  /// units, is assumed to correspond to the temporal origin of the given gradient image.
86  /// For 4D transformations parameterized by velocities, a second time for the upper integration
87  /// bound can be provided as last argument to this method. This last argument is ignored by
88  /// transformations parameterized by displacements.
89  virtual void ParametricGradient(const GenericImage<double> *, double *,
90  const WorldCoordsImage *,
91  const WorldCoordsImage *,
92  double = NaN, double = 1) const;
93 
94  // ---------------------------------------------------------------------------
95  // I/O
96 
97 protected:
98 
99  /// Reads transformation parameters from a file stream
101 
102  /// Writes transformation parameters to a file stream
103  virtual Cofstream &WriteDOFs(Cofstream &) const;
104 
105 public:
106 
107  // ---------------------------------------------------------------------------
108  // Deprecated
109 
110  /// \deprecated Use overloaded PutStatus method instead.
111  void PutStatusCP(int, int, int, int, DOFStatus, DOFStatus, DOFStatus);
112 
113  /// \deprecated Use overloaded GetStatus method instead.
114  void GetStatusCP(int, int, int, int, DOFStatus &, DOFStatus &, DOFStatus &) const;
115 
116  /// \deprecated Use overloaded BoundingBox method instead.
117  /// Note, however, that the new function swaps coordinates to
118  /// enforce p1[i] <= p2[i]. This is not done by this function.
119  void BoundingBoxCP(int, Point &, Point &, double = 1) const;
120 
121  /// \deprecated Use overloaded BoundingBox method instead.
122  void BoundingBoxImage(const GreyImage *, int, int &, int &, int &,
123  int &, int &, int &, double = 1) const;
124 };
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 // Inline definitions
128 ////////////////////////////////////////////////////////////////////////////////
129 
130 // =============================================================================
131 // Derivatives
132 // =============================================================================
133 
134 // -----------------------------------------------------------------------------
135 inline void FreeFormTransformation4D
136 ::JacobianDOFs(Matrix &, int, int, int, int, double, double, double, double, double) const
137 {
138  cerr << this->NameOfClass() << "::JacobianDOFs: Not implemented" << endl;
139  exit(1);
140 }
141 
142 // -----------------------------------------------------------------------------
143 inline void FreeFormTransformation4D
144 ::JacobianDOFs(Matrix &jac, int cp, double x, double y, double z, double t, double t0) const
145 {
146  int ci, cj, ck, cl;
147  this->IndexToLattice(cp, ci, cj, ck, cl);
148  return this->JacobianDOFs(jac, ci, cj, ck, cl, x, y, z, t, t0);
149 }
150 
151 // -----------------------------------------------------------------------------
152 inline void FreeFormTransformation4D
153 ::JacobianDOFs(double jac[3], int ci, int cj, int ck, int cl, double x, double y, double z, double t, double t0) const
154 {
155  Matrix tmp(3, 3);
156  this->JacobianDOFs(tmp, ci, cj, ck, cl, x, y, z, t, t0);
157  if (tmp(0, 0) != .0 || tmp(0, 2) != .0 || tmp(1, 0) != .0 || tmp(1, 2) != .0 || tmp(2, 0) != .0 || tmp(2, 1) != .0) {
158  cerr << "FreeFormTransformation4D::JacobianDOFs: Jacobian is full 3x3 matrix" << endl;
159  exit(1);
160  }
161  jac[0] = tmp(0, 0);
162  jac[1] = tmp(1, 1);
163  jac[2] = tmp(2, 2);
164 }
165 
166 // -----------------------------------------------------------------------------
167 inline void FreeFormTransformation4D::JacobianDOFs(double jac[3], int dof, double x, double y, double z, double t, double t0) const
168 {
169  int ci, cj, ck, cl;
170  this->IndexToLattice(dof / 3, ci, cj, ck, cl);
171  this->JacobianDOFs(jac, ci, cj, ck, cl, x, y, z, t, t0);
172  const int c = dof % 3;
173  for (int i = 0; i < 3; ++i) {
174  if (i != c) jac[i] = .0;
175  }
176 }
177 
178 // =============================================================================
179 // Deprecated
180 // =============================================================================
181 
182 // -----------------------------------------------------------------------------
183 inline void FreeFormTransformation4D::PutStatusCP(int i, int j, int k, int l,
184  DOFStatus sx, DOFStatus sy, DOFStatus sz)
185 {
186  PutStatus(i, j, k, l, sx, sy, sz);
187 }
188 
189 // -----------------------------------------------------------------------------
190 inline void FreeFormTransformation4D::GetStatusCP(int i, int j, int k, int l,
191  DOFStatus &sx, DOFStatus &sy, DOFStatus &sz) const
192 {
193  GetStatus(i, j, k, l, sx, sy, sz);
194 }
195 
196 // -----------------------------------------------------------------------------
198  Point &p2, double fraction) const
199 {
200  int i, j, k;
201  IndexToLattice(cp, i, j, k);
202  p1 = Point(i - 2 * fraction, j - 2 * fraction, k - 2 * fraction);
203  p2 = Point(i + 2 * fraction, j + 2 * fraction, k + 2 * fraction);
204  this->LatticeToWorld(p1);
205  this->LatticeToWorld(p2);
206 }
207 
208 // -----------------------------------------------------------------------------
209 inline void
211 ::BoundingBoxImage(const GreyImage *image, int cp, int &i1, int &j1, int &k1,
212  int &i2, int &j2, int &k2, double fraction) const
213 {
214  // Calculate bounding box in world coordinates
215  Point p1, p2;
216  this->BoundingBoxCP(cp, p1, p2, fraction);
217 
218  // Transform world coordinates to image coordinates
219  image->WorldToImage(p1._x, p1._y, p1._z);
220  image->WorldToImage(p2._x, p2._y, p2._z);
221 
222  // Calculate bounding box in image coordinates
223  i1 = (p1._x < 0) ? 0 : int(p1._x)+1;
224  j1 = (p1._y < 0) ? 0 : int(p1._y)+1;
225  k1 = (p1._z < 0) ? 0 : int(p1._z)+1;
226  i2 = (int(p2._x) >= image->GetX()) ? image->GetX()-1 : int(p2._x);
227  j2 = (int(p2._y) >= image->GetY()) ? image->GetY()-1 : int(p2._y);
228  k2 = (int(p2._z) >= image->GetZ()) ? image->GetZ()-1 : int(p2._z);
229 }
230 
231 
232 } // namespace mirtk
233 
234 #endif // MIRTK_FreeFormTransformation4D_H
FreeFormTransformation4D(CPInterpolator &)
Default constructor.
virtual void JacobianDOFs(Matrix &, int, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t the transformation parameters of a control point...
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
void BoundingBoxCP(int, Point &, Point &, double=1) const
void WorldToImage(double &, double &) const
World to image coordinate conversion with two doubles.
Definition: BaseImage.h:1212
double _x
x coordinate of Point
Definition: Point.h:46
virtual void Initialize(const ImageAttributes &)
Initialize free-form transformation.
virtual void Initialize(const ImageAttributes &)=0
Initialize free-form transformation.
void PutStatusCP(int, int, int, int, DOFStatus, DOFStatus, DOFStatus)
void GetStatusCP(int, int, int, int, DOFStatus &, DOFStatus &, DOFStatus &) const
Status
Enumeration of common states for entities such as objective function parameters.
Definition: Status.h:28
Definition: IOConfig.h:41
int GetX() const
Returns the number of voxels in the x-direction.
Definition: BaseImage.h:904
int GetY() const
Returns the number of voxels in the y-direction.
Definition: BaseImage.h:910
void PutStatus(int, const CPStatus &)
Puts status of the parameters at a control point.
void BoundingBoxImage(const GreyImage *, int, int &, int &, int &, int &, int &, int &, double=1) const
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
void GetStatus(int, CPStatus &) const
Gets status of the parameters at a control point.
virtual const char * NameOfClass() const =0
Get name of class, which this object is an instance of.
void IndexToLattice(int, int &, int &) const
Get control point lattice coordinates from index.
virtual void JacobianDOFs(Matrix &, int, int, int, int, double, double, double, double, double=NaN) const
Calculates the Jacobian of the transformation w.r.t a control point.
virtual void LatticeToWorld(double &, double &) const
Transforms lattice coordinates to world coordinates (in mm)
double _z
z coordinate of Point
Definition: Point.h:48
virtual Cofstream & WriteDOFs(Cofstream &) const
Writes transformation parameters to a file stream.
virtual ~FreeFormTransformation4D()
Destructor.
double _y
y coordinate of Point
Definition: Point.h:47
int GetZ() const
Returns the number of voxels in the z-direction.
Definition: BaseImage.h:916
virtual Cifstream & ReadDOFs(Cifstream &, TransformationType)
Reads transformation parameters from a file stream.