Developer documentation
Version 3.0.3-105-gd3941f44
histogram.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 __algo_histogram_h__
18#define __algo_histogram_h__
19
20#include <cmath>
21
22#include "image_helpers.h"
23#include "types.h"
24#include "adapter/replicate.h"
25#include "algo/loop.h"
26
27namespace MR
28{
29 namespace Algo
30 {
31 namespace Histogram
32 {
33
34
35 extern const App::OptionGroup Options;
36
37
39 { MEMALIGN (Calibrator)
40
41 public:
42 Calibrator (const size_t number_of_bins = 0, const bool ignorezero = false) :
43 min (std::numeric_limits<default_type>::infinity()),
44 max (-std::numeric_limits<default_type>::infinity()),
45 bin_width (NaN),
46 num_bins (number_of_bins),
47 ignore_zero (ignorezero) { }
48
49 template <typename value_type>
50 typename std::enable_if<std::is_arithmetic<value_type>::value, bool>::type operator() (const value_type val) {
51 if (std::isfinite(val) && !(ignore_zero && val == 0.0)) {
52 min = std::min (min, default_type(val));
53 max = std::max (max, default_type(val));
54 if (!num_bins)
55 data.push_back (default_type(val));
56 }
57 return true;
58 }
59
60 template <class T>
61 FORCE_INLINE typename std::enable_if<!std::is_arithmetic<T>::value, bool>::type operator() (const T& val) {
62 return (*this) (typename T::value_type (val));
63 }
64
65 void from_file (const std::string&);
66
67 void finalize (const size_t num_volumes, const bool is_integer);
68
69 default_type get_bin_centre (const size_t i) const {
70 assert (i < num_bins);
71 return get_min() + (get_bin_width() * (i + 0.5));
72 }
73
74 default_type get_bin_width() const { return bin_width; }
75 size_t get_num_bins() const { return num_bins; }
76 default_type get_min() const { return min; }
77 default_type get_max() const { return max; }
78 bool get_ignore_zero() const { return ignore_zero; }
79
80
81 private:
82 default_type min, max, bin_width;
83 size_t num_bins;
84 const bool ignore_zero;
86
87 default_type get_iqr();
88
89 };
90
91
92
93
94 class Data
95 { MEMALIGN (Data)
96 public:
97
98 using vector_type = Eigen::Array<size_t, Eigen::Dynamic, 1>;
99 using cdf_type = Eigen::Array<default_type, Eigen::Dynamic, 1>;
100
101 Data (const Calibrator& calibrate) :
102 info (calibrate),
103 list (vector_type::Zero (info.get_num_bins())) { }
104
105 template <typename value_type>
106 bool operator() (const value_type val) {
107 if (std::isfinite(val) && !(info.get_ignore_zero() && val == 0.0)) {
108 const size_t pos = bin (val);
109 if (pos != size_t(list.size()))
110 ++list[pos];
111 }
112 return true;
113 }
114
115 template <typename value_type>
116 size_t bin (const value_type val) const {
117 size_t pos = std::floor ((val - info.get_min()) / info.get_bin_width());
118 if (pos > size_t(list.size())) return size();
119 return pos;
120 }
121
122
123 size_t operator[] (const size_t index) const {
124 assert (index < size_t(list.size()));
125 return list[index];
126 }
127 size_t size() const {
128 return list.size();
129 }
130 const Calibrator& get_calibration() const { return info; }
131
132 const vector_type& pdf() const { return list; }
133 cdf_type cdf() const;
134
135 default_type first_min () const;
136
137 default_type entropy () const;
138
139 protected:
142 friend class Kernel;
143 };
144
145
146 // Convenience functions for calibrating (& histograming) basic input images
147 template <class ImageType>
148 void calibrate (Calibrator& result, ImageType& image)
149 {
150 for (auto l = Loop(image) (image); l; ++l)
151 result (image.value());
152 result.finalize (image.ndim() > 3 ? image.size(3) : 1, std::is_integral<typename ImageType::value_type>::value);
153 }
154
155 template <class ImageType, class MaskType>
156 void calibrate (Calibrator& result, ImageType& image, MaskType& mask)
157 {
158 if (!mask.valid()) {
159 calibrate (result, image);
160 return;
161 }
162 if (!dimensions_match (image, mask, 0, 3))
163 throw Exception ("Image and mask for histogram calibration do not match");
164 Adapter::Replicate<MaskType> mask_replicate (mask, image);
165 for (auto l = Loop(image) (image, mask_replicate); l; ++l) {
166 if (mask_replicate.value())
167 result (image.value());
168 }
169 result.finalize (image.ndim() > 3 ? image.size(3) : 1, std::is_integral<typename ImageType::value_type>::value);
170 }
171
172 template <class ImageType>
173 Data generate (ImageType& image, const size_t num_bins, const bool ignore_zero = false)
174 {
175 Calibrator calibrator (num_bins, ignore_zero);
176 calibrate (calibrator, image);
177 return generate (calibrator, image);
178 }
179
180 template <class ImageType, class MaskType>
181 Data generate (ImageType& image, MaskType& mask, const size_t num_bins, const bool ignore_zero = false)
182 {
183 Calibrator calibrator (num_bins, ignore_zero);
184 calibrate (calibrator, image, mask);
185 return generate (calibrator, image, mask);
186 }
187
188 template <class ImageType>
189 Data generate (const Calibrator& calibrator, ImageType& image)
190 {
191 Data result (calibrator);
192 for (auto l = Loop(image) (image); l; ++l)
193 result (typename ImageType::value_type (image.value()));
194 return result;
195 }
196
197 template <class ImageType, class MaskType>
198 Data generate (const Calibrator& calibrator, ImageType& image, MaskType& mask)
199 {
200 if (!mask.valid())
201 return generate (calibrator, image);
202 if (!dimensions_match (image, mask, 0, 3))
203 throw Exception ("Image and mask for histogram generation do not match");
204 Data result (calibrator);
205 Adapter::Replicate<MaskType> mask_replicate (mask, image);
206 for (auto l = Loop(image) (image, mask_replicate); l; ++l) {
207 if (mask_replicate.value())
208 result (typename ImageType::value_type (image.value()));
209 }
210 return result;
211 }
212
213
214
215
217 { MEMALIGN (Matcher)
218
219 using vector_type = Eigen::Array<default_type, Eigen::Dynamic, 1>;
220
221 public:
222 Matcher (const Data& input, const Data& target);
223
225
226 private:
227 const Calibrator calib_input, calib_target;
228 vector_type mapping;
229
230 };
231
232
233
234
235
236 }
237 }
238}
239
240#endif
const Calibrator info
Definition: histogram.h:140
Matcher(const Data &input, const Data &target)
default_type operator()(const default_type) const
a class to hold a named list of Option's
constexpr I floor(const T x)
template function with cast to different type
Definition: math.h:75
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
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
Data generate(ImageType &image, const size_t num_bins, const bool ignore_zero=false)
Definition: histogram.h:173
const App::OptionGroup Options
Definition: app.h:274
void calibrate(Calibrator &result, ImageType &image)
Definition: histogram.h:148
MR::default_type value_type
Definition: typedefs.h:33
Eigen::Array< value_type, Eigen::Dynamic, 1 > vector_type
Definition: typedefs.h:35
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
constexpr default_type NaN
Definition: types.h:230
size_t index
#define MEMALIGN(...)
Definition: types.h:185
#define FORCE_INLINE
Definition: types.h:156