Developer documentation
Version 3.0.3-105-gd3941f44
invert.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_warp_invert_h__
18#define __registration_warp_invert_h__
19
20#include "image.h"
21#include "interp/linear.h"
22#include "algo/threaded_loop.h"
24#include "transform.h"
25
26namespace MR
27{
28 namespace Registration
29 {
30 namespace Warp
31 {
32
33 namespace {
34
35
36 class DisplacementThreadKernel { MEMALIGN(DisplacementThreadKernel)
37
38 public:
39 DisplacementThreadKernel (Image<default_type> & displacement,
40 Image<default_type> & displacement_inverse,
41 const size_t max_iter,
42 const default_type error_tol) :
43 displacement (displacement),
44 transform (displacement_inverse),
45 max_iter (max_iter),
46 error_tolerance (error_tol) {}
47
48 void operator() (Image<default_type>& displacement_inverse)
49 {
50 Eigen::Vector3d voxel ((default_type)displacement_inverse.index(0), (default_type)displacement_inverse.index(1), (default_type)displacement_inverse.index(2));
51 Eigen::Vector3d truth = transform.voxel2scanner * voxel;
52 Eigen::Vector3d current = truth + Eigen::Vector3d(displacement_inverse.row(3));
53
54 size_t iter = 0;
55 default_type error = std::numeric_limits<default_type>::max();
56 while (iter < max_iter && error > error_tolerance) {
57 error = update (current, truth);
58 ++iter;
59 }
60 displacement_inverse.row(3) = current - truth;
61 }
62
63 private:
64
65 default_type update (Eigen::Vector3d& current, const Eigen::Vector3d& truth)
66 {
67 displacement.scanner (current);
68 Eigen::Vector3d discrepancy = truth - (current + Eigen::Vector3d (displacement.row(3)));
69 current += discrepancy;
70 return discrepancy.dot (discrepancy);
71 }
72
73 Interp::Linear<Image<default_type> > displacement;
74 MR::Transform transform;
75 const size_t max_iter;
76 default_type error_tolerance;
77 };
78
79
80 class DeformationThreadKernel { MEMALIGN(DeformationThreadKernel)
81
82 public:
83 DeformationThreadKernel (Image<default_type> & deform,
84 Image<default_type> & inv_deform,
85 const size_t max_iter,
86 const default_type error_tol) :
87 deform (deform),
88 transform (inv_deform),
89 max_iter (max_iter),
90 error_tolerance (error_tol) {}
91
92 void operator() (Image<default_type>& inv_deform)
93 {
94 Eigen::Vector3d voxel ((default_type)inv_deform.index(0), (default_type)inv_deform.index(1), (default_type)inv_deform.index(2));
95 Eigen::Vector3d truth = transform.voxel2scanner * voxel;
96 Eigen::Vector3d current = inv_deform.row(3);
97
98 size_t iter = 0;
99 default_type error = std::numeric_limits<default_type>::max();
100 while (iter < max_iter && error > error_tolerance) {
101 error = update (current, truth);
102 ++iter;
103 }
104 inv_deform.row(3) = current;
105 }
106
107 private:
108
109 default_type update (Eigen::Vector3d& current, const Eigen::Vector3d& truth)
110 {
111 deform.scanner (current);
112 Eigen::Vector3d discrepancy = truth - Eigen::Vector3d (deform.row(3));
113 current += discrepancy;
114 return discrepancy.dot (discrepancy);
115 }
116
117 Interp::Linear<Image<default_type> > deform;
118 MR::Transform transform;
119 const size_t max_iter;
120 default_type error_tolerance;
121 };
122 }
123
124
131 FORCE_INLINE void invert_deformation (Image<default_type>& deform_field, Image<default_type>& inv_deform_field, bool is_initialised = false, size_t max_iter = 50, default_type error_tolerance = 0.0001)
132 {
133 check_dimensions (deform_field, inv_deform_field);
134 error_tolerance *= (deform_field.spacing(0) + deform_field.spacing(1) + deform_field.spacing(2)) / 3;
135
136 if (!is_initialised)
137 displacement2deformation (inv_deform_field, inv_deform_field);
138
139 ThreadedLoop ("inverting warp field...", inv_deform_field, 0, 3)
140 .run (DeformationThreadKernel (deform_field, inv_deform_field, max_iter, error_tolerance), inv_deform_field);
141 }
142
146 FORCE_INLINE void invert_displacement_deformation (Image<default_type>& disp, Image<default_type>& inv_deform, bool is_initialised = false, size_t max_iter = 50, default_type error_tolerance = 0.0001)
147 {
148 auto deform_field = Image<default_type>::scratch (disp);
149 Warp::displacement2deformation (disp, deform_field);
150
151 invert_deformation (deform_field, inv_deform, is_initialised, max_iter, error_tolerance);
152 }
153
154
158 FORCE_INLINE void invert_displacement (Image<default_type>& disp_field, Image<default_type>& inv_disp_field, size_t max_iter = 50, default_type error_tolerance = 0.0001)
159 {
160 check_dimensions (disp_field, inv_disp_field);
161 error_tolerance *= (disp_field.spacing(0) + disp_field.spacing(1) + disp_field.spacing(2)) / 3;
162
163 ThreadedLoop ("inverting displacement field...", inv_disp_field, 0, 3)
164 .run (DisplacementThreadKernel (disp_field, inv_disp_field, max_iter, error_tolerance), inv_disp_field);
165 }
166
167
169 }
170 }
171}
172
173
174#endif
static Image scratch(const Header &template_header, const std::string &label="scratch image")
Definition: image.h:195
default_type spacing(size_t axis) const
Definition: image.h:67
const transform_type voxel2scanner
Definition: transform.h:43
FORCE_INLINE void invert_displacement_deformation(Image< default_type > &disp, Image< default_type > &inv_deform, bool is_initialised=false, size_t max_iter=50, default_type error_tolerance=0.0001)
Definition: invert.h:146
FORCE_INLINE void invert_displacement(Image< default_type > &disp_field, Image< default_type > &inv_disp_field, size_t max_iter=50, default_type error_tolerance=0.0001)
Definition: invert.h:158
FORCE_INLINE void invert_deformation(Image< default_type > &deform_field, Image< default_type > &inv_deform_field, bool is_initialised=false, size_t max_iter=50, default_type error_tolerance=0.0001)
Definition: invert.h:131
std::pair< int, int > current()
Definition: gl.h:135
void displacement2deformation(ImageType &input, ImageType &output)
Definition: convert.h:34
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
ThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> ThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
Multi-threaded loop object.
#define MEMALIGN(...)
Definition: types.h:185
#define FORCE_INLINE
Definition: types.h:156