Developer documentation
Version 3.0.3-105-gd3941f44
model_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 __dwi_tractography_sift_model_base_h__
18#define __dwi_tractography_sift_model_base_h__
19
20#include "app.h"
21#include "dwi/fixel_map.h"
22#include "dwi/fmls.h"
23
24#include "dwi/directions/set.h"
25
27
29
35
38
39#include "file/path.h"
40
41#include "image.h"
42#include "algo/copy.h"
43#include "thread_queue.h"
44
45
46//#define SIFT_MODEL_OUTPUT_SH_IMAGES
47#define SIFT_MODEL_OUTPUT_FIXEL_IMAGES
48
49
50namespace MR
51{
52 namespace DWI
53 {
54 namespace Tractography
55 {
56 namespace SIFT
57 {
58
59
60
62 { MEMALIGN(FixelBase)
63
64 public:
65 FixelBase () :
66 FOD (0.0),
67 TD (0.0),
68 weight (0.0),
69 dir () { }
70
71 FixelBase (const default_type amp) :
72 FOD (amp),
73 TD (0.0),
74 weight (1.0),
75 dir () { }
76
77 FixelBase (const default_type amp, const Eigen::Vector3d& d) :
78 FOD (amp),
79 TD (0.0),
80 weight (1.0),
81 dir (d) { }
82
83 FixelBase (const FMLS::FOD_lobe& lobe) :
84 FOD (lobe.get_integral()),
85 TD (0.0),
86 weight (1.0),
87 dir (lobe.get_mean_dir()) { }
88
89 FixelBase (const FixelBase&) = default;
90
91 default_type get_FOD() const { return FOD; }
92 default_type get_TD() const { return TD; }
93 default_type get_weight() const { return weight; }
94 const Eigen::Vector3d& get_dir() const { return dir; }
95
96 void scale_FOD (const default_type factor) { FOD *= factor; }
97 void set_weight (const default_type w) { weight = w; }
98 FixelBase& operator+= (const default_type length) { TD += length; return *this; }
99
100 void clear_TD() { TD = 0.0; }
101
102 default_type get_diff (const default_type mu) const { return ((TD * mu) - FOD); }
103 default_type get_cost (const default_type mu) const { return get_cost_unweighted (mu) * weight; }
104
105
106 protected:
108 Eigen::Vector3d dir;
109
110 default_type get_cost_unweighted (const default_type mu) const { return Math::pow2 (get_diff (mu)); }
111
112 };
113
114
115
116
117
118
119 // Templated Fixel class should derive from FixelBase to ensure that it has adequate functionality
120 // This class stores the necessary fixel information (including streamline densities), but does not retain the
121 // list of fixels traversed by each streamline. If this information is necessary, use the Model class (model.h)
122
123 template <class Fixel>
124 class ModelBase : public Mapping::Fixel_TD_map<Fixel>
126
127 protected:
128 using MapVoxel = typename Fixel_map<Fixel>::MapVoxel;
130
131 public:
133 Mapping::Fixel_TD_map<Fixel> (dwi, dirs),
134 proc_mask (Image<float>::scratch (Fixel_map<Fixel>::header(), "SIFT model processing mask")),
135 FOD_sum (0.0),
136 TD_sum (0.0),
137 have_null_lobes (false)
138 {
140 }
141 ModelBase (const ModelBase&) = delete;
142
143 virtual ~ModelBase () { }
144
147
148 void map_streamlines (const std::string&);
149
150 virtual bool operator() (const FMLS::FOD_lobes& in);
151 virtual bool operator() (const Mapping::SetDixel& in);
152
154
155 default_type mu() const { return FOD_sum / TD_sum; }
156 bool have_act_data() const { return act_5tt.valid(); }
157
158 void output_proc_mask (const std::string&);
159 void output_5tt_image (const std::string&);
160 void output_all_debug_images (const std::string&) const;
161
163
164
165 protected:
169
173
174 // The definitions of these functions are located in dwi/tractography/SIFT/output.h
175 void output_target_image (const std::string&) const;
176 void output_target_image_sh (const std::string&) const;
177 void output_target_image_fixel (const std::string&) const;
178 void output_tdi (const std::string&) const;
179 void output_tdi_null_lobes (const std::string&) const;
180 void output_tdi_sh (const std::string&) const;
181 void output_tdi_fixel (const std::string&) const;
182 void output_error_images (const std::string&, const std::string&, const std::string&) const;
183 void output_error_fixel_images (const std::string&, const std::string&) const;
184 void output_scatterplot (const std::string&) const;
185 void output_fixel_count_image (const std::string&) const;
186 void output_untracked_fixels (const std::string&, const std::string&) const;
187
188 };
189
190
191
192
193 template <class Fixel>
195 {
196 Math::SH::check (data);
197 DWI::FMLS::FODQueueWriter writer (data, proc_mask);
198 DWI::FMLS::Segmenter fmls (dirs, Math::SH::LforN (data.size(3)));
199 fmls.set_dilate_lookup_table (!App::get_options ("no_dilate_lut").size());
200 fmls.set_create_null_lobe (App::get_options ("make_null_lobes").size());
202 have_null_lobes = fmls.get_create_null_lobe();
203 }
204
205
206
207
208 template <class Fixel>
210 {
211 if (!App::get_options("fd_scale_gm").size())
212 return;
213 if (!act_5tt.valid()) {
214 INFO ("Cannot scale fibre densities according to GM fraction; no ACT image data provided");
215 return;
216 }
217 // Loop through voxels, getting total GM fraction for each, and scale all fixels in each voxel
218 VoxelAccessor v (accessor());
219 FOD_sum = 0.0;
220 for (auto l = Loop(v) (v, act_5tt); l; ++l) {
221 Tractography::ACT::Tissues tissues (act_5tt);
222 const default_type multiplier = 1.0 - tissues.get_cgm() - (0.5 * tissues.get_sgm()); // Heuristic
223 for (typename Fixel_map<Fixel>::Iterator i = begin(v); i; ++i) {
224 i().scale_FOD (multiplier);
225 FOD_sum += i().get_weight() * i().get_FOD();
226 }
227 }
228 }
229
230
231
232
233 template <class Fixel>
234 void ModelBase<Fixel>::map_streamlines (const std::string& path)
235 {
236 Tractography::Properties properties;
237 Tractography::Reader<> file (path, properties);
238
239 const track_t count = (properties.find ("count") == properties.end()) ? 0 : to<track_t>(properties["count"]);
240 if (!count)
241 throw Exception ("Cannot map streamlines: track file " + Path::basename(path) + " is empty");
242
243 Mapping::TrackLoader loader (file, count);
245 mapper.set_upsample_ratio (Mapping::determine_upsample_ratio (Fixel_map<Fixel>::header(), properties, 0.1));
246 mapper.set_use_precise_mapping (true);
248 loader,
250 Thread::multi (mapper),
252 *this);
253
254 INFO ("Proportionality coefficient after streamline mapping is " + str (mu()));
255 }
256
257
258
259
260 template <class Fixel>
262 {
263 if (!Fixel_map<Fixel>::operator() (in))
264 return false;
265
266 VoxelAccessor v (accessor());
267 assign_pos_of (in.vox).to (v);
268
269 if (v.value()) {
270 assign_pos_of (in.vox).to (proc_mask);
271 const float mask_value = proc_mask.value();
272
273 for (typename Fixel_map<Fixel>::Iterator i = begin (v); i; ++i) {
274 i().set_weight (mask_value);
275 FOD_sum += i().get_FOD() * mask_value;
276 }
277 }
278 return true;
279 }
280
281
282
283
284 template <class Fixel>
286 {
287 default_type total_contribution = 0.0;
288 for (Mapping::SetDixel::const_iterator i = in.begin(); i != in.end(); ++i) {
289 const size_t fixel_index = Mapping::Fixel_TD_map<Fixel>::dixel2fixel (*i);
290 if (fixel_index) {
291 fixels[fixel_index] += i->get_length();
292 total_contribution += fixels[fixel_index].get_weight() * i->get_length();
293 }
294 }
295 TD_sum += total_contribution;
296 return true;
297 }
298
299
300
301
302 template <class Fixel>
304 {
305 const default_type current_mu = mu();
306 default_type cost = 0.0;
307 for (auto i = fixels.cbegin()+1; i != fixels.end(); ++i)
308 cost += i->get_cost (current_mu);
309 return cost;
310 }
311
312
313
314 template <class Fixel>
315 void ModelBase<Fixel>::output_proc_mask (const std::string& path)
316 {
317 save (proc_mask, path);
318 }
319
320
321 template <class Fixel>
322 void ModelBase<Fixel>::output_5tt_image (const std::string& path)
323 {
324 if (!have_act_data())
325 throw Exception ("Cannot export 5TT image; no such data present");
326 save (act_5tt, path);
327 }
328
329
330
331
332 template <class Fixel>
333 void ModelBase<Fixel>::output_all_debug_images (const std::string& prefix) const
334 {
335 output_target_image (prefix + "_target.mif");
336#ifdef SIFT_MODEL_OUTPUT_SH_IMAGES
337 output_target_image_sh (prefix + "_target_sh.mif");
338#endif
339#ifdef SIFT_MODEL_OUTPUT_FIXEL_IMAGES
340 output_target_image_fixel (prefix + "_target_fixel.msf");
341#endif
342 output_tdi (prefix + "_tdi.mif");
343 if (have_null_lobes)
344 output_tdi_null_lobes (prefix + "_tdi_null_lobes.mif");
345#ifdef SIFT_MODEL_OUTPUT_SH_IMAGES
346 output_tdi_sh (prefix + "_tdi_sh.mif");
347#endif
348#ifdef SIFT_MODEL_OUTPUT_FIXEL_IMAGES
349 output_tdi_fixel (prefix + "_tdi_fixel.msf");
350#endif
351 output_error_images (prefix + "_max_abs_diff.mif", prefix + "_diff.mif", prefix + "_cost.mif");
352#ifdef SIFT_MODEL_OUTPUT_FIXEL_IMAGES
353 output_error_fixel_images (prefix + "_diff_fixel.msf", prefix + "_cost_fixel.msf");
354#endif
355 output_scatterplot (prefix + "_scatterplot.csv");
356 output_fixel_count_image (prefix + "_fixel_count.mif");
357 output_untracked_fixels (prefix + "_untracked_count.mif", prefix + "_untracked_amps.mif");
358 }
359
360
361
362
363 }
364 }
365 }
366}
367
368
369#endif
float amp
Definition: calibrator.h:61
const DWI::Directions::FastLookupSet & dirs
Definition: fixel_td_map.h:59
size_t dixel2fixel(const Dixel &) const
Definition: fixel_td_map.h:82
Fixel_TD_map(const Header &H, const DWI::Directions::FastLookupSet &directions)
Definition: fixel_td_map.h:46
A class to read streamlines data.
Definition: file.h:63
default_type get_cost_unweighted(const default_type mu) const
Definition: model_base.h:110
void output_tdi_fixel(const std::string &) const
Definition: output.h:192
void output_all_debug_images(const std::string &) const
Definition: model_base.h:333
ModelBase(Image< float > &dwi, const DWI::Directions::FastLookupSet &dirs)
Definition: model_base.h:132
ModelBase(const ModelBase &)=delete
void output_target_image_fixel(const std::string &) const
Definition: output.h:98
void output_5tt_image(const std::string &)
Definition: model_base.h:322
void output_untracked_fixels(const std::string &, const std::string &) const
Definition: output.h:299
void output_target_image_sh(const std::string &) const
Definition: output.h:66
default_type calc_cost_function() const
Definition: model_base.h:303
void output_target_image(const std::string &) const
Definition: output.h:49
void output_error_images(const std::string &, const std::string &, const std::string &) const
Definition: output.h:216
void output_scatterplot(const std::string &) const
Definition: output.h:272
void output_proc_mask(const std::string &)
Definition: model_base.h:315
virtual bool operator()(const FMLS::FOD_lobes &in)
Definition: model_base.h:261
void output_tdi_null_lobes(const std::string &) const
Definition: output.h:139
void output_fixel_count_image(const std::string &) const
Definition: output.h:284
void output_tdi_sh(const std::string &) const
Definition: output.h:159
void output_tdi(const std::string &) const
Definition: output.h:121
void perform_FOD_segmentation(Image< float > &)
Definition: model_base.h:194
void output_error_fixel_images(const std::string &, const std::string &) const
Definition: output.h:244
void map_streamlines(const std::string &)
Definition: model_base.h:234
bool valid() const
Definition: image.h:56
ssize_t size(size_t axis) const
Definition: image.h:66
#define INFO(msg)
Definition: exception.h:74
constexpr T pow2(const T &v)
Definition: math.h:53
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
void check(const ImageType &H)
convenience function to check if an input image can contain SH coefficients
Definition: SH.h:745
size_t LforN(int N)
returns the largest lmax given N parameters
Definition: SH.h:70
__Multi< typename std::remove_reference< Functor >::type > multi(Functor &&functor, size_t nthreads=threads_to_execute())
used to request multiple threads of the corresponding functor
Definition: thread.h:285
void run_queue(Source &&source, const Item &item, Sink &&sink, size_t capacity=128)
convenience function to set up and run a 2-stage multi-threaded pipeline.
__Batch< Item > batch(const Item &, size_t number=128)
used to request batched processing of items
Definition: thread_queue.h:858
const vector< ParsedOption > get_options(const std::string &name)
return all command-line options matching name
size_t determine_upsample_ratio(const Header &, const float, const float)
void initialise_processing_mask(Image< float > &, Image< float > &, Image< float > &)
unsigned int track_t
Definition: types.h:34
PointType::Scalar length(const vector< PointType > &tck)
Definition: streamline.h:134
std::string basename(const std::string &name)
Definition: path.h:60
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
std::enable_if< is_adapter_type< typenamestd::remove_reference< ImageType >::type >::value, std::string >::type save(ImageType &&x, const std::string &filename, bool use_multi_threading=true)
save contents of an existing image to file (for debugging only)
Definition: image.h:523
InputImageType dwi
#define MEMALIGN(...)
Definition: types.h:185