Developer documentation
Version 3.0.3-105-gd3941f44
base.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __registration_transform_base_h__
18#define __registration_transform_base_h__
19
20#include "types.h"
21#include <unsupported/Eigen/MatrixFunctions> // Eigen::MatrixBase::sqrt()
22#include <Eigen/SVD>
23#include <Eigen/Geometry> // Eigen::Translation
24#include "datatype.h" // debug
25#include "file/config.h"
27
28namespace MR
29{
30 namespace Registration
31 {
32 namespace Transform
33 {
34 template <class ValueType>
35 inline void param_mat2vec (const Eigen::Matrix<ValueType, 3, 4, Eigen::RowMajor>& transformation_matrix,
36 Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& param_vector) {
37 assert(param_vector.size() == 12);
38 param_vector = Eigen::Map<Eigen::MatrixXd> (transformation_matrix.data(), 12, 1);
39 }
40 template <class ValueType>
41 inline void param_mat2vec (const Eigen::Matrix<ValueType, 4, 4, Eigen::RowMajor>& transformation_matrix,
42 Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& param_vector) {
43 assert(param_vector.size() == 12);
44 param_vector = Eigen::Map<Eigen::MatrixXd> ((transformation_matrix.template block<3,4>(0,0)).data(), 12, 1);
45 }
46 template <class ValueType>
47 inline void param_mat2vec (const Eigen::Matrix<ValueType, 3, 4, Eigen::ColMajor>& transformation_matrix,
48 Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& param_vector) {
49 assert(param_vector.size() == 12);
50 // create temporary copy of the matrix in row major order and map it's memory as a vector
51 param_vector = Eigen::Map<Eigen::Matrix<ValueType, 12, 1>> (
52 (Eigen::Matrix<default_type, 3, 4, Eigen::RowMajor>(transformation_matrix)).data() );
53 }
54 template <class ValueType>
55 inline void param_mat2vec (const Eigen::Matrix<ValueType, 4, 4, Eigen::ColMajor>& transformation_matrix,
56 Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& param_vector) {
57 assert(param_vector.size() == 12);
58 // create temporary copy of the matrix in row major order and map it's memory as a vector
59 param_vector = Eigen::Map<Eigen::Matrix<ValueType, 12, 1>> (
60 (Eigen::Matrix<default_type, 3, 4, Eigen::RowMajor>((transformation_matrix.template block<3,4>(0,0)))).data() );
61 }
62 template <class Derived, class ValueType>
63 inline void param_vec2mat (const Eigen::MatrixBase<Derived>& param_vector,
64 Eigen::Matrix<ValueType, 3, 4>& transformation_matrix) {
65 assert(param_vector.size() == 12);
66 transformation_matrix = Eigen::Map<const Eigen::Matrix<ValueType, 3, 4, Eigen::RowMajor> >(&param_vector(0));
67 }
68 template <class Derived, class ValueType>
69 inline void param_vec2mat (const Eigen::MatrixBase<Derived>& param_vector,
70 Eigen::Matrix<ValueType, 4, 4>& transformation_matrix) {
71 assert(param_vector.size() == 12);
72 transformation_matrix.template block<3,4>(0,0) = Eigen::Map<const Eigen::Matrix<ValueType, 3, 4, Eigen::RowMajor> >(&param_vector(0));
73 transformation_matrix.row(3) << 0.0, 0.0, 0.0, 1.0;
74 }
75
87 public:
88
89 using ParameterType = default_type;
90 Base (size_t number_of_parameters) :
93 nonsymmetric (false)
94 {
95 trafo.matrix().setIdentity();
96 trafo_half.matrix().setIdentity();
97 trafo_half_inverse.matrix().setIdentity();
98 centre.setZero();
99 }
100
101
102 template <class OutPointType, class InPointType>
103 inline void transform (OutPointType& out, const InPointType& in) const {
104 out.noalias() = trafo * in;
105 }
106
107 template <class OutPointType, class InPointType>
108 inline void transform_half (OutPointType& out, const InPointType& in) const {
109 out.noalias() = trafo_half * in;
110 }
111
112 template <class OutPointType, class InPointType>
113 inline void transform_half_inverse (OutPointType& out, const InPointType& in) const {
114 out.noalias() = trafo_half_inverse * in;
115 }
116
117 size_t size() const {
119 }
120
121 Eigen::Matrix<default_type, 4, 1> get_jacobian_vector_wrt_params (const Eigen::Vector3d& p) const {
122 throw Exception ("FIXME: get_jacobian_vector_wrt_params not implemented for this metric");
123 Eigen::Matrix<default_type, 4, 1> jac;
124 return jac;
125 }
126
127 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> get_transform () const {
128 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> transform;
129 transform.matrix() = trafo.matrix();
130 return transform;
131 }
132
133 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> get_transform_half () const {
134 return trafo_half;
135 }
136
137 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> get_transform_half_inverse () const {
138 return trafo_half_inverse;
139 }
140
141 template <class TrafoType>
142 void set_transform (const TrafoType& transform) {
143 trafo.matrix().template block<3,4>(0,0) = transform.matrix().template block<3,4>(0,0);
145 }
146
147 // set_matrix_const_translation updates the 3x3 matrix without updating the translation
148 void set_matrix_const_translation (const Eigen::Matrix<ParameterType, 3, 3>& mat) {
149 trafo.linear() = mat;
151 }
152
153 // set_matrix updates the 3x3 matrix and also updates the translation
154 // void set_matrix (const Eigen::Matrix<ParameterType, 3, 3>& mat) {
155 // transform_type Tc2, To, R0;
156 // Tc2.setIdentity();
157 // To.setIdentity();
158 // R0.setIdentity();
159 // To.translation() = offset;
160 // Tc2.translation() = centre - 0.5 * offset;
161 // R0.linear() = mat;
162 // trafo = Tc2 * To * R0 * Tc2.inverse();
163 // compute_halfspace_transformations();
164 // }
165
166 const Eigen::Matrix<ParameterType, 3, 3> get_matrix () const {
167 return trafo.linear();
168 }
169
170 void set_translation (const Eigen::Matrix<ParameterType, 1, 3>& trans) {
171 trafo.translation() = trans;
174 }
175
176 const Eigen::Vector3d get_translation() const {
177 return trafo.translation();
178 }
179
180 void set_centre_without_transform_update (const Eigen::Vector3d& centre_in) {
181 centre = centre_in;
182 DEBUG ("centre: " + str(centre.transpose()));
183 }
184
185 void set_centre (const Eigen::Vector3d& centre_in) {
186 centre = centre_in;
187 DEBUG ("centre: " + str(centre.transpose()));
190 }
191
192 const Eigen::Vector3d get_centre() const {
193 return centre;
194 }
195
196
197 void set_optimiser_weights (Eigen::VectorXd& weights) {
198 assert(size() == (size_t)optimiser_weights.size());
199 optimiser_weights = weights;
200 }
201
202 Eigen::VectorXd get_optimiser_weights () const {
203 return optimiser_weights;
204 }
205
206
207 bool is_symmetric () const {
208 return !nonsymmetric;
209 }
210
211 void use_nonsymmetric (const bool asym) {
212 nonsymmetric = asym;
213 }
214
215 void set_offset (const Eigen::Vector3d& offset_in) {
216 trafo.translation() = offset_in;
218 }
219
220 std::string info () {
221 Eigen::IOFormat fmt(Eigen::FullPrecision, 0, ", ", "\n", "", "", "", "");
222 INFO ("transformation:\n"+str(trafo.matrix().format(fmt)));
223 DEBUG ("transformation_half:\n"+str(trafo_half.matrix().format(fmt)));
224 DEBUG ("transformation_half_inverse:\n"+str(trafo_half_inverse.matrix().format(fmt)));
225 return "centre: "+str(centre.transpose(),12);
226 }
227
228 std::string debug () {
229 Eigen::IOFormat fmt(Eigen::FullPrecision, 0, ", ", "\n", "", "", "", "");
230 CONSOLE ("trafo:\n"+str(trafo.matrix().format(fmt)));
231 CONSOLE ("trafo_inverse:\n"+str(trafo.inverse().matrix().format(fmt)));
232 CONSOLE ("trafo_half:\n"+str(trafo_half.matrix().format(fmt)));
233 CONSOLE ("trafo_half_inverse:\n"+str(trafo_half_inverse.matrix().format(fmt)));
234 CONSOLE ("centre: "+str(centre.transpose(),12));
235 return "";
236 }
237
238 template <class ParamType, class VectorType>
239 bool robust_estimate (VectorType& gradient,
240 vector<VectorType>& grad_estimates,
241 const ParamType& params,
242 const VectorType& parameter_vector,
243 const default_type& weiszfeld_precision,
244 const size_t& weiszfeld_iterations,
245 default_type& learning_rate) const {
246 DEBUG ("robust estimator is not implemented for this metric");
247 for (auto& grad_estimate : grad_estimates) {
248 gradient += grad_estimate;
249 }
250 return true;
251 }
252
253
254 protected:
256 trafo.translation() = (trafo.translation() + centre - trafo.linear() * centre).eval();
257 }
258
260 Eigen::Matrix<ParameterType, 4, 4> tmp;
261 tmp.setIdentity();
262 tmp.template block<3,4>(0,0) = trafo.matrix();
263 assert ((tmp.template block<3,3>(0,0).isApprox (trafo.linear())));
264 assert (tmp.determinant() > 0);
265 if (nonsymmetric) {
266 trafo_half.matrix() = tmp.template block<3,4>(0,0);
267 trafo_half_inverse.setIdentity();
268 assert (trafo.matrix().isApprox (trafo.matrix()));
269 } else {
270 tmp = tmp.sqrt().eval();
271 trafo_half.matrix() = tmp.template block<3,4>(0,0);
272 trafo_half_inverse.matrix() = trafo_half.inverse().matrix();
273 assert (trafo.matrix().isApprox ((trafo_half*trafo_half).matrix()));
274 assert (trafo.inverse().matrix().isApprox ((trafo_half_inverse*trafo_half_inverse).matrix()));
275 }
276 // debug();
277 }
278
280 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> trafo;
281 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> trafo_half;
282 Eigen::Transform<ParameterType, 3, Eigen::AffineCompact> trafo_half_inverse;
283 Eigen::Vector3d centre;
284 Eigen::VectorXd optimiser_weights;
286
287 };
289 }
290 }
291}
292
293#endif
Eigen::Transform< ParameterType, 3, Eigen::AffineCompact > trafo
Definition: base.h:280
Eigen::Transform< ParameterType, 3, Eigen::AffineCompact > trafo_half
Definition: base.h:281
Eigen::Transform< ParameterType, 3, Eigen::AffineCompact > trafo_half_inverse
Definition: base.h:282
Eigen::Vector3d centre
Definition: base.h:283
void compute_halfspace_transformations()
Definition: base.h:259
Eigen::VectorXd optimiser_weights
Definition: base.h:284
#define INFO(msg)
Definition: exception.h:74
#define DEBUG(msg)
Definition: exception.h:75
#define CONSOLE(msg)
Definition: exception.h:71
T eval(const double *coef, const int order, const T lower, const T upper, const T x)
Definition: chebyshev.h:29
transform_type TrafoType
Definition: search.h:55
void param_vec2mat(const Eigen::MatrixBase< Derived > &param_vector, Eigen::Matrix< ValueType, 3, 4 > &transformation_matrix)
Definition: base.h:63
void param_mat2vec(const Eigen::Matrix< ValueType, 3, 4, Eigen::RowMajor > &transformation_matrix, Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > &param_vector)
Definition: base.h:35
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247
#define MEMALIGN(...)
Definition: types.h:185