Developer documentation
Version 3.0.3-105-gd3941f44
matrix.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
18#ifndef __fixel_matrix_h__
19#define __fixel_matrix_h__
20
21#include "image.h"
22#include "types.h"
23#include "file/ofstream.h"
25
26namespace MR
27{
28 namespace Fixel
29 {
30
31
32 namespace Matrix
33 {
34
35
36 using index_image_type = uint64_t;
37 using fixel_index_type = uint32_t;
38 using count_type = uint32_t;
40
41
42
43 // Classes for dealing with dynamic multi-threaded construction of the
44 // fixel-fixel connectivity matrix
47 public:
50 fixel_index (std::numeric_limits<fixel_index_type>::max()),
51 track_count (0) { }
52 InitElement (const fixel_index_type fixel_index) :
53 fixel_index (fixel_index),
54 track_count (1) { }
55 InitElement (const fixel_index_type fixel_index, const ValueType track_count) :
56 fixel_index (fixel_index),
57 track_count (track_count) { }
58 InitElement (const InitElement&) = default;
59 FORCE_INLINE InitElement& operator++() { track_count++; return *this; }
60 FORCE_INLINE InitElement& operator= (const InitElement& that) { fixel_index = that.fixel_index; track_count = that.track_count; return *this; }
61 FORCE_INLINE fixel_index_type index() const { return fixel_index; }
62 FORCE_INLINE ValueType value() const { return track_count; }
63 FORCE_INLINE bool operator< (const InitElement& that) const { return fixel_index < that.fixel_index; }
64 private:
65 fixel_index_type fixel_index;
66 ValueType track_count;
67 };
68
69
70
71 class InitFixel : public vector<InitElement>
73 public:
74 using ElementType = InitElement;
75 using BaseType = vector<InitElement>;
76 InitFixel() :
77 track_count (0) { }
78 void add (const vector<fixel_index_type>& indices);
79 count_type count() const { return track_count; }
80 private:
81 count_type track_count;
82 };
83
84
85
86
87 // A class to store fixel index / connectivity value pairs
88 // only after the connectivity matrix has been thresholded / normalised
91 public:
93 NormElement (const index_type fixel_index,
94 const ValueType connectivity_value) :
95 fixel_index (fixel_index),
96 connectivity_value (connectivity_value) { }
97 FORCE_INLINE index_type index() const { return fixel_index; }
98 FORCE_INLINE ValueType value() const { return connectivity_value; }
99 FORCE_INLINE void exponentiate (const ValueType C) { connectivity_value = std::pow (connectivity_value, C); }
100 FORCE_INLINE void normalise (const ValueType norm_factor) { connectivity_value *= norm_factor; }
101 private:
102 index_type fixel_index;
103 connectivity_value_type connectivity_value;
104 };
105
106
107
108
109 // With the internally normalised CFE expression, want to store a
110 // multiplicative factor per fixel
111 class NormFixel : public vector<NormElement>
113 public:
114 using ElementType = NormElement;
115 using BaseType = vector<NormElement>;
116 NormFixel() :
117 norm_multiplier (connectivity_value_type (1)) { }
118 NormFixel (const BaseType& i) :
119 BaseType (i),
120 norm_multiplier (connectivity_value_type (1)) { }
121 NormFixel (BaseType&& i) :
122 BaseType (std::move (i)),
123 norm_multiplier (connectivity_value_type (1)) { }
124 void normalise() {
125 norm_multiplier = connectivity_value_type (0);
126 for (const auto& c : *this)
127 norm_multiplier += c.value();
128 norm_multiplier = norm_multiplier ? (connectivity_value_type (1) / norm_multiplier) : connectivity_value_type(0);
129 }
130 void normalise (const connectivity_value_type sum) {
131 norm_multiplier = sum ? (connectivity_value_type(1) / sum) : connectivity_value_type(0);
132 }
133 connectivity_value_type norm_multiplier;
134 };
135
136
137
138
139
140
141 // Different types are used depending on whether the connectivity matrix
142 // is in the process of being built, or whether it has been normalised
143 // TODO Revise
145
146
147
148
149
150
151 // Generate a fixel-fixel connectivity matrix
153 const std::string& track_filename,
154 Image<fixel_index_type>& index_image,
155 Image<bool>& fixel_mask,
156 const float angular_threshold);
157
158
159
160
161
162
163 // New code for handling load/save of fixel-fixel connectivity matrix
164 // Use something akin to the fixel directory format, with a sub-directory
165 // within an existing fixel directory containing the following data:
166 // - index.mif: Similar to the index image in the fixel directory format,
167 // but has dimensions Nx1x1x2, where:
168 // - N is the number of fixels in the fixel template
169 // - The first volume contains the number of connected fixels for that fixel
170 // - The second volume contains the offset of the first connected fixel for that fixel
171 // - connectivity.mif: Floating-point image of dimension Cx1x1, where C is the total
172 // number of fixel-fixel connections stored in the entire matrix. Each value should be
173 // between 0.0 and 1.0, corresponding to the fraction of streamlines passing through
174 // the fixel that additionally pass through some other fixel.
175 // - fixel.mif: Unsigned integer image of dimension Cx1x1, where C is the total number of
176 // fixel-fixel connections stored in the entire matrix. Each value indexes the
177 // fixel to which the fixel-fixel connection refers.
178 //
179 // In order to avoid duplication of memory usage, the writing function should
180 // perform, for each fixel in turn:
181 // - Normalisation of the matrix
182 // - Writing to the three images
183 // - Erasing the memory used for that matrix in the initial building
184
186 const connectivity_value_type threshold,
187 const std::string& path,
188 const KeyValues& keyvals = KeyValues());
189
190
191
192 // Wrapper class for reading the connectivity matrix from the filesystem
193 class Reader
195
196 public:
197 Reader (const std::string& path, const Image<bool>& mask);
198 Reader (const std::string& path);
199
200 // TODO Entirely feasible to construct this thing using scratch storage;
201 // would need two passes over the pre-normalised data in order to calculate
202 // the number of fixel-fixel connections, but it could be done
203 //
204 // It would require restoration of the old Matrix::normalise() function,
205 // but modification to write out to scratch index / fixel / value images
206 // rather than "norm_matrix_type"
207 //
208 // This would permit usage of fixelcfestats with tractogram as input
209 //
210 // TODO Could pre-exponentiation of connectivity values be done beforehand using an mrcalc call?
211 // Expect fixelcfestats to be provided with a data file, from which it will find the
212 // index & fixel images
213
214 NormFixel operator[] (const size_t index) const;
215
216 // TODO Define iteration constructs?
217
218 size_t size() const { return index_image.size (0); }
219 size_t size (const size_t) const;
220
221 protected:
222 const std::string directory;
223 // Not to be manipulated directly; need to copy in order to ensure thread-safety
228
229
230 };
231
232
233
234 }
235 }
236}
237
238#endif
FORCE_INLINE bool operator<(const InitElement &that) const
Definition: matrix.h:63
FORCE_INLINE fixel_index_type index() const
Definition: matrix.h:61
FORCE_INLINE InitElement & operator=(const InitElement &that)
Definition: matrix.h:60
InitElement(const InitElement &)=default
InitElement(const fixel_index_type fixel_index, const ValueType track_count)
Definition: matrix.h:55
InitElement(const fixel_index_type fixel_index)
Definition: matrix.h:52
FORCE_INLINE ValueType value() const
Definition: matrix.h:62
fixel_index_type ValueType
Definition: matrix.h:48
FORCE_INLINE InitElement & operator++()
Definition: matrix.h:59
FORCE_INLINE index_type index() const
Definition: matrix.h:97
FORCE_INLINE void normalise(const ValueType norm_factor)
Definition: matrix.h:100
FORCE_INLINE ValueType value() const
Definition: matrix.h:98
connectivity_value_type ValueType
Definition: matrix.h:92
NormElement(const index_type fixel_index, const ValueType connectivity_value)
Definition: matrix.h:93
FORCE_INLINE void exponentiate(const ValueType C)
Definition: matrix.h:99
Image< connectivity_value_type > value_image
Definition: matrix.h:226
Image< fixel_index_type > fixel_image
Definition: matrix.h:225
Image< bool > mask_image
Definition: matrix.h:227
const std::string directory
Definition: matrix.h:222
Image< index_image_type > index_image
Definition: matrix.h:224
ssize_t size(size_t axis) const
Definition: image.h:66
Matrix(const MR::Helper::ConstRow< ImageType > &row)
Definition: matrix.h:17
#define NOMEMALIGN
Definition: memory.h:22
void normalise_and_write(init_matrix_type &matrix, const connectivity_value_type threshold, const std::string &path, const KeyValues &keyvals=KeyValues())
float connectivity_value_type
Definition: matrix.h:39
uint64_t index_image_type
Definition: matrix.h:36
uint32_t count_type
Definition: matrix.h:38
init_matrix_type generate(const std::string &track_filename, Image< fixel_index_type > &index_image, Image< bool > &fixel_mask, const float angular_threshold)
uint32_t fixel_index_type
Definition: matrix.h:37
uint32_t index_type
Definition: types.h:25
Definition: base.h:24
std::map< std::string, std::string > KeyValues
used in various places for storing key-value pairs
Definition: types.h:238
Definition: types.h:303
size_t index
#define MEMALIGN(...)
Definition: types.h:185
#define FORCE_INLINE
Definition: types.h:156