Developer documentation
Version 3.0.3-105-gd3941f44
output.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_output_h__
18#define __dwi_tractography_sift_output_h__
19
20
21#include "image.h"
22#include "header.h"
23
24#include "algo/loop.h"
25
26#include "dwi/fixel_map.h"
28
29#include "file/ofstream.h"
30
31#include "math/SH.h"
32
34#include "fixel/legacy/image.h"
35#include "fixel/legacy/keys.h"
36
37
38namespace MR
39{
40 namespace DWI
41 {
42 namespace Tractography
43 {
44 namespace SIFT
45 {
46
47 // Output functions - non-essential, mostly debugging outputs
48 template <class Fixel>
49 void ModelBase<Fixel>::output_target_image (const std::string& path) const
50 {
52 VoxelAccessor v (accessor());
53 for (auto l = Loop(out) (out, v); l; ++l) {
54 if (v.value()) {
55 default_type value = 0.0;
56 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i)
57 value += i().get_FOD();
58 out.value() = value;
59 } else {
60 out.value() = NAN;
61 }
62 }
63 }
64
65 template <class Fixel>
66 void ModelBase<Fixel>::output_target_image_sh (const std::string& path) const
67 {
68 const size_t L = 8;
69 const size_t N = Math::SH::NforL (L);
72 H_sh.ndim() = 4;
73 H_sh.size(3) = N;
74 H_sh.stride (3) = 0;
75 auto out = Image<float>::create (path, H_sh);
76 VoxelAccessor v (accessor());
77 for (auto l = Loop (0, 3) (out, v); l; ++l) {
78 if (v.value()) {
79 Eigen::Matrix<default_type, Eigen::Dynamic, 1> sum = Eigen::Matrix<default_type, Eigen::Dynamic, 1>::Zero (N);
80 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i) {
81 if (i().get_FOD()) {
82 Eigen::Matrix<default_type, Eigen::Dynamic, 1> this_lobe;
83 aPSF (this_lobe, i().get_dir());
84 for (size_t c = 0; c != N; ++c)
85 sum[c] += i().get_FOD() * this_lobe[c];
86 }
87 }
88 for (auto l = Loop (3) (out); l; ++l)
89 out.value() = sum[out.index(3)];
90 } else {
91 for (auto l = Loop (3) (out); l; ++l)
92 out.value() = NAN;
93 }
94 }
95 }
96
97 template <class Fixel>
98 void ModelBase<Fixel>::output_target_image_fixel (const std::string& path) const
99 {
102 H_fixel.datatype() = DataType::UInt64;
103 H_fixel.datatype().set_byte_order_native();
104 H_fixel.keyval()[MR::Fixel::Legacy::name_key] = str(typeid(FixelMetric).name());
105 H_fixel.keyval()[MR::Fixel::Legacy::size_key] = str(sizeof(FixelMetric));
106 MR::Fixel::Legacy::Image<FixelMetric> out (path, H_fixel);
107 VoxelAccessor v (accessor());
108 for (auto l = Loop (out) (out, v); l; ++l) {
109 if (v.value()) {
110 out.value().set_size ((*v.value()).num_fixels());
111 size_t index = 0;
112 for (typename Fixel_map<Fixel>::ConstIterator iter = begin (v); iter; ++iter, ++index) {
113 FixelMetric fixel (iter().get_dir().template cast<float>(), iter().get_FOD(), iter().get_FOD());
114 out.value()[index] = fixel;
115 }
116 }
117 }
118 }
119
120 template <class Fixel>
121 void ModelBase<Fixel>::output_tdi (const std::string& path) const
122 {
123 const default_type current_mu = mu();
125 VoxelAccessor v (accessor());
126 for (auto l = Loop (out) (out, v); l; ++l) {
127 if (v.value()) {
128 default_type value = 0.0;
129 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i)
130 value += i().get_TD();
131 out.value() = value * current_mu;
132 } else {
133 out.value() = NaN;
134 }
135 }
136 }
137
138 template <class Fixel>
139 void ModelBase<Fixel>::output_tdi_null_lobes (const std::string& path) const
140 {
141 const default_type current_mu = mu();
143 VoxelAccessor v (accessor());
144 for (auto l = Loop (out) (out, v); l; ++l) {
145 if (v.value()) {
146 default_type value = 0.0;
147 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i) {
148 if (!i().get_FOD())
149 value += i().get_TD();
150 }
151 out.value() = value * current_mu;
152 } else {
153 out.value() = NaN;
154 }
155 }
156 }
157
158 template <class Fixel>
159 void ModelBase<Fixel>::output_tdi_sh (const std::string& path) const
160 {
161 const default_type current_mu = mu();
162 const size_t L = 8;
163 const size_t N = Math::SH::NforL (L);
166 H_sh.ndim() = 4;
167 H_sh.size(3) = N;
168 H_sh.stride (3) = 0;
169 auto out = Image<float>::create (path, H_sh);
170 VoxelAccessor v (accessor());
171 for (auto l = Loop (v) (out, v); l; ++l) {
172 if (v.value()) {
173 Eigen::Matrix<default_type, Eigen::Dynamic, 1> sum = Eigen::Matrix<default_type, Eigen::Dynamic, 1>::Zero (N);
174 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i) {
175 if (i().get_FOD()) {
176 Eigen::Matrix<default_type, Eigen::Dynamic, 1> this_lobe;
177 aPSF (this_lobe, i().get_dir());
178 for (size_t c = 0; c != N; ++c)
179 sum[c] += i().get_TD() * this_lobe[c];
181 for (auto l = Loop (3) (out); l; ++l)
182 out.value() = sum[out.index(3)] * current_mu;
184 } else {
185 for (auto l = Loop (3) (out); l; ++l)
186 out.value() = NaN;
187 }
188 }
189 }
190
191 template <class Fixel>
192 void ModelBase<Fixel>::output_tdi_fixel (const std::string& path) const
193 {
195 const default_type current_mu = mu();
197 H_fixel.datatype() = DataType::UInt64;
198 H_fixel.datatype().set_byte_order_native();
199 H_fixel.keyval()[MR::Fixel::Legacy::name_key] = str(typeid(FixelMetric).name());
200 H_fixel.keyval()[MR::Fixel::Legacy::size_key] = str(sizeof(FixelMetric));
201 MR::Fixel::Legacy::Image<FixelMetric> out (path, H_fixel);
202 VoxelAccessor v (accessor());
203 for (auto l = Loop (out) (out, v); l; ++l) {
204 if (v.value()) {
205 out.value().set_size ((*v.value()).num_fixels());
206 size_t index = 0;
207 for (typename Fixel_map<Fixel>::ConstIterator iter = begin (v); iter; ++iter, ++index) {
208 FixelMetric fixel (iter().get_dir().template cast<float>(), iter().get_FOD(), current_mu * iter().get_TD());
209 out.value()[index] = fixel;
210 }
211 }
212 }
213 }
214
215 template <class Fixel>
216 void ModelBase<Fixel>::output_error_images (const std::string& max_abs_diff_path, const std::string& diff_path, const std::string& cost_path) const
217 {
218 const default_type current_mu = mu();
219 auto out_max_abs_diff = Image<float>::create (max_abs_diff_path, Fixel_map<Fixel>::header());
220 auto out_diff = Image<float>::create (diff_path, Fixel_map<Fixel>::header());
221 auto out_cost = Image<float>::create (cost_path, Fixel_map<Fixel>::header());
222 VoxelAccessor v (accessor());
223 for (auto l = Loop (v) (v, out_max_abs_diff, out_diff, out_cost); l; ++l) {
224 if (v.value()) {
225 default_type max_abs_diff = 0.0, diff = 0.0, cost = 0.0;
226 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i) {
227 const default_type this_diff = i().get_diff (current_mu);
228 max_abs_diff = std::max (max_abs_diff, abs (this_diff));
229 diff += this_diff;
230 cost += i().get_cost (current_mu) * i().get_weight();
231 }
232 out_max_abs_diff.value() = max_abs_diff;
233 out_diff.value() = diff;
234 out_cost.value() = cost;
235 } else {
236 out_max_abs_diff.value() = NaN;
237 out_diff.value() = NaN;
238 out_cost.value() = NaN;
239 }
240 }
241 }
242
243 template <class Fixel>
244 void ModelBase<Fixel>::output_error_fixel_images (const std::string& diff_path, const std::string& cost_path) const
245 {
247 const default_type current_mu = mu();
249 H_fixel.datatype() = DataType::UInt64;
250 H_fixel.datatype().set_byte_order_native();
251 H_fixel.keyval()[MR::Fixel::Legacy::name_key] = str(typeid(FixelMetric).name());
252 H_fixel.keyval()[MR::Fixel::Legacy::size_key] = str(sizeof(FixelMetric));
253 MR::Fixel::Legacy::Image<FixelMetric> out_diff (diff_path, H_fixel);
254 MR::Fixel::Legacy::Image<FixelMetric> out_cost (cost_path, H_fixel);
255 VoxelAccessor v (accessor());
256 for (auto l = Loop (v) (v, out_diff, out_cost); l; ++l) {
257 if (v.value()) {
258 out_diff.value().set_size ((*v.value()).num_fixels());
259 out_cost.value().set_size ((*v.value()).num_fixels());
260 size_t index = 0;
261 for (typename Fixel_map<Fixel>::ConstIterator iter = begin (v); iter; ++iter, ++index) {
262 FixelMetric fixel_diff (iter().get_dir().template cast<float>(), iter().get_FOD(), iter().get_diff (current_mu));
263 out_diff.value()[index] = fixel_diff;
264 FixelMetric fixel_cost (iter().get_dir().template cast<float>(), iter().get_FOD(), iter().get_cost (current_mu));
265 out_cost.value()[index] = fixel_cost;
266 }
267 }
268 }
269 }
270
271 template <class Fixel>
272 void ModelBase<Fixel>::output_scatterplot (const std::string& path) const
273 {
274 File::OFStream out (path, std::ios_base::out | std::ios_base::trunc);
275 out << "# " << App::command_history_string << "\n";
276 const default_type current_mu = mu();
277 out << "#Fibre density,Track density (unscaled),Track density (scaled),Weight,\n";
278 for (typename vector<Fixel>::const_iterator i = fixels.begin(); i != fixels.end(); ++i)
279 out << str (i->get_FOD()) << "," << str (i->get_TD()) << "," << str (i->get_TD() * current_mu) << "," << str (i->get_weight()) << ",\n";
280 out.close();
281 }
282
283 template <class Fixel>
284 void ModelBase<Fixel>::output_fixel_count_image (const std::string& path) const
285 {
287 H_out.datatype() = DataType::UInt8;
288 auto out = Image<uint8_t>::create (path, H_out);
289 VoxelAccessor v (accessor());
290 for (auto l = Loop (v) (v, out); l; ++l) {
291 if (v.value())
292 out.value() = (*v.value()).num_fixels();
293 else
294 out.value() = 0;
295 }
296 }
297
298 template <class Fixel>
299 void ModelBase<Fixel>::output_untracked_fixels (const std::string& path_count, const std::string& path_amps) const
300 {
301 Header H_uint8_t (Fixel_map<Fixel>::header());
302 H_uint8_t.datatype() = DataType::UInt8;
303 auto out_count = Image<uint8_t>::create (path_count, H_uint8_t);
304 auto out_amps = Image<float>::create (path_amps, Fixel_map<Fixel>::header());
305 VoxelAccessor v (accessor());
306 for (auto l = Loop (v) (v, out_count, out_amps, v); l; ++l) {
307 if (v.value()) {
308 uint8_t count = 0;
309 default_type sum = 0.0;
310 for (typename Fixel_map<Fixel>::ConstIterator i = begin (v); i; ++i) {
311 if (!i().get_TD()) {
312 ++count;
313 sum += i().get_FOD();
314 }
315 }
316 out_count.value() = count;
317 out_amps .value() = sum;
318 } else {
319 out_count.value() = 0;
320 out_amps .value() = NaN;
321 }
322 }
323 }
324
325
326
327 }
328 }
329 }
330}
331
332
333#endif
334
335
void output_tdi_fixel(const std::string &) const
Definition: output.h:192
void output_target_image_fixel(const std::string &) const
Definition: output.h:98
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
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_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 output_error_fixel_images(const std::string &, const std::string &) const
Definition: output.h:244
static constexpr uint8_t UInt64
Definition: datatype.h:146
static constexpr uint8_t UInt8
Definition: datatype.h:143
open output files for writing, checking for pre-existing file if necessary
Definition: ofstream.h:39
static Image create(const std::string &image_name, const Header &template_header, bool add_to_command_history=true)
Definition: image.h:192
a class to hold the coefficients for an apodised point-spread function.
Definition: SH.h:653
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
size_t NforL(int lmax)
the number of (even-degree) coefficients for the given value of lmax
Definition: SH.h:46
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Definition: SH.h:233
std::string command_history_string
const std::string size_key("sparse_data_size")
const std::string name_key("sparse_data_name")
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
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247
constexpr default_type NaN
Definition: types.h:230
size_t index
const std::string name
Definition: thread.h:108