Developer documentation
Version 3.0.3-105-gd3941f44
voxel.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 __dwi_tractography_mapping_voxel_h__
18#define __dwi_tractography_mapping_voxel_h__
19
20
21
22#include <set>
23
24#include "image.h"
25
26#include "dwi/directions/set.h"
27
28
29namespace MR {
30 namespace DWI {
31 namespace Tractography {
32 namespace Mapping {
33
34
35
36 // Helper functions; note that int[3] rather than Voxel is always used during the mapping itself
37 template <typename T>
38 inline Eigen::Vector3i round (const Eigen::Matrix<T, 3, 1>& p)
39 {
40 assert (p.allFinite());
41 return { int(std::round (p[0])), int(std::round (p[1])), int(std::round (p[2])) };
42 }
43
44 template <class HeaderType>
45 inline bool check (const Eigen::Vector3i& V, const HeaderType& H)
46 {
47 return (V[0] >= 0 && V[0] < H.size(0) && V[1] >= 0 && V[1] < H.size(1) && V[2] >= 0 && V[2] < H.size(2));
48 }
49
50 inline Eigen::Vector3d vec2DEC (const Eigen::Vector3d& d)
51 {
52 return { abs(d[0]), abs(d[1]), abs(d[2]) };
53 }
54
55
56
57
58 class Voxel : public Eigen::Vector3i
59 { MEMALIGN(Voxel)
60 public:
61 Voxel (const int x, const int y, const int z) : Eigen::Vector3i (x,y,z), length (1.0f) { }
62 Voxel (const Eigen::Vector3i& that) : Eigen::Vector3i (that), length (1.0f) { }
63 Voxel (const Eigen::Vector3i& v, const default_type l) : Eigen::Vector3i (v), length (l) { }
64 Voxel () : length (0.0) { setZero(); }
65 bool operator< (const Voxel& V) const { return (((*this)[2] == V[2]) ? (((*this)[1] == V[1]) ? ((*this)[0] < V[0]) : ((*this)[1] < V[1])) : ((*this)[2] < V[2])); }
66 Voxel& operator= (const Voxel& V) { Eigen::Vector3i::operator= (V); length = V.length; return *this; }
67 void operator+= (const default_type l) const { length += l; }
68 void normalize() const { length = 1.0; }
69 default_type get_length() const { return length; }
70 private:
71 mutable default_type length;
72 };
73
74
75
76 class VoxelDEC : public Voxel
77 { MEMALIGN(VoxelDEC)
78
79 public:
80 VoxelDEC () :
81 Voxel (),
82 colour (0.0, 0.0, 0.0) { }
83
84 VoxelDEC (const Eigen::Vector3i& V) :
85 Voxel (V),
86 colour (0.0, 0.0, 0.0) { }
87
88 VoxelDEC (const Eigen::Vector3i& V, const Eigen::Vector3d& d) :
89 Voxel (V),
90 colour (vec2DEC (d)) { }
91
92 VoxelDEC (const Eigen::Vector3i& V, const Eigen::Vector3d& d, const float l) :
93 Voxel (V, l),
94 colour (vec2DEC (d)) { }
95
96 VoxelDEC& operator= (const VoxelDEC& V) { Voxel::operator= (V); colour = V.colour; return *this; }
97 VoxelDEC& operator= (const Eigen::Vector3i& V) { Voxel::operator= (V); colour = { 0.0, 0.0, 0.0 }; return *this; }
98
99 // For sorting / inserting, want to identify the same voxel, even if the colour is different
100 bool operator== (const VoxelDEC& V) const { return Voxel::operator== (V); }
101 bool operator< (const VoxelDEC& V) const { return Voxel::operator< (V); }
102
103 void normalize() const { colour.normalize(); Voxel::normalize(); }
104 void set_dir (const Eigen::Vector3d& i) { colour = vec2DEC (i); }
105 void add (const Eigen::Vector3d& i, const default_type l) const { Voxel::operator+= (l); colour += vec2DEC (i); }
106 void operator+= (const Eigen::Vector3d& i) const { Voxel::operator+= (1.0); colour += vec2DEC (i); }
107 const Eigen::Vector3d& get_colour() const { return colour; }
108
109 private:
110 mutable Eigen::Vector3d colour;
111
112 };
113
114
115
116 // Temporary fix for fixel stats branch
117 // Stores precise direction through voxel rather than mapping to a DEC colour or a dixel
118 class VoxelDir : public Voxel
119 { MEMALIGN(VoxelDir)
120
121 public:
122 VoxelDir () :
123 Voxel (),
124 dir (0.0, 0.0, 0.0) { }
125
126 VoxelDir (const Eigen::Vector3i& V) :
127 Voxel (V),
128 dir (0.0, 0.0, 0.0) { }
129
130 VoxelDir (const Eigen::Vector3i& V, const Eigen::Vector3d& d) :
131 Voxel (V),
132 dir (d) { }
133
134 VoxelDir (const Eigen::Vector3i& V, const Eigen::Vector3d& d, const default_type l) :
135 Voxel (V, l),
136 dir (d) { }
137
138 VoxelDir& operator= (const VoxelDir& V) { Voxel::operator= (V); dir = V.dir; return *this; }
139 VoxelDir& operator= (const Eigen::Vector3i& V) { Voxel::operator= (V); dir = { 0.0, 0.0, 0.0 }; return *this; }
140
141 bool operator== (const VoxelDir& V) const { return Voxel::operator== (V); }
142 bool operator< (const VoxelDir& V) const { return Voxel::operator< (V); }
143
144 void normalize() const { dir.normalize(); Voxel::normalize(); }
145 void set_dir (const Eigen::Vector3d& i) { dir = i; }
146 void add (const Eigen::Vector3d& i, const default_type l) const { Voxel::operator+= (l); dir += i * (dir.dot(i) < 0.0 ? -1.0 : 1.0); }
147 void operator+= (const Eigen::Vector3d& i) const { Voxel::operator+= (1.0); dir += i * (dir.dot(i) < 0.0 ? -1.0 : 1.0); }
148 const Eigen::Vector3d& get_dir() const { return dir; }
149
150 private:
151 mutable Eigen::Vector3d dir;
152
153 };
154
155
156
157 // Assumes tangent has been mapped to a hemisphere basis direction set
158 class Dixel : public Voxel
159 { MEMALIGN(Dixel)
160
161 public:
162
163 using dir_index_type = DWI::Directions::index_type;
164
165 Dixel () :
166 Voxel (),
167 dir (invalid) { }
168
169 Dixel (const Eigen::Vector3i& V) :
170 Voxel (V),
171 dir (invalid) { }
172
173 Dixel (const Eigen::Vector3i& V, const dir_index_type b) :
174 Voxel (V),
175 dir (b) { }
176
177 Dixel (const Eigen::Vector3i& V, const dir_index_type b, const default_type l) :
178 Voxel (V, l),
179 dir (b) { }
180
181 void set_dir (const size_t b) { dir = b; }
182
183 bool valid() const { return (dir != invalid); }
184 dir_index_type get_dir() const { return dir; }
185
186 Dixel& operator= (const Dixel& V) { Voxel::operator= (V); dir = V.dir; return *this; }
187 Dixel& operator= (const Eigen::Vector3i& V) { Voxel::operator= (V); dir = invalid; return *this; }
188 bool operator== (const Dixel& V) const { return (Voxel::operator== (V) ? (dir == V.dir) : false); }
189 bool operator< (const Dixel& V) const { return (Voxel::operator== (V) ? (dir < V.dir) : Voxel::operator< (V)); }
190 void operator+= (const float l) const { Voxel::operator+= (l); }
191
192 private:
193 dir_index_type dir;
194
195 static const dir_index_type invalid;
196
197 };
198
199
200
201 // TOD class: tore the SH coefficients in the voxel class so that aPSF generation can be multi-threaded
202 // Provide a normalize() function to remove any length dependence, and have unary contribution per streamline
203 class VoxelTOD : public Voxel
205
206 public:
207
208 using vector_type = Eigen::Matrix<default_type, Eigen::Dynamic, 1>;
209
210 VoxelTOD () :
211 Voxel (),
212 sh_coefs () { }
213
214 VoxelTOD (const Eigen::Vector3i& V) :
215 Voxel (V),
216 sh_coefs () { }
217
218 VoxelTOD (const Eigen::Vector3i& V, const vector_type& t) :
219 Voxel (V),
220 sh_coefs (t) { }
221
222 VoxelTOD (const Eigen::Vector3i& V, const vector_type& t, const default_type l) :
223 Voxel (V, l),
224 sh_coefs (t) { }
225
226 VoxelTOD& operator= (const VoxelTOD& V) { Voxel::operator= (V); sh_coefs = V.sh_coefs; return (*this); }
227 VoxelTOD& operator= (const Eigen::Vector3i& V) { Voxel::operator= (V); sh_coefs.resize(0); return (*this); }
228
229 // For sorting / inserting, want to identify the same voxel, even if the TOD is different
230 bool operator== (const VoxelTOD& V) const { return Voxel::operator== (V); }
231 bool operator< (const VoxelTOD& V) const { return Voxel::operator< (V); }
232
233 void normalize() const
234 {
235 const default_type multiplier = 1.0 / get_length();
236 sh_coefs *= multiplier;
237 Voxel::normalize();
238 }
239 void set_tod (const vector_type& i) { sh_coefs = i; }
240 void add (const vector_type& i, const default_type l) const
241 {
242 assert (i.size() == sh_coefs.size());
243 for (ssize_t index = 0; index != sh_coefs.size(); ++index)
244 sh_coefs[index] += l * i[index];
245 Voxel::operator+= (l);
246 }
247 void operator+= (const vector_type& i) const
248 {
249 assert (i.size() == sh_coefs.size());
250 sh_coefs += i;
251 Voxel::operator+= (1.0);
252 }
253 const vector_type& get_tod() const { return sh_coefs; }
254
255 private:
256 mutable vector_type sh_coefs;
257
258 };
259
260
261
262 std::ostream& operator<< (std::ostream&, const Voxel&);
263 std::ostream& operator<< (std::ostream&, const VoxelDEC&);
264 std::ostream& operator<< (std::ostream&, const VoxelDir&);
265 std::ostream& operator<< (std::ostream&, const Dixel&);
266 std::ostream& operator<< (std::ostream&, const VoxelTOD&);
267
268
269
271 { NOMEMALIGN
272 public:
273 default_type factor; // For TWI, when contribution to the map is uniform along the length of the track
274 size_t index; // Index of the track
275 default_type weight; // Cross-sectional multiplier for the track
276 };
277
278
279
280
281
282
283 // Set classes that give sensible behaviour to the insert() function depending on the base voxel class
284
285 class SetVoxel : public std::set<Voxel>, public SetVoxelExtras
286 { NOMEMALIGN
287 public:
288 using VoxType = Voxel;
289 inline void insert (const Voxel& v)
290 {
291 iterator existing = std::set<Voxel>::find (v);
292 if (existing == std::set<Voxel>::end())
293 std::set<Voxel>::insert (v);
294 else
295 (*existing) += v.get_length();
296 }
297 inline void insert (const Eigen::Vector3i& v, const default_type l)
298 {
299 const Voxel temp (v, l);
300 insert (temp);
301 }
302 };
303
304
305
306
307
308 class SetVoxelDEC : public std::set<VoxelDEC>, public SetVoxelExtras
309 { NOMEMALIGN
310 public:
312 inline void insert (const VoxelDEC& v)
313 {
314 iterator existing = std::set<VoxelDEC>::find (v);
315 if (existing == std::set<VoxelDEC>::end())
316 std::set<VoxelDEC>::insert (v);
317 else
318 existing->add (v.get_colour(), v.get_length());
319 }
320 inline void insert (const Eigen::Vector3i& v, const Eigen::Vector3d& d)
321 {
322 const VoxelDEC temp (v, d);
323 insert (temp);
324 }
325 inline void insert (const Eigen::Vector3i& v, const Eigen::Vector3d& d, const default_type l)
326 {
327 const VoxelDEC temp (v, d, l);
328 insert (temp);
329 }
330 };
331
332
333
334
335 class SetVoxelDir : public std::set<VoxelDir>, public SetVoxelExtras
336 { NOMEMALIGN
337 public:
339 inline void insert (const VoxelDir& v)
340 {
341 iterator existing = std::set<VoxelDir>::find (v);
342 if (existing == std::set<VoxelDir>::end())
343 std::set<VoxelDir>::insert (v);
344 else
345 existing->add (v.get_dir(), v.get_length());
346 }
347 inline void insert (const Eigen::Vector3i& v, const Eigen::Vector3d& d)
348 {
349 const VoxelDir temp (v, d);
350 insert (temp);
351 }
352 inline void insert (const Eigen::Vector3i& v, const Eigen::Vector3d& d, const default_type l)
353 {
354 const VoxelDir temp (v, d, l);
355 insert (temp);
356 }
357 };
358
359
360 class SetDixel : public std::set<Dixel>, public SetVoxelExtras
361 { NOMEMALIGN
362 public:
363
364 using VoxType = Dixel;
365 using dir_index_type = Dixel::dir_index_type;
366
367 inline void insert (const Dixel& v)
368 {
369 iterator existing = std::set<Dixel>::find (v);
370 if (existing == std::set<Dixel>::end())
371 std::set<Dixel>::insert (v);
372 else
373 (*existing) += v.get_length();
374 }
375 inline void insert (const Eigen::Vector3i& v, const dir_index_type d)
376 {
377 const Dixel temp (v, d);
378 insert (temp);
379 }
380 inline void insert (const Eigen::Vector3i& v, const dir_index_type d, const default_type l)
381 {
382 const Dixel temp (v, d, l);
383 insert (temp);
384 }
385 };
386
387
388
389
390
391 class SetVoxelTOD : public std::set<VoxelTOD>, public SetVoxelExtras
392 { NOMEMALIGN
393 public:
394
397
398 inline void insert (const VoxelTOD& v)
399 {
400 iterator existing = std::set<VoxelTOD>::find (v);
401 if (existing == std::set<VoxelTOD>::end())
402 std::set<VoxelTOD>::insert (v);
403 else
404 (*existing) += v.get_tod();
405 }
406 inline void insert (const Eigen::Vector3i& v, const vector_type& t)
407 {
408 const VoxelTOD temp (v, t);
409 insert (temp);
410 }
411 inline void insert (const Eigen::Vector3i& v, const vector_type& t, const default_type l)
412 {
413 const VoxelTOD temp (v, t, l);
414 insert (temp);
415 }
416 };
417
418
419
420 }
421 }
422 }
423}
424
425#endif
426
427
428
Array & operator=(const MR::Helper::ConstRow< ImageType > &row)
Definition: array.h:25
void insert(const Eigen::Vector3i &v, const dir_index_type d)
Definition: voxel.h:375
Dixel::dir_index_type dir_index_type
Definition: voxel.h:365
void insert(const Eigen::Vector3i &v, const dir_index_type d, const default_type l)
Definition: voxel.h:380
void insert(const Eigen::Vector3i &v, const Eigen::Vector3d &d)
Definition: voxel.h:320
void insert(const VoxelDEC &v)
Definition: voxel.h:312
void insert(const Eigen::Vector3i &v, const Eigen::Vector3d &d, const default_type l)
Definition: voxel.h:325
void insert(const Eigen::Vector3i &v, const Eigen::Vector3d &d, const default_type l)
Definition: voxel.h:352
void insert(const Eigen::Vector3i &v, const Eigen::Vector3d &d)
Definition: voxel.h:347
void insert(const VoxelDir &v)
Definition: voxel.h:339
void insert(const Eigen::Vector3i &v, const default_type l)
Definition: voxel.h:297
void insert(const Eigen::Vector3i &v, const vector_type &t)
Definition: voxel.h:406
VoxelTOD::vector_type vector_type
Definition: voxel.h:396
void insert(const VoxelTOD &v)
Definition: voxel.h:398
void insert(const Eigen::Vector3i &v, const vector_type &t, const default_type l)
Definition: voxel.h:411
#define NOMEMALIGN
Definition: memory.h:22
unsigned int index_type
Definition: set.h:34
Eigen::Vector3i round(const Eigen::Matrix< T, 3, 1 > &p)
Definition: voxel.h:38
bool check(const Eigen::Vector3i &V, const HeaderType &H)
Definition: voxel.h:45
std::ostream & operator<<(std::ostream &, const Voxel &)
Eigen::Vector3d vec2DEC(const Eigen::Vector3d &d)
Definition: voxel.h:50
Eigen::Array< value_type, Eigen::Dynamic, 1 > vector_type
Definition: typedefs.h:35
void set(HeaderType &header, const List &stride)
set the strides of header from a vector<ssize_t>
Definition: stride.h:135
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
constexpr std::enable_if< std::is_arithmetic< X >::value &&std::is_unsigned< X >::value, X >::type abs(X x)
Definition: types.h:297
Eigen::MatrixXd H
size_t index
#define MEMALIGN(...)
Definition: types.h:185