MultiLevelStationaryVelocityTransformation.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_MultiLevelStationaryVelocityTransformation_H
21 #define MIRTK_MultiLevelStationaryVelocityTransformation_H
22 
23 #include "mirtk/MultiLevelTransformation.h"
24 #include "mirtk/BSplineFreeFormTransformationSV.h"
25 
26 #include "mirtk/Array.h"
27 #include "mirtk/Matrix.h"
28 #include "mirtk/EventDelegate.h"
29 #include "mirtk/VelocityToDisplacementFieldSS.h"
30 #include "mirtk/VoxelFunction.h"
31 #include "mirtk/Profiling.h"
32 
33 
34 namespace mirtk {
35 
36 
37 /**
38  * Multi-level SV FFD where global and local transformations are summed up
39  * in the log space before exponentiation
40  *
41  * T_msvffd(x) = exp(log(T_global(x)) + sum_i log(T_local^i(x)))
42  */
44 {
45  mirtkTransformationMacro(MultiLevelStationaryVelocityTransformation);
46 
47 protected:
48 
49  /// Logarithm of global transformation matrix
51 
52  /// Observes changes of global transformation matrix
54 
55  /// Update logarithm of global transformation matrix
56  void UpdateLogMatrix();
57 
58 public:
59 
60  /// Get n-th local SV FFD
62 
63  /// Get n-th local SV FFD
64  const BSplineFreeFormTransformationSV *SVFFD(int n) const;
65 
66  /// Get active SV FFD whose parameters are being optimized
68 
69  /// Get active SV FFD whose parameters are being optimized
71 
72  // ---------------------------------------------------------------------------
73  // Construction/Destruction
74 
75  /// Default constructor
77 
78  /// Construct multi-level transformation given a rigid transformation
80 
81  /// Construct multi-level transformation given an affine transformation
83 
84  /// Copy constructor
86 
87  /// Destructor
89 
90  // ---------------------------------------------------------------------------
91  // Transformation parameters (DoFs)
92 
93  /// Get norm of the gradient vector
94  virtual double DOFGradientNorm(const double *) const;
95 
96  /// Get number of transformation parameters
97  virtual int NumberOfDOFs() const;
98 
99  /// Put value of transformation parameter
100  virtual void Put(int, double);
101 
102  /// Put values of transformation parameters
103  virtual void Put(const DOFValue *);
104 
105  /// Add change to transformation parameters
106  virtual void Add(const DOFValue *);
107 
108  /// Update transformation parameters given parametric gradient
109  virtual double Update(const DOFValue *);
110 
111  /// Get value of transformation parameter
112  virtual double Get(int) const;
113 
114  /// Get values of transformation parameters
115  virtual void Get(DOFValue *) const;
116 
117  /// Put status of transformation parameter
118  virtual void PutStatus(int, DOFStatus);
119 
120  /// Get status of transformation parameter
121  virtual DOFStatus GetStatus(int) const;
122 
123  // ---------------------------------------------------------------------------
124  // Levels
125 
126  /// Combine local transformations on stack
127  virtual void CombineLocalTransformation();
128 
129  /// Convert the global transformation from a matrix representation to a
130  /// FFD and incorporate it with any existing local transformation
131  virtual void MergeGlobalIntoLocalDisplacement();
132 
133  // ---------------------------------------------------------------------------
134  // Point transformation
135 
140 
141  /// Whether the caching of the transformation displacements is required
142  /// (or preferred) by this transformation. For some transformations such as
143  /// those parameterized by velocities, caching of the displacements for
144  /// each target voxel results in better performance or is needed for example
145  /// for the scaling and squaring method.
146  virtual bool RequiresCachingOfDisplacements() const;
147 
148 protected:
149 
150  /// Upper integration limit used given the temporal origin of both target
151  /// and source images. If both images have the same temporal origin, the value
152  /// of the member variable @c T is returned. Note that @c T may be set to zero
153  /// in order to force no displacement between images located at the same point
154  /// in time to be zero. This is especially useful when animating the
155  /// deformation between two images with successively increasing upper
156  /// integration limit. Otherwise, if the temporal origin of the two images
157  /// differs, the signed difference between these is returned, i.e., t - t0,
158  /// which corresponds to a forward integration of the target point (x, y, z)
159  /// to the time point of the source image.
160  double UpperIntegrationLimit(double t, double t0) const;
161 
162  /// Get number of integration steps for a given temporal integration interval
163  int NumberOfStepsForIntervalLength(double) const;
164 
165  /// Set number of integration steps for a given temporal integration interval
166  void NumberOfStepsForIntervalLength(double, int) const;
167 
168  /// Whether to use scaling and squaring when possible
169  bool UseScalingAndSquaring() const;
170 
171  /// Whether to use fast scaling and squaring when possible
172  bool FastScalingAndSquaring() const;
173 
174  /// Whether scaling and squaring can be used to obtain the displacement field
175  /// for each voxel of the specified vector field
176  template <class VoxelType>
178 
179  /// Maximum norm of scaled velocity for scaling and squaring
180  double MaxScaledVelocity() const;
181 
182  /// Get stationary velocity field as 3D+t vector field
183  template <class ScalarType>
184  void VelocityComponents(int, int, GenericImage<ScalarType> &, bool = false) const;
185 
186  /// Get stationary velocity field
187  template <class VoxelType>
188  void Velocity(int, int, GenericImage<VoxelType> &, bool = false) const;
189 
190  /// Compute group exponential map using the scaling and squaring (SS) method
191  ///
192  /// \attention The scaling and squaring cannot be used to obtain the displacements
193  /// generated by a 3D velocity field on a 2D slice only. It always
194  /// must be applied to the entire domain of the velocity field.
195  template <class VoxelType>
196  void ScalingAndSquaring(int, int, GenericImage<VoxelType> &, double,
197  const WorldCoordsImage * = NULL) const;
198 
199  /// Transform point using the forward Euler integration method
200  void RKE1(int, int, double &x, double &y, double &z, double t) const;
201 
202 public:
203 
204 
205  /// Transforms a single point
206  virtual void Transform(int, int, double &, double &, double &, double = 0, double = NaN) const;
207 
208  /// Transforms a single point using the inverse of the transformation
209  virtual bool Inverse(int, int, double &, double &, double &, double = 0, double = NaN) const;
210 
211  /// Calculates the displacement vectors for a whole image domain
212  ///
213  /// \attention The displacements are computed at the positions after applying the
214  /// current displacements at each voxel. These displacements are then
215  /// added to the current displacements. Therefore, set the input
216  /// displacements to zero if only interested in the displacements of
217  /// this transformation at the voxel positions.
218  virtual void Displacement(int, int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
219 
220  /// Calculates the displacement vectors for a whole image domain
221  ///
222  /// \attention The displacements are computed at the positions after applying the
223  /// current displacements at each voxel. These displacements are then
224  /// added to the current displacements. Therefore, set the input
225  /// displacements to zero if only interested in the displacements of
226  /// this transformation at the voxel positions.
227  virtual void Displacement(int, int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
228 
229  /// Calculates the inverse displacement vectors for a whole image domain
230  ///
231  /// \attention The displacements are computed at the positions after applying the
232  /// current displacements at each voxel. These displacements are then
233  /// added to the current displacements. Therefore, set the input
234  /// displacements to zero if only interested in the displacements of
235  /// this transformation at the voxel positions.
236  ///
237  /// \returns Always zero.
238  virtual int InverseDisplacement(int, int, GenericImage<double> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
239 
240  /// Calculates the inverse displacement vectors for a whole image domain
241  ///
242  /// \attention The displacements are computed at the positions after applying the
243  /// current displacements at each voxel. These displacements are then
244  /// added to the current displacements. Therefore, set the input
245  /// displacements to zero if only interested in the displacements of
246  /// this transformation at the voxel positions.
247  ///
248  /// \returns Always zero.
249  virtual int InverseDisplacement(int, int, GenericImage<float> &, double, double = NaN, const WorldCoordsImage * = NULL) const;
250 
251  // ---------------------------------------------------------------------------
252  // Derivatives
254 
255 protected:
256 
257  /// Applies the chain rule to convert spatial non-parametric gradient
258  /// to a gradient w.r.t the parameters of this transformation.
259  virtual void ParametricGradient(const GenericImage<double> *, double *,
260  const WorldCoordsImage *,
261  const WorldCoordsImage *,
262  double, double, double) const;
263 
264 public:
265 
266  /// Applies the chain rule to convert spatial non-parametric gradient
267  /// to a gradient w.r.t the parameters of this transformation.
268  virtual void ParametricGradient(const GenericImage<double> *, double *,
269  const WorldCoordsImage *,
270  const WorldCoordsImage *,
271  double = NaN, double = 1) const;
272 
273  // ---------------------------------------------------------------------------
274  // I/O
275 
276  /// Prints the parameters of the transformation
277  virtual void Print(ostream &, Indent = 0) const;
278 
279  // ---------------------------------------------------------------------------
280  // Others
281 
282  /// Invert transformation
283  virtual void Invert();
284 
286 };
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 // Auxiliary voxel functions for subclasses
290 ////////////////////////////////////////////////////////////////////////////////
291 
292 // -----------------------------------------------------------------------------
293 /// Add parameters of B-spline SV FFD
295 {
296 public:
297 
299  BaseImage *output)
300  :
301  _Input(input), _Output(output)
302  {}
303 
304 // template <class T>
305 // void Add(Vector2D<T> *v, double vx, double vy, double)
306 // {
307 // v->_x += vx, v->_y += vy;
308 // }
309 
310  template <class T>
311  void Add(Vector3D<T> *v, double vx, double vy, double vz)
312  {
313  v->_x += vx, v->_y += vy, v->_z += vz;
314  }
315 
316  template <class VectorType>
317  void operator()(int i, int j, int k, int, VectorType *v)
318  {
319  double vx, vy, vz;
320  _Input->Get(i, j, k, vx, vy, vz);
321  Add(v, vx, vy, vz);
322  }
323 
324 protected:
325  const BSplineFreeFormTransformationSV *_Input; ///< Input transformation
326  BaseImage *_Output; ///< Output image
327 };
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 // Inline definitions
331 ////////////////////////////////////////////////////////////////////////////////
332 
333 // =============================================================================
334 // Levels
335 // =============================================================================
336 
337 // -----------------------------------------------------------------------------
340 {
341  if (n < 0) n += _NumberOfLevels;
342  return reinterpret_cast<BSplineFreeFormTransformationSV *>(_LocalTransformation[n]);
343 }
344 
345 // -----------------------------------------------------------------------------
346 inline const BSplineFreeFormTransformationSV *
348 {
349  if (n < 0) n += _NumberOfLevels;
350  return reinterpret_cast<BSplineFreeFormTransformationSV *>(_LocalTransformation[n]);
351 }
352 
353 // -----------------------------------------------------------------------------
356 {
357  for (int l = _NumberOfLevels - 1; l >= 0; --l) {
358  if (LocalTransformationIsActive(l)) return SVFFD(l);
359  }
360  return _NumberOfLevels > 0 ? SVFFD(_NumberOfLevels - 1) : NULL;
361 }
362 
363 // -----------------------------------------------------------------------------
364 inline const BSplineFreeFormTransformationSV *
366 {
367  for (int l = _NumberOfLevels - 1; l >= 0; --l) {
368  if (LocalTransformationIsActive(l)) return SVFFD(l);
369  }
370  return _NumberOfLevels > 0 ? SVFFD(_NumberOfLevels - 1) : NULL;
371 }
372 
373 // =============================================================================
374 // Point transformation
375 // =============================================================================
376 
377 // -----------------------------------------------------------------------------
379 ::UpperIntegrationLimit(double t, double t0) const
380 {
382  return (svffd ? svffd->UpperIntegrationLimit(t, t0) : (t - t0));
383 }
384 
385 // -----------------------------------------------------------------------------
388 {
390  return (svffd ? svffd->NumberOfStepsForIntervalLength(T) : 32);
391 }
392 
393 // -----------------------------------------------------------------------------
395 ::NumberOfStepsForIntervalLength(double T, int n) const
396 {
398  if (svffd) svffd->NumberOfStepsForIntervalLength(T, n);
399 }
400 
401 // -----------------------------------------------------------------------------
404 {
406  return (svffd ? svffd->IntegrationMethod() == FFDIM_SS ||
407  svffd->IntegrationMethod() == FFDIM_FastSS
408  : false);
409 }
410 
411 // -----------------------------------------------------------------------------
414 {
416  return (svffd ? svffd->IntegrationMethod() == FFDIM_FastSS : false);
417 }
418 
419 // -----------------------------------------------------------------------------
420 template <class VoxelType>
423 {
425  return (svffd || (svffd->Z() <= 1 && d.Z() <= 1) ||
426  (svffd->Z() > 1 && d.Z() > 1));
427 }
428 
429 // -----------------------------------------------------------------------------
432 {
434  return (svffd ? svffd->MaxScaledVelocity() : .0);
435 }
436 
437 // -----------------------------------------------------------------------------
440 {
441  return this->UseScalingAndSquaring();
442 }
443 
444 // -----------------------------------------------------------------------------
445 template <class VectorType>
447 ::Velocity(int m, int n, GenericImage<VectorType> &v, bool coeff) const
448 {
449  MIRTK_START_TIMING();
450  if (n < 0 || n > _NumberOfLevels) n = _NumberOfLevels;
451  const int l1 = (m < 0 ? 0 : m);
452  const ImageAttributes &grid = v.Attributes();
453  // Determine local SV FFDs whose coefficients can be added without prior deconvolution
454  Array<bool> add_coeff(n, false);
455  bool convert_to_coeff = false;
456  if (coeff) {
457  for (int l = l1; l < n; ++l) {
458  add_coeff[l] = grid.EqualInSpace(SVFFD(l)->Attributes());
459  }
460  }
461  // Add global velocities
462  if (m < 0 && !_LogA.IsIdentity()) {
463  ParallelForEachVoxel(EvaluateGlobalSVFFD(_LogA, &v), grid, v);
464  convert_to_coeff = coeff;
465  } else {
466  v = .0;
467  }
468  // Add local velocities (which require deconvolution)
469  for (int l = l1; l < n; ++l) {
470  if (!add_coeff[l]) {
471  ParallelForEachVoxel(AddBSplineSVFFD(SVFFD(l), &v), grid, v);
472  convert_to_coeff = coeff;
473  }
474  }
475  // Convert to cubic B-spline coefficients if needed and requested
476  if (convert_to_coeff) ConvertToCubicBSplineCoefficients(v);
477  // Add local velocities (which do not require deconvolution)
478  for (int l = l1; l < n; ++l) {
479  if (add_coeff[l]) {
480  ParallelForEachVoxel(AddDOFsOfBSplineSVFFD(SVFFD(l), &v), grid, v);
481  }
482  }
483  MIRTK_DEBUG_TIMING(3, "MultiLevelStationaryVelocityTransformation::Velocity");
484 }
485 
487 ::Velocity(int, int, GenericImage<float> &, bool) const;
488 
490 ::Velocity(int, int, GenericImage<double> &, bool) const;
491 
492 // -----------------------------------------------------------------------------
493 template <class VoxelType>
496  const WorldCoordsImage * /*unused*/) const
497 {
498  if (n < 0 || n > _NumberOfLevels) n = _NumberOfLevels;
499  if (m < 0 && _GlobalTransformation.IsIdentity()) m = 0;
500  if (m >= 0 && n == 0) return;
503  // Use only vector fields defined at control points with B-spline interpolation.
504  // This results in an approximate solution due to the error at each squaring.
505  if (n > 0 && FastScalingAndSquaring()) {
506  v.Initialize(SVFFD(n-1)->Attributes(), 3);
507  Velocity(m, n, v, true);
508  exp.Interpolation(Interpolation_BSpline);
509  exp.ComputeInterpolationCoefficients(false);
510  // Evaluate velocities at output voxels beforehand and use
511  // linear interpolation of dense vector fields during squaring
512  } else {
513  v.Initialize(d.Attributes(), 3);
514  Velocity(m, n, v, false);
515  exp.Interpolation(Interpolation_Linear);
516  }
517  // Exponentiate velocity field
518  exp.UpperIntegrationLimit(T);
519  exp.NumberOfSteps(NumberOfStepsForIntervalLength(T));
520  exp.MaxScaledVelocity(static_cast<VoxelType>(MaxScaledVelocity()));
521  exp.Upsample(false); // better, but too expensive
522  exp.Input(0, &v); // velocity field to be exponentiated
523  exp.Input(1, &d); // input displacement field (may be zero)
524  exp.Output(&tmp); // result is exp(v) o d
525  exp.Run();
526  d.CopyFrom(tmp);
527  // Update number of integration steps to use
528  //NumberOfStepsForIntervalLength(T, pow(2.0, exp.NumberOfSquaringSteps()));
529 }
530 
531 // -----------------------------------------------------------------------------
533 ::RKE1(int m, int n, double &x, double &y, double &z, double T) const
534 {
535  if (n < 0 || n > _NumberOfLevels) n = _NumberOfLevels;
536  // According to
537  // Bossa, M., Zacur, E., & Olmos, S. (2008). Algorithms for
538  // computing the group exponential of diffeomorphisms: Performance evaluation.
539  // In 2008 IEEE Computer Society Conference on Computer Vision and Pattern
540  // Recognition Workshops (pp. 1–8). IEEE. doi:10.1109/CVPRW.2008.4563005
541  // it is more accurate to sum the displacements instead of updating the
542  // transformed point directly because the components of the sum have similar
543  // order of magnitude. This promises a lower numerical error. Therefore,
544  // we sum the displacements dx, dy, dz and add them to the initial point
545  // at each iteration in order to evaluate the next velocity.
546  const int N = NumberOfStepsForIntervalLength(T);
547  if (N > 0) {
548  const int l1 = (m < 0 ? 0 : m);
549  const double dt = T / static_cast<double>(N);
550  double xi, yi, zi, vx, vy, vz, dx = .0, dy = .0, dz = .0;
551  for (int i = 0; i < N; ++i) {
552  // Add current displacement to initial point
553  xi = x + dx, yi = y + dy, zi = z + dz;
554  // Add displacement of global step
555  if (m < 0) {
556  dx += (_LogA(0, 0) * xi + _LogA(0, 1) * yi + _LogA(0, 2) * zi + _LogA(0, 3)) * dt;
557  dy += (_LogA(1, 0) * xi + _LogA(1, 1) * yi + _LogA(1, 2) * zi + _LogA(1, 3)) * dt;
558  dz += (_LogA(2, 0) * xi + _LogA(2, 1) * yi + _LogA(2, 2) * zi + _LogA(2, 3)) * dt;
559  }
560  // Add displacements of local steps
561  for (int l = l1; l < n; ++l) {
562  vx = xi, vy = yi, vz = zi;
563  SVFFD(l)->WorldToLattice(vx, vy, vz);
564  SVFFD(l)->Evaluate (vx, vy, vz);
565  dx += vx * dt;
566  dy += vy * dt;
567  dz += vz * dt;
568  }
569  }
570  x += dx, y += dy, z += dz;
571  }
572 }
573 
574 // -----------------------------------------------------------------------------
575 inline void MultiLevelStationaryVelocityTransformation::Transform(int m, int n, double &x, double &y, double &z, double t, double t0) const
576 {
577  RKE1(m, n, x, y, z, + UpperIntegrationLimit(t, t0));
578 }
579 
580 // -----------------------------------------------------------------------------
581 inline bool MultiLevelStationaryVelocityTransformation::Inverse(int m, int n, double &x, double &y, double &z, double t, double t0) const
582 {
583  RKE1(m, n, x, y, z, - UpperIntegrationLimit(t, t0));
584  return true;
585 }
586 
587 // -----------------------------------------------------------------------------
589 ::Displacement(int m, int n, GenericImage<double> &d, double t, double t0, const WorldCoordsImage *wc) const
590 {
591  double T;
592  if ((T = + UpperIntegrationLimit(t, t0))) {
593  // Use scaling and squaring method to efficiently compute displacements when possible
595  ScalingAndSquaring(m, n, d, T, wc);
596  // Evaluate transformation at each voxel separately using explicit integration
597  } else {
598  MultiLevelTransformation::Displacement(m, n, d, t, t0, wc);
599  }
600  }
601 }
602 
603 // -----------------------------------------------------------------------------
605 ::Displacement(int m, int n, GenericImage<float> &d, double t, double t0, const WorldCoordsImage *wc) const
606 {
607  double T;
608  if ((T = + UpperIntegrationLimit(t, t0))) {
609  // Use scaling and squaring method to efficiently compute displacements when possible
611  ScalingAndSquaring(m, n, d, T, wc);
612  // Evaluate transformation at each voxel separately using explicit integration
613  } else {
614  MultiLevelTransformation::Displacement(m, n, d, t, t0, wc);
615  }
616  }
617 }
618 
619 // -----------------------------------------------------------------------------
621 ::InverseDisplacement(int m, int n, GenericImage<double> &d, double t, double t0, const WorldCoordsImage *wc) const
622 {
623  double T;
624  if ((T = - UpperIntegrationLimit(t, t0))) {
625  // Use scaling and squaring method to efficiently compute displacements when possible
627  ScalingAndSquaring(m, n, d, T, wc);
628  // Evaluate transformation at each voxel separately using explicit integration
629  } else {
631  }
632  }
633  return 0;
634 }
635 
636 // -----------------------------------------------------------------------------
638 ::InverseDisplacement(int m, int n, GenericImage<float> &d, double t, double t0, const WorldCoordsImage *wc) const
639 {
640  double T;
641  if ((T = - UpperIntegrationLimit(t, t0))) {
642  // Use scaling and squaring method to efficiently compute displacements when possible
644  ScalingAndSquaring(m, n, d, T, wc);
645  // Evaluate transformation at each voxel separately using explicit integration
646  } else {
648  }
649  }
650  return 0;
651 }
652 
653 
654 } // namespace mirtk
655 
656 #endif // MIRTK_MultiLevelStationaryVelocityTransformation_H
void Velocity(int, int, GenericImage< VoxelType > &, bool=false) const
Get stationary velocity field.
MultiLevelStationaryVelocityTransformation()
Default constructor.
bool CanUseScalingAndSquaring(const GenericImage< VoxelType > &) const
virtual double Update(const DOFValue *)
Update transformation parameters given parametric gradient.
virtual void Displacement(int, int, double &, double &, double &, double=0, double=NaN) const
Calculates the displacement of a single point.
bool FastScalingAndSquaring() const
Whether to use fast scaling and squaring when possible.
virtual double Get(int) const
Get value of transformation parameter.
const ImageAttributes & Attributes() const
Gets the image attributes.
Definition: BaseImage.h:856
virtual void CombineLocalTransformation()
Combine local transformations on stack.
double DOFValue
Type of transformation parameter value.
virtual bool IsIdentity() const
Checks whether transformation is an identity mapping.
int Z() const
Returns the number of control points in z.
double MaxScaledVelocity() const
Maximum norm of scaled velocity for scaling and squaring.
FreeFormTransformation * _LocalTransformation[MAX_TRANS]
Local transformations.
void VelocityComponents(int, int, GenericImage< ScalarType > &, bool=false) const
Get stationary velocity field as 3D+t vector field.
void UpdateLogMatrix()
Update logarithm of global transformation matrix.
void CopyFrom(const VoxelType *)
Copy image data from 1D array.
virtual bool InverseDisplacement(int, int, double &, double &, double &, double=0, double=NaN) const
Calculates the displacement of a single point using the inverse of the transformation.
Evaluate global SV FFD at image voxels of vector field.
BSplineFreeFormTransformationSV * ActiveSVFFD()
Get active SV FFD whose parameters are being optimized.
virtual void Put(int, double)
Put value of transformation parameter.
virtual void Invert()
Invert transformation.
mirtkAttributeMacro(Matrix, LogA)
Logarithm of global transformation matrix.
Status
Enumeration of common states for entities such as objective function parameters.
Definition: Status.h:28
Definition: IOConfig.h:41
double UpperIntegrationLimit(double t, double t0) const
virtual void Displacement(int, int, GenericImage< double > &, double, double=NaN, const WorldCoordsImage *=NULL) const
virtual void PutStatus(int, DOFStatus)
Put status of transformation parameter.
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double, double, double) const
virtual bool LocalTransformationIsActive(int) const
Get whether local transformation is active.
int NumberOfStepsForIntervalLength(double) const
Get number of integration steps for a given temporal integration interval.
BSplineFreeFormTransformationSV * SVFFD(int n)
Get n-th local SV FFD.
virtual void Transform(int, int, double &, double &, double &, double=0, double=NaN) const
Transforms a single point.
EventDelegate _GlobalTransformationObserver
Observes changes of global transformation matrix.
bool EqualInSpace(const ImageAttributes &attr) const
Whether spatial attributes are equal.
virtual int NumberOfDOFs() const
Get number of transformation parameters.
T _z
The z component.
Definition: Vector3D.h:60
T _y
The y component.
Definition: Vector3D.h:59
virtual DOFStatus GetStatus(int) const
Get status of transformation parameter.
virtual int InverseDisplacement(int, int, GenericImage< double > &, double, double=NaN, const WorldCoordsImage *=NULL) const
void RKE1(int, int, double &x, double &y, double &z, double t) const
Transform point using the forward Euler integration method.
int _NumberOfLevels
Number of local transformations.
bool UseScalingAndSquaring() const
Whether to use scaling and squaring when possible.
virtual void Add(const DOFValue *)
Add change to transformation parameters.
virtual bool Inverse(int, int, double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the transformation.
virtual void Initialize()
Initialize a previously allocated image.
void ConvertToCubicBSplineCoefficients(GenericImage< TData > &image, int l)
Convert 3D floating point scalar or vector image to cubic spline coefficients.
virtual ~MultiLevelStationaryVelocityTransformation()
Destructor.
virtual double DOFGradientNorm(const double *) const
Get norm of the gradient vector.
AffineTransformation _GlobalTransformation
Global transformation.
T _x
The x component.
Definition: Vector3D.h:58
virtual bool Inverse(int, int, double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the transformation.
virtual void Transform(int, int, double &, double &, double &, double=0, double=NaN) const =0
Transforms a single point.
void ScalingAndSquaring(int, int, GenericImage< VoxelType > &, double, const WorldCoordsImage *=NULL) const
void Evaluate(double &, double &, double &, double) const
Evaluates the FFD at a point in lattice coordinates.
virtual void Run()
Compute output = log(input)
const BSplineFreeFormTransformationSV * _Input
Input transformation.
int NumberOfStepsForIntervalLength(double) const
Get number of integration steps for a given temporal integration interval.
virtual void Print(ostream &, Indent=0) const
Prints the parameters of the transformation.
virtual void Input(int, const ImageType *)
Set n-th input (0: velocity field, 1: input displacement field, optional)
int Z() const
Returns the number of voxels in the z-direction.
Definition: BaseImage.h:886
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
Evaluate and add B-spline SV FFD at image voxels.
virtual void WorldToLattice(double &, double &) const
Transforms world coordinates (in mm) to lattice coordinates.