BSplineFreeFormTransformationTD.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_BSplineFreeFormTransformationTD_H
21 #define MIRTK_BSplineFreeFormTransformationTD_H
22 
23 #include "mirtk/BSplineFreeFormTransformation4D.h"
24 #include "mirtk/FFDIntegrationMethod.h"
25 
26 
27 namespace mirtk {
28 
29 
30 /**
31  * Temporal diffeomorphic free-form transformation.
32  *
33  * This class implements a free-form transformation which is represented
34  * by a time-varying velocity field (3D+t). The 3D displacement field at a
35  * specific time is obtained by integrating the velocity field starting at the
36  * reference time point. The integration steps are adjusted if necessary in
37  * order to ensure that the resulting spatial transformation is diffeomorphic.
38  *
39  * For more details about the implementation see De Craene et al. (2012).
40  * Temporal diffeomorphic free-form deformation: application to motion and
41  * strain estimation from 3D echocardiography.
42  * Medical image analysis, 16(2), 427, 2012. doi:10.1016/j.media.2011.10.006
43  */
44 
46 {
47  mirtkTransformationMacro(BSplineFreeFormTransformationTD);
48 
49  // ---------------------------------------------------------------------------
50  // Attributes
51 
52  /// Numerical integration method
53  mirtkPublicAttributeMacro(FFDIntegrationMethod, IntegrationMethod);
54 
55  /// Minimum length of temporal steps (in ms)
56  mirtkPublicAttributeMacro(double, MinTimeStep);
57 
58  /// Maximum length of temporal steps (in ms)
59  mirtkPublicAttributeMacro(double, MaxTimeStep);
60 
61  /// Local integration error tolerance (in mm)
62  mirtkPublicAttributeMacro(double, Tolerance);
63 
64  // ---------------------------------------------------------------------------
65  // Construction/Destruction
66 
67 public:
68 
69  /// Default constructor
71 
72  /// Construct free-form transformation for given image domain and lattice spacing
74  double = -1, double = -1, double = -1, double = -1);
75 
76  /// Construct free-form transformation for given target image and lattice spacing
78  double, double, double, double);
79 
80  /// Copy constructor
82 
83  /// Destructor
85 
86  // ---------------------------------------------------------------------------
87  // Approximation/Interpolation
88 
90 
91  /// Approximate displacements: This function takes a set of 3D displacement fields
92  /// and corresponding time point and temporal interval. Given these inputs,
93  /// it finds a time-varying velocity field which approximates these displacements.
94  virtual void ApproximateDOFs(const GenericImage<double> * const *,
95  const double *, const double *, int,
96  bool = false, int = 3, int = 8);
97 
98  /// Approximates displacements: This function takes a set of points and a set
99  /// of displacements and finds a !new! FFD which approximates these displacements.
100  virtual void ApproximateDOFs(const double *, const double *, const double *, const double *,
101  const double *, const double *, const double *, int);
102 
103  /// Finds gradient of approximation error: This function takes a set of points
104  /// and a set of errors. It finds a gradient w.r.t. the transformation parameters
105  /// which minimizes the L2 norm of the approximation error and adds it to the
106  /// input gradient with the given weight.
107  virtual void ApproximateDOFsGradient(const double *, const double *, const double *, const double *,
108  const double *, const double *, const double *, int,
109  double *, double = 1.0) const;
110 
111  /// Approximate displacements: This function takes a set of 3D displacement fields
112  /// and corresponding time point and temporal interval. Given these inputs,
113  /// it finds a time-varying velocity field which approximates these displacements.
114  /// The displacements are replaced by the residual displacements of the newly
115  /// approximated transformation. Returns the approximation error of the resulting FFD.
116  virtual double ApproximateAsNew(GenericImage<double> **,
117  const double *, const double *, int,
118  bool = false, int = 3, int = 8);
119 
120  /// Interpolates displacements: This function takes a set of displacements defined at
121  /// the control points and finds a time-varying velocity field such that the
122  /// resulting transformation interpolates these displacements.
123  virtual void Interpolate(const double *, const double *, const double *);
124 
125  // ---------------------------------------------------------------------------
126  // Parameters (non-DoFs)
127 
128  /// Set named (non-DoF) parameter from value as string
129  virtual bool Set(const char *, const char *);
130 
131  /// Get (non-DoF) parameters as key/value as string map
132  virtual ParameterList Parameter() const;
133 
134  // ---------------------------------------------------------------------------
135  // Point transformation
137 
138  /// Transforms a single point
139  virtual void LocalTransform(double &, double &, double &, double, double) const;
140 
141  /// Transforms a single point using the inverse transformation
142  virtual bool LocalInverse(double &, double &, double &, double, double) const;
143 
144  // ---------------------------------------------------------------------------
145  // Derivatives
148 
149  /// Calculates the Jacobian of the (local) transformation w.r.t world coordinates
150  /// and transforms the given point at the same time
151  virtual void TransformAndJacobian(Matrix &, double &, double &, double &, double, double) const;
152 
153  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
154  /// of the specified control point and transforms the given point at the same time
155  virtual void TransformAndJacobianDOFs(Matrix &, int, int, int, int, double &, double &, double &, double, double) const;
156 
157  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
158  /// of the specified control point and transforms the given point at the same time
159  virtual void TransformAndJacobianDOFs(Matrix &, int, double &, double &, double &, double, double) const;
160 
161  /// Calculates the Jacobian of the transformation w.r.t all transformation parameters
162  /// and transforms the given point at the same time
163  virtual void TransformAndJacobianDOFs(TransformationJacobian &, double &, double &, double &, double, double) const;
164 
165  /// Calculates the Jacobian of the local transformation w.r.t world coordinates
166  virtual void LocalJacobian(Matrix &, double, double, double, double, double) const;
167 
168  /// Calculates the Hessian for each component of the local transformation w.r.t world coordinates
169  virtual void LocalHessian(Matrix [3], double, double, double, double, double) const;
170 
171  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
172  virtual void JacobianDOFs(Matrix &, int, int, int, int, double, double, double, double, double) const;
173 
174  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
175  virtual void JacobianDOFs(double [3], int, int, int, int, double, double, double, double, double) const;
176 
177  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
178  virtual void JacobianDOFs(TransformationJacobian &, double, double, double, double, double) const;
179 
180  /// Applies the chain rule to convert spatial non-parametric gradient
181  /// to a gradient w.r.t the parameters of this transformation
182  virtual void ParametricGradient(const GenericImage<double> *, double *,
183  const WorldCoordsImage *,
184  const WorldCoordsImage *,
185  double = 1, double = 1) const;
186 
187  /// Applies the chain rule to convert point-wise non-parametric gradient
188  /// to a gradient w.r.t the parameters of this transformation.
189  virtual void ParametricGradient(const PointSet &, const Vector3D<double> *,
190  double *, double = 0, double = -1, double = 1) const;
191 
192  // ---------------------------------------------------------------------------
193  // I/O
194 
195  // Do not hide methods of base class
197 
198  /// Prints the parameters of the transformation
199  virtual void Print(ostream &, Indent = 0) const;
200 
201  /// Whether this transformation can read a file of specified type (i.e. format)
202  virtual bool CanRead(TransformationType) const;
203 
204 protected:
205 
206  /// Reads transformation parameters from a file stream
208 
209  /// Writes transformation parameters to a file stream
210  virtual Cofstream &WriteDOFs(Cofstream &) const;
211 
212 public:
213 
214  // ---------------------------------------------------------------------------
215  // Others
216 
217  /// Invert the transformation
218  virtual void Invert();
219 
220 };
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 // Inline definitions
224 ////////////////////////////////////////////////////////////////////////////////
225 
226 // =============================================================================
227 // Point transformation
228 // =============================================================================
229 
230 // -----------------------------------------------------------------------------
232 ::LocalInverse(double &x, double &y, double &z, double t, double t0) const
233 {
234  this->LocalTransform(x, y, z, t, t0);
235  return true;
236 }
237 
238 // =============================================================================
239 // Derivatives
240 // =============================================================================
241 
242 // -----------------------------------------------------------------------------
244 ::LocalJacobian(Matrix &jac, double x, double y, double z, double t, double t0) const
245 {
246  this->TransformAndJacobian(jac, x, y, z, t, t0);
247 }
248 
249 // -----------------------------------------------------------------------------
251 ::LocalHessian(Matrix [3], double, double, double, double, double) const
252 {
253  cerr << this->NameOfClass() << "::LocalHessian: Not implemented" << endl;
254  exit(1);
255 }
256 
257 // -----------------------------------------------------------------------------
259 ::JacobianDOFs(Matrix &jac, int i, int j, int k, int l,
260  double x, double y, double z, double t, double t0) const
261 {
262  this->TransformAndJacobianDOFs(jac, i, j, k, l, x, y, z, t, t0);
263 }
264 
265 // -----------------------------------------------------------------------------
267 ::JacobianDOFs(TransformationJacobian &jac, double x, double y, double z, double t, double t0) const
268 {
269  jac.Clear();
270  this->TransformAndJacobianDOFs(jac, x, y, z, t, t0);
271 }
272 
273 // -----------------------------------------------------------------------------
275 ::JacobianDOFs(double [3], int, int, int, int, double, double, double, double, double) const
276 {
277  cerr << this->NameOfClass() << "::JacobianDOFs: Jacobian is full symmetric 3x3 matrix, not only a diagonal matrix" << endl;
278  exit(1);
279 }
280 
281 // -----------------------------------------------------------------------------
284  const GenericImage<double> *i2w, const WorldCoordsImage *wc,
285  double t0, double w) const
286 {
287  // Use general implementation provided by FFD base class, not the one
288  // of FreeFormTransformation4D which is only valid for FFDs that are
289  // parameterized by displacements instead of velocities.
290  FreeFormTransformation::ParametricGradient(in, out, i2w, wc, t0, w);
291 }
292 
293 // -----------------------------------------------------------------------------
294 /*
295 void BSplineFreeFormTransformationTD
296 ::ParametricGradient(const GenericImage<double> **in, int n, double *out,
297  const GenericImage<double> *i2w, const WorldCoordsImage *wc,
298  double *t0, double w) const
299 {
300  // TODO: Can be more efficient by re-using already computed trajectories
301  // especially when different source images are frames of a temporal
302  // sequence. See ImageTDFFDRegistration.
303 }
304 */
305 
306 
307 } // namespace mirtk
308 
309 #endif // MIRTK_BSplineFreeFormTransformationTD_H
virtual ParameterList Parameter() const
Get (non-DoF) parameters as key/value as string map.
virtual void LocalHessian(Matrix [3], double, double, double, double, double) const
Calculates the Hessian for each component of the local transformation w.r.t world coordinates...
virtual bool CanRead(TransformationType) const
Whether this transformation can read a file of specified type (i.e. format)
virtual bool Set(const char *, const char *)
Set named (non-DoF) parameter from value as string.
virtual void Print(ostream &, Indent=0) const
Prints the parameters of the transformation.
virtual void Print(ostream &, Indent=0) const
Prints the parameters of the transformation.
virtual double ApproximateAsNew(GenericImage< double > **, const double *, const double *, int, bool=false, int=3, int=8)
virtual void LocalJacobian(Matrix &, double, double, double, double, double) const
Calculates the Jacobian of the local transformation w.r.t world coordinates.
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
virtual void Invert()
Invert the transformation.
virtual ~BSplineFreeFormTransformationTD()
Destructor.
virtual double ApproximateAsNew(const Transformation *, int=1, double=.0)
Approximate another transformation and return approximation error.
Definition: IOConfig.h:41
virtual void TransformAndJacobianDOFs(Matrix &, int, int, int, int, double &, double &, double &, double, double) const
virtual void Displacement(double &, double &, double &, double=0, double=NaN) const
Calculates the displacement of a single point.
virtual void JacobianDOFs(Matrix &, int, int, int, int, double, double, double, double, double=NaN) const
Calculates the Jacobian of the transformation w.r.t the transformation parameters.
virtual void JacobianDOFs(Matrix &, int, int, int, int, double, double, double, double, double) const
Calculates the Jacobian of the transformation w.r.t the transformation parameters.
virtual void ApproximateDOFsGradient(const double *, const double *, const double *, const double *, const double *, const double *, const double *, int, double *, double=1.0) const
FFDIntegrationMethod
Enumeration of implemented numerical integration methods.
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
virtual const char * NameOfClass() const =0
Get name of class, which this object is an instance of.
virtual void ApproximateDOFs(const GenericImage< double > *const *, const double *, const double *, int, bool=false, int=3, int=8)
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1.0) const
virtual void TransformAndJacobian(Matrix &, double &, double &, double &, double, double) const
virtual bool LocalInverse(double &, double &, double &, double, double) const
Transforms a single point using the inverse transformation.
virtual Cofstream & WriteDOFs(Cofstream &) const
Writes transformation parameters to a file stream.
void Clear()
Remove all non-zero columns.
BSplineFreeFormTransformationTD()
Default constructor.
virtual void Interpolate(const double *, const double *, const double *)
virtual Cifstream & ReadDOFs(Cifstream &, TransformationType)
Reads transformation parameters from a file stream.
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=1, double=1) const
virtual void LocalTransform(double &, double &, double &, double, double) const
Transforms a single point.