JacobianConstraint.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2017 Imperial College London
5  * Copyright 2013-2017 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_JacobianConstraint_H
21 #define MIRTK_JacobianConstraint_H
22 
23 #include "mirtk/TransformationConstraint.h"
24 
25 #include "mirtk/Matrix.h"
26 #include "mirtk/GenericImage.h"
27 
28 
29 namespace mirtk {
30 
31 
32 class FreeFormTransformation;
33 
34 
35 /**
36  * Base class of soft transformation constraints penalizing the Jacobian determinant
37  *
38  * \note The Jacobian, Penalty, and Derivative functions are public such that
39  * these can be called by a TBB parallel_for/parall_reduce body in a subclass
40  * implementation. These should not be considered as public API and may be
41  * subject to change.
42  */
44 {
45  mirtkAbstractMacro(JacobianConstraint);
46 
47  // ---------------------------------------------------------------------------
48  // Types
49 
50 public:
51 
52  /// Enumeration of target image sub-domains on which to evaluate penalty
54  {
55  SD_Image, ///< Evaluate penalty at image voxels
56  SD_Lattice, ///< Evaluate penalty at control points
57  SD_SubDiv, ///< Evaluate penalty at subdivided control point lattice
58  SD_Shifted ///< Evaluate penalty in-between control points
59  };
60 
61  // ---------------------------------------------------------------------------
62  // Attributes
63 
64  /// Sub-domain on which to evaluate penalty
66 
67  /// Whether to always apply constraint to Jacobian of FFD spline function
68  ///
69  /// This option has no effect when the FFD parameters are displacements.
70  /// In case of a velocity based FFD model, it applies the constraint to
71  /// the velocity field instead of the corresponding displacement field.
72  mirtkReadOnlyAttributeMacro(bool, ConstrainParameterization);
73 
74  /// Whether to evaluate derivatives of smoothness term w.r.t. world coordinates.
75  ///
76  /// When \c false, the smoothness penalty is evaluated w.r.t the local lattice coordinates
77  mirtkPublicAttributeMacro(bool, WithRespectToWorld);
78 
79  /// Whether to use control point spacing when derivatives are computed w.r.t. world coordinates
80  mirtkPublicAttributeMacro(bool, UseLatticeSpacing);
81 
82  /// Whether to apply symmetric penalty in case of SVFFD model (default: true)
83  mirtkPublicAttributeMacro(bool, Symmetric);
84 
85 protected:
86 
87  int _NumJacobian; ///< Number of allocated Jacobian matrices
88  double *_DetJacobian; ///< Determinant of Jacobian at each control point
89  Matrix *_AdjJacobian; ///< Adjugate of Jacobian at each control point
90  Array<Matrix> _MatW2L; ///< World to sub-domain lattice coordinates
91  Array<Matrix> _MatL2W; ///< Sub-domain lattice coordinates to world
92  Array<ImageAttributes> _SubDomains; ///< Discrete sub-domain over which to integrate penalty
93 
94  // ---------------------------------------------------------------------------
95  // Construction/destruction
96 
97  /// Constructor
98  JacobianConstraint(const char *, bool = false);
99 
100 public:
101 
102  /// Destructor
103  virtual ~JacobianConstraint();
104 
105 protected:
106 
107  /// Set parameter value from string
108  virtual bool SetWithoutPrefix(const char *, const char *);
109 
110 public:
111 
112  // Import other overloads
114 
115  /// Get parameter key/value as string map
116  virtual ParameterList Parameter() const;
117 
118  // ---------------------------------------------------------------------------
119  // Evaluation
120 
121  /// Initialize energy term once input and parameters have been set
122  virtual void Initialize();
123 
124  /// Update internal state upon change of input
125  virtual void Update(bool = true);
126 
127  /// Evaluate penalty at control point location given Jacobian determinant value
128  ///
129  /// \param[in] det Jacobian determinant value.
130  virtual double Penalty(double det) const = 0;
131 
132  /// Evaluate derivative of penalty w.r.t. Jacobian determinant value
133  ///
134  /// \param[in] det Jacobian determinant value.
135  virtual double DerivativeWrtJacobianDet(double det) const = 0;
136 
137 protected:
138 
139  /// Compute penalty for current transformation estimate
140  virtual double Evaluate();
141 
142  /// Compute gradient of penalty term w.r.t transformation parameters
143  virtual void EvaluateGradient(double *, double, double);
144 
145  // ---------------------------------------------------------------------------
146  // Debugging
147 
148 public:
149 
150  /// Write Jacobian determinant
151  virtual void WriteDataSets(const char *, const char *, bool = true) const;
152 
153  /// Write gradient of penalty term
154  virtual void WriteGradient(const char *, const char *) const;
155 
156 };
157 
158 ///////////////////////////////////////////////////////////////////////////////
159 // Inline definitions
160 ///////////////////////////////////////////////////////////////////////////////
161 
162 // ----------------------------------------------------------------------------
163 template <>
164 inline string ToString(const JacobianConstraint::SubDomainEnum &value, int w, char c, bool left)
165 {
166  const char *str;
167  switch (value) {
168  case JacobianConstraint::SD_Image: str = "Image"; break;
169  case JacobianConstraint::SD_Lattice: str = "Lattice"; break;
170  case JacobianConstraint::SD_Shifted: str = "Shifted"; break;
171  case JacobianConstraint::SD_SubDiv: str = "SubDiv"; break;
172  default: str = "Unknown"; break;
173  }
174  return ToString(str, w, c, left);
175 }
176 
177 // ----------------------------------------------------------------------------
178 template <>
179 inline bool FromString(const char *str, JacobianConstraint::SubDomainEnum &value)
180 {
181  string lstr = ToLower(str);
182  if (lstr == "image" || lstr == "target" || lstr == "imagelattice") {
184  } else if (lstr == "lattice" || lstr == "ffd" || lstr == "ffdlattice" || lstr == "cp" || lstr == "cps" || lstr == "controlpoints") {
186  } else if (lstr == "shifted" || lstr == "betweencontrolpoints") {
188  } else if (lstr == "subdiv" || lstr == "subdivided" || lstr == "subdividedlattice") {
190  } else {
191  return false;
192  }
193  return true;
194 }
195 
196 
197 } // namespace mirtk
198 
199 #endif // MIRTK_JacobianConstraint_H
virtual void WriteGradient(const char *, const char *) const
Write gradient of penalty term.
Array< Matrix > _MatL2W
Sub-domain lattice coordinates to world.
Evaluate penalty at subdivided control point lattice.
Evaluate penalty in-between control points.
int _NumJacobian
Number of allocated Jacobian matrices.
Array< ImageAttributes > _SubDomains
Discrete sub-domain over which to integrate penalty.
Matrix * _AdjJacobian
Adjugate of Jacobian at each control point.
virtual double Evaluate()
Compute penalty for current transformation estimate.
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
virtual ~JacobianConstraint()
Destructor.
virtual void Initialize()
Initialize energy term once input and parameters have been set.
mirtkPublicAttributeMacro(SubDomainEnum, SubDomain)
Sub-domain on which to evaluate penalty.
mirtkReadOnlyAttributeMacro(bool, ConstrainParameterization)
string ToLower(const string &)
Convert string to lowercase letters.
virtual void Update(bool=true)
Update internal state upon change of input.
Definition: IOConfig.h:41
JacobianConstraint(const char *, bool=false)
Constructor.
virtual ParameterList Parameter() const
Get parameter key/value as string map.
virtual void EvaluateGradient(double *, double, double)
Compute gradient of penalty term w.r.t transformation parameters.
virtual void WriteDataSets(const char *, const char *, bool=true) const
Write Jacobian determinant.
virtual ParameterList Parameter() const
Get parameter name/value pairs.
SubDomainEnum
Enumeration of target image sub-domains on which to evaluate penalty.
Evaluate penalty at control points.
string ToString(const EnergyMeasure &value, int w, char c, bool left)
Convert energy measure enumeration value to string.
bool FromString(const char *str, EnergyMeasure &value)
Convert energy measure string to enumeration value.
double * _DetJacobian
Determinant of Jacobian at each control point.
virtual double DerivativeWrtJacobianDet(double det) const =0
Evaluate penalty at image voxels.
virtual bool SetWithoutPrefix(const char *, const char *)
Set parameter value from string.
Array< Matrix > _MatW2L
World to sub-domain lattice coordinates.
virtual double Penalty(double det) const =0