17#ifndef __registration_metric_threadkernel_h__
18#define __registration_metric_threadkernel_h__
28 namespace Registration
40 template <
class MetricType,
typename U =
void>
45 template <
class MetricType>
46 struct is_neighbourhood_metric<MetricType, typename Void<typename MetricType::is_neighbourhood>::type> {
NOMEMALIGN
50 template <
class MetricType,
typename U =
void>
55 template <
class MetricType>
56 struct use_processed_image<MetricType, typename Void<typename MetricType::requires_precompute>::type> {
NOMEMALIGN
60 template <
class MetricType,
typename U =
void>
65 template <
class MetricType>
66 struct cost_is_vector<MetricType, typename Void<typename MetricType::is_vector_type>::type> {
NOMEMALIGN
70 template <
class MetricType,
typename U =
void>
75 template <
class MetricType>
76 struct is_asymmetric<MetricType, typename Void<typename MetricType::is_asymmetric_type>::type> {
NOMEMALIGN
82 template <
class MetricType,
class ParamType>
87 const ParamType& parameters,
100 if (
params.robust_estimate_subset) {
102 assert (
params.robust_estimate_subset_from.size() == 3);
104 auto spacing = Eigen::DiagonalMatrix<default_type, 3> (
params.midway_image.spacing(0),
params.midway_image.spacing(1),
params.midway_image.spacing(2));
105 for (
size_t j = 0; j < 3; ++j)
106 for (
size_t i = 0; i < 3; ++i)
107 i2s(i,3) +=
params.robust_estimate_subset_from[j] *
params.midway_image.spacing(j) * i2s(i,j);
118 (*overall_cnt) +=
cnt;
121 template <
class U = MetricType>
122 void operator() (
const Iterator& iter,
123 typename is_neighbourhood_metric<U>::no = 0,
124 typename use_processed_image<U>::no = 0,
125 typename cost_is_vector<U>::no = 0,
126 typename is_asymmetric<U>::no = 0) {
133 Eigen::Vector3d im2_point;
134 params.transformation.transform_half_inverse (im2_point, midway_point);
135 if (
params.im2_mask_interp) {
136 params.im2_mask_interp->scanner (im2_point);
137 if (
params.im2_mask_interp->value() < 0.5)
140 if (
params.robust_estimate_use_score &&
params.robust_estimate_score2_interp) {
141 params.robust_estimate_score2_interp->scanner (im2_point);
142 if (!(
params.robust_estimate_score2_interp->value() >= 0.5))
146 Eigen::Vector3d im1_point;
147 params.transformation.transform_half (im1_point, midway_point);
148 if (
params.im1_mask_interp) {
149 params.im1_mask_interp->scanner (im1_point);
150 if (
params.im1_mask_interp->value() < 0.5)
153 if (
params.robust_estimate_use_score &&
params.robust_estimate_score1_interp) {
154 params.robust_estimate_score1_interp->scanner (im1_point);
155 if (!(
params.robust_estimate_score1_interp->value() >= 0.5))
159 params.im1_image_interp->scanner (im1_point);
160 if (!(*
params.im1_image_interp))
163 params.im2_image_interp->scanner (im2_point);
164 if (!(*
params.im2_image_interp))
172 template <
class U = MetricType>
173 void operator() (
const Iterator& iter,
174 typename is_neighbourhood_metric<U>::no = 0,
175 typename use_processed_image<U>::no = 0,
176 typename cost_is_vector<U>::no = 0,
177 typename is_asymmetric<U>::yes = 0) {
183 if (
params.robust_estimate_subset) {
184 assert(
params.robust_estimate_subset_from.size() == 3);
185 voxel_pos[0] +=
params.robust_estimate_subset_from[0];
186 voxel_pos[1] +=
params.robust_estimate_subset_from[1];
187 voxel_pos[2] +=
params.robust_estimate_subset_from[2];
190 if (!
params.robust_estimate_subset &&
params.robust_estimate_score2_interp) {
191 params.robust_estimate_score2_interp->scanner (im2_point);
192 if (!(
params.robust_estimate_score2_interp->value() >= 0.5))
196 params.im2_image.index(0) = voxel_pos[0];
197 params.im2_image.index(1) = voxel_pos[1];
198 params.im2_image.index(2) = voxel_pos[2];
209 if (
params.im2_mask_interp) {
210 params.im2_mask_interp->scanner (im2_point);
211 if (
params.im2_mask_interp->value() < 0.5)
215 Eigen::Vector3d im1_point;
216 params.transformation.transform_half (im1_point, im2_point);
217 if (
params.im1_mask_interp) {
218 params.im1_mask_interp->scanner (im1_point);
219 if (
params.im1_mask_interp->value() < 0.5)
222 if (
params.robust_estimate_use_score &&
params.robust_estimate_score1_interp) {
223 params.robust_estimate_score1_interp->scanner (im1_point);
224 if (!(
params.robust_estimate_score1_interp->value() >= 0.5))
228 params.im1_image_interp->scanner (im1_point);
229 if (!(*
params.im1_image_interp))
236 template <
class U = MetricType>
237 void operator() (
const Iterator& iter,
238 typename is_neighbourhood_metric<U>::no = 0,
239 typename use_processed_image<U>::no = 0,
240 typename cost_is_vector<U>::yes = 0,
241 typename is_asymmetric<U>::no = 0) {
247 Eigen::Vector3d im2_point;
248 params.transformation.transform_half_inverse (im2_point, midway_point);
249 if (
params.im2_mask_interp) {
250 params.im2_mask_interp->scanner (im2_point);
251 if (
params.im2_mask_interp->value() < 0.5)
255 Eigen::Vector3d im1_point;
256 params.transformation.transform_half (im1_point, midway_point);
257 if (
params.im1_mask_interp) {
258 params.im1_mask_interp->scanner (im1_point);
259 if (
params.im1_mask_interp->value() < 0.5)
263 params.im1_image_interp->scanner (im1_point);
264 if (!(*
params.im1_image_interp))
267 params.im2_image_interp->scanner (im2_point);
268 if (!(*
params.im2_image_interp))
275 template <
class U = MetricType>
276 void operator() (
const Iterator& iter,
277 typename is_neighbourhood_metric<U>::no = 0,
278 typename use_processed_image<U>::yes = 0,
279 typename cost_is_vector<U>::no = 0,
280 typename is_asymmetric<U>::no = 0) {
281 assert (
params.processed_image.valid());
282 assign_pos_of (iter, 0, 3).to (
params.processed_image);
284 if (
params.processed_mask.valid()) {
285 assign_pos_of (iter, 0, 3).to (
params.processed_mask);
286 if (!
params.processed_mask.value())
293 template <
class U = MetricType>
294 void operator() (
const Iterator& iter,
295 typename is_neighbourhood_metric<U>::yes = 0,
296 typename use_processed_image<U>::yes = 0,
297 typename cost_is_vector<U>::no = 0,
298 typename is_asymmetric<U>::no = 0) {
299 assert(
params.processed_image.valid());
303 if (
params.processed_mask.valid()){
304 assign_pos_of (iter, 0, 3).to (
params.processed_mask);
305 assert(
params.processed_mask.index(0) == iter.
index(0));
306 assert(
params.processed_mask.index(1) == iter.
index(1));
307 assert(
params.processed_mask.index(2) == iter.
index(2));
308 if (!
params.processed_mask.value())
330 template <
class MetricType,
class ParamType>
337 const ParamType& parameters,
339 Eigen::VectorXd& overall_grad,
364 auto engine = std::default_random_engine{
static_cast<std::default_random_engine::result_type
>(
rng.
get_seed())};
367 assign_pos_of(iter).to(iterator);
369 for (
auto j = inner_loop; j; ++j)
a dummy image to iterate over, useful for multi-threaded looping.
ssize_t size(size_t axis) const
const ssize_t & index(size_t axis) const
static std::mt19937::result_type get_seed()
Eigen::VectorXd & overall_cost_function
transform_type voxel2scanner
Eigen::VectorXd & overall_gradient
Eigen::VectorXd cost_function
FORCE_INLINE LoopAlongAxes Loop()
double default_type
the default type used throughout MRtrix
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
Eigen::VectorXd & overall_cost_function
Eigen::VectorXd cost_function
MEMALIGN(StochasticThreadKernel) public
~StochasticThreadKernel()
Eigen::VectorXd & overall_gradient
vector< size_t > inner_axes
void operator()(const Iterator &iter)