Developer documentation
Version 3.0.3-105-gd3941f44
stats.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 __stats_h_
18#define __stats_h_
19
20
21#include "app.h"
22#include "file/ofstream.h"
23#include "math/median.h"
24
25
26namespace MR
27{
28
29 namespace Stats
30 {
31
32 extern const char * field_choices[];
33 extern const App::OptionGroup Options;
34
37
38
40 public:
41 Stats (const bool is_complex = false, const bool ignorezero = false) :
42 mean (0.0, 0.0),
43 delta (0.0, 0.0),
44 delta2 (0.0, 0.0),
45 m2 (0.0, 0.0),
46 std (0.0, 0.0),
47 std_rv (0.0, 0.0),
48 min (INFINITY, INFINITY),
49 max (-INFINITY, -INFINITY),
50 count (0),
52 ignore_zero (ignorezero) { }
53
54
56 if (std::isfinite (val.real()) && std::isfinite (val.imag()) && !(ignore_zero && val.real() == 0.0 && val.imag() == 0.0)) {
57 if (min.real() > val.real()) min = complex_type (val.real(), min.imag());
58 if (min.imag() > val.imag()) min = complex_type (min.real(), val.imag());
59 if (max.real() < val.real()) max = complex_type (val.real(), max.imag());
60 if (max.imag() < val.imag()) max = complex_type (max.real(), val.imag());
61 count++;
62 // Welford's online algorithm for variance calculation:
63 delta = val - mean;
64 mean += cdouble(delta.real() / count, delta.imag() / count);
65 delta2 = val - mean;
66 m2 += cdouble(delta.real() * delta2.real(), delta.imag() * delta2.imag());
67 if (!is_complex)
68 values.push_back(val.real());
69 }
70 }
71
72 template <class ImageType> void print (ImageType& ima, const vector<std::string>& fields) {
73
74 if (count > 1) {
75 std = complex_type(sqrt (m2.real() / value_type (count - 1)), sqrt (m2.imag() / value_type (count - 1)));
76 std_rv = complex_type(sqrt((m2.real() + m2.imag()) / value_type (count - 1)));
77 std::sort (values.begin(), values.end());
78 }
79 if (fields.size()) {
80 if (!count) {
81 if (fields.size() == 1 && fields.front() == "count") {
82 std::cout << "0\n";
83 return;
84 } else {
85 throw Exception ("Cannot output statistic of interest; no values read (empty mask?)");
86 }
87 }
88 for (size_t n = 0; n < fields.size(); ++n) {
89 if (fields[n] == "mean") std::cout << str(mean) << " ";
90 else if (fields[n] == "median") std::cout << ( values.size() > 0 ? str(Math::median (values)) : "N/A" ) << " ";
91 else if (fields[n] == "std") std::cout << ( count > 1 ? str(std) : "N/A" ) << " ";
92 else if (fields[n] == "std_rv") std::cout << ( count > 1 ? str(std_rv) : "N/A" ) << " ";
93 else if (fields[n] == "min") std::cout << str(min) << " ";
94 else if (fields[n] == "max") std::cout << str(max) << " ";
95 else if (fields[n] == "count") std::cout << count << " ";
96 else throw Exception("stats type not supported: " + fields[n]);
97 }
98 std::cout << "\n";
99
100 }
101 else {
102
103 std::string s = "[ ";
104 if (ima.ndim() > 3)
105 for (size_t n = 3; n < ima.ndim(); n++)
106 s += str (ima.index(n)) + " ";
107 else
108 s += "0 ";
109 s += "]";
110
111 int width = is_complex ? 20 : 10;
112 std::cout << std::setw(12) << std::right << s << " ";
113
114 std::cout << std::setw(width) << std::right << ( count ? str(mean) : "N/A" );
115
116 if (!is_complex) {
117 std::cout << " " << std::setw(width) << std::right;
118 if (count)
119 std::cout << Math::median (values);
120 else
121 std::cout << "N/A";
122 }
123 std::cout << " " << std::setw(width) << std::right << ( count > 1 ? str(std) : "N/A" )
124 << " " << std::setw(width) << std::right << ( count ? str(min) : "N/A" )
125 << " " << std::setw(width) << std::right << ( count ? str(max) : "N/A" )
126 << " " << std::setw(10) << std::right << count << "\n";
127 }
128
129 }
130
131 private:
132 complex_type mean, delta, delta2, m2, std, std_rv, min, max;
133 size_t count;
134 const bool is_complex, ignore_zero;
135 vector<float> values;
136 };
137
138
139
140 inline void print_header (bool is_complex)
141 {
142 int width = is_complex ? 20 : 10;
143 std::cout << std::setw(12) << std::right << "volume"
144 << " " << std::setw(width) << std::right << "mean";
145 if (!is_complex)
146 std::cout << " " << std::setw(width) << std::right << "median";
147 std::cout << " " << std::setw(width) << std::right << "std"
148 << " " << std::setw(width) << std::right << "min"
149 << " " << std::setw(width) << std::right << "max"
150 << " " << std::setw(10) << std::right << "count" << "\n";
151 }
152
153 }
154
155}
156
157
158
159#endif
160
a class to hold a named list of Option's
Stats(const bool is_complex=false, const bool ignorezero=false)
Definition: stats.h:41
void operator()(complex_type val)
Definition: stats.h:55
void print(ImageType &ima, const vector< std::string > &fields)
Definition: stats.h:72
#define NOMEMALIGN
Definition: memory.h:22
Container::value_type median(Container &list)
Definition: median.h:45
default_type value_type
Definition: stats.h:35
void print_header(bool is_complex)
Definition: stats.h:140
const char * field_choices[]
cdouble complex_type
Definition: stats.h:36
const App::OptionGroup Options
Definition: app.h:274
Definition: base.h:24
std::complex< double > cdouble
Definition: types.h:217
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
Definition: types.h:303
check whether type is complex:
Definition: types.h:242