Developer documentation
Version 3.0.3-105-gd3941f44
roi.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_roi_h__
18#define __dwi_tractography_roi_h__
19
20#include "app.h"
21#include "image.h"
22#include "image.h"
23#include "interp/linear.h"
24#include "math/rng.h"
25#include "misc/bitset.h"
26
27
28namespace MR
29{
30 namespace DWI
31 {
32 namespace Tractography
33 {
34 class Properties;
35
36
37 extern const App::OptionGroup ROIOption;
38 void load_rois (Properties& properties);
39
40
41 class Mask : public Image<bool> { MEMALIGN(Mask)
42 public:
43 using transform_type = Eigen::Transform<float, 3, Eigen::AffineCompact>;
44 Mask (const Mask&) = default;
45 Mask (const std::string& name) :
46 Image<bool> (__get_mask (name)),
47 scanner2voxel (new transform_type (Transform(*this).scanner2voxel.cast<float>())),
48 voxel2scanner (new transform_type (Transform(*this).voxel2scanner.cast<float>())) { }
49
50 std::shared_ptr<transform_type> scanner2voxel, voxel2scanner; // Ptr to prevent unnecessary copy-construction
51
52 private:
53 static Image<bool> __get_mask (const std::string& name);
54 };
55
56
57
58
59 class ROI { MEMALIGN(ROI)
60 public:
61 ROI (const Eigen::Vector3f& sphere_pos, float sphere_radius) :
62 pos (sphere_pos), radius (sphere_radius), radius2 (Math::pow2 (radius)) { }
63
64 ROI (const std::string& spec) :
65 radius (NaN), radius2 (NaN)
66 {
67 try {
68 auto F = parse_floats (spec);
69 if (F.size() != 4)
70 throw 1;
71 pos[0] = F[0];
72 pos[1] = F[1];
73 pos[2] = F[2];
74 radius = F[3];
75 radius2 = Math::pow2 (radius);
76 }
77 catch (Exception& e_assphere) {
78 try {
79 mask.reset (new Mask (spec));
80 } catch (Exception& e_asimage) {
81 Exception e ("Unable to parse text \"" + spec + "\" as a ROI");
82 e.push_back ("If interpreted as sphere:");
83 for (size_t i = 0; i != e_assphere.num(); ++i)
84 e.push_back (" " + e_assphere[i]);
85 e.push_back ("If interpreted as image:");
86 for (size_t i = 0; i != e_asimage.num(); ++i)
87 e.push_back (" " + e_asimage[i]);
88 throw e;
89 }
90 }
91 }
92
93 std::string shape () const { return (mask ? "image" : "sphere"); }
94
95 std::string parameters () const {
96 return mask ?
97 mask->name() :
98 str(pos[0]) + "," + str(pos[1]) + "," + str(pos[2]) + "," + str(radius);
99 }
100
101 float min_featurelength() const {
102 return mask ?
103 std::min ({ mask->spacing(0), mask->spacing(1), mask->spacing(2) }) :
104 radius;
105 }
106
107 bool contains (const Eigen::Vector3f& p) const
108 {
109 if (mask) {
110 Eigen::Vector3f v = *(mask->scanner2voxel) * p;
111 Mask temp (*mask); // Required for thread-safety
112 temp.index(0) = std::round (v[0]);
113 temp.index(1) = std::round (v[1]);
114 temp.index(2) = std::round (v[2]);
115 if (is_out_of_bounds (temp))
116 return false;
117 return temp.value();
118 }
119 return (pos-p).squaredNorm() <= radius2;
120 }
121
122 friend inline std::ostream& operator<< (std::ostream& stream, const ROI& roi)
123 {
124 stream << roi.shape() << " (" << roi.parameters() << ")";
125 return stream;
126 }
127
128
129
130 private:
131 Eigen::Vector3f pos;
132 float radius, radius2;
133 std::shared_ptr<Mask> mask;
134
135 };
136
137
138
139
141 { MEMALIGN(ROISetBase)
142 public:
143 ROISetBase () { }
144
145 void clear () { R.clear(); }
146 size_t size () const { return (R.size()); }
147 const ROI& operator[] (size_t i) const { return (R[i]); }
148 void add (const ROI& roi) { R.push_back (roi); }
149
150 friend inline std::ostream& operator<< (std::ostream& stream, const ROISetBase& R) {
151 if (R.R.empty()) return (stream);
152 vector<ROI>::const_iterator i = R.R.begin();
153 stream << *i;
154 ++i;
155 for (; i != R.R.end(); ++i) stream << ", " << *i;
156 return stream;
157 }
158
159 protected:
161 };
162
163
164
165
167 { MEMALIGN(ROIUnorderedSet)
168 public:
169 ROIUnorderedSet () { }
170 bool contains (const Eigen::Vector3f& p) const {
171 for (size_t n = 0; n < R.size(); ++n)
172 if (R[n].contains (p)) return (true);
173 return false;
174 }
175 void contains (const Eigen::Vector3f& p, BitSet& retval) const {
176 for (size_t n = 0; n < R.size(); ++n)
177 if (R[n].contains (p)) retval[n] = true;
178 }
179 };
180
181
182
183
184
187 public:
188
189 class LoopState
190 { NOMEMALIGN
191 public:
192 LoopState (const ROIOrderedSet& master) :
193 size (master.size()),
194 valid (true),
195 next_index (0) { }
196 LoopState (const size_t num_rois) :
197 size (num_rois),
198 valid (true),
199 next_index (0) { }
200
201 void reset() { valid = true; next_index = 0; }
202 operator bool () const { return valid; }
203
204 void operator() (const size_t roi_index)
205 {
206 assert (roi_index < size);
207 if (roi_index == next_index)
208 ++next_index;
209 else if (roi_index != next_index - 1)
210 valid = false;
211 }
212
213 bool all_entered() const { return (valid && (next_index == size)); }
214
215 private:
216 const size_t size;
217 bool valid; // true if the order at which ROIs have been entered thus far is legal
218 size_t next_index;
219 };
220
221 ROIOrderedSet () { }
222
223 void contains (const Eigen::Vector3f& p, LoopState& loop_state) const
224 {
225 // do nothing if the series of coordinates have already performed something illegal
226 if (!loop_state)
227 return;
228 for (size_t n = 0; n < R.size(); ++n) {
229 if (R[n].contains(p)) {
230 loop_state (n);
231 break;
232 }
233 }
234 }
235
236 };
237
238
239
240
242 { MEMALIGN(IncludeROIVisitation)
243 public:
244
246 const ROIOrderedSet& ordered) :
249 visited (unordered.size()),
250 state (ordered.size()) { }
251
253 IncludeROIVisitation& operator= (const IncludeROIVisitation&) = delete;
254
255 void reset() { visited.clear(); state.reset(); }
256 size_t size() const { return unordered.size() + ordered.size(); }
257
258 void operator() (const Eigen::Vector3f& p)
259 {
260 unordered.contains (p, visited);
261 ordered.contains (p, state);
262 }
263
264 operator bool () const { return (visited.full() && state.all_entered()); }
265 bool operator! () const { return (!visited.full() || !state.all_entered()); }
266
267
268 protected:
272 ROIOrderedSet::LoopState state;
273 };
274
275
276
277
278
279 }
280 }
281}
282
283#endif
a class for storing bitwise information
Definition: bitset.h:43
void clear(const bool allocator=false)
clear the data
bool full() const
whether or not the bitset is 'full' i.e. all elements are true
const ROIOrderedSet & ordered
Definition: roi.h:270
ROIOrderedSet::LoopState state
Definition: roi.h:272
const ROIUnorderedSet & unordered
Definition: roi.h:269
friend std::ostream & operator<<(std::ostream &stream, const ROI &roi)
Definition: roi.h:122
friend std::ostream & operator<<(std::ostream &stream, const ROISetBase &R)
Definition: roi.h:150
size_t num() const
Definition: exception.h:96
functions and classes related to image data input/output
Definition: image.h:41
const std::string & name() const
Definition: image.h:62
const transform_type voxel2scanner
Definition: transform.h:43
const transform_type scanner2voxel
Definition: transform.h:43
constexpr T pow2(const T &v)
Definition: math.h:53
constexpr I round(const T x)
Definition: math.h:64
constexpr double e
Definition: math.h:39
#define NOMEMALIGN
Definition: memory.h:22
void load_rois(Properties &properties)
const App::OptionGroup ROIOption
Definition: base.h:24
vector< default_type > parse_floats(const std::string &spec)
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
Definition: types.h:234
constexpr default_type NaN
Definition: types.h:230
#define MEMALIGN(...)
Definition: types.h:185