Developer documentation
Version 3.0.3-105-gd3941f44
header.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 __header_h__
18#define __header_h__
19
20#include <map>
21#include <functional>
22
23#include "app.h"
24#include "debug.h"
25#include "types.h"
26#include "memory.h"
27#include "datatype.h"
28#include "stride.h"
29#include "file/mmap.h"
30#include "image_helpers.h"
31#include "image_io/base.h"
32
33
34namespace MR
35{
36
41 // @{
42
44
45
46 template <typename ValueType> class Image;
47
49 public:
50
52 class Axis { NOMEMALIGN
53 public:
54 Axis () noexcept : size (1), spacing (std::numeric_limits<default_type>::quiet_NaN()), stride (0) { }
55 ssize_t size;
56 default_type spacing;
57 ssize_t stride;
58 };
59
60 Header () :
61 transform_ (Eigen::Matrix<default_type,3,4>::Constant (NaN)),
62 format_ (nullptr),
63 offset_ (0.0),
64 scale_ (1.0),
65 realign_perm_ {{0, 1, 2}},
66 realign_flip_ {{false, false, false}} {}
67
68 explicit Header (Header&& H) noexcept :
69 axes_ (std::move (H.axes_)),
70 transform_ (std::move (H.transform_)),
71 name_ (std::move (H.name_)),
72 keyval_ (std::move (H.keyval_)),
73 format_ (H.format_),
74 io (std::move (H.io)),
75 datatype_ (std::move (H.datatype_)),
76 offset_ (H.offset_),
77 scale_ (H.scale_),
78 realign_perm_ {{0, 1, 2}},
79 realign_flip_ {{false, false, false}} {}
80
81 Header& operator= (Header&& H) noexcept {
82 axes_ = std::move (H.axes_);
83 transform_ = std::move (H.transform_);
84 name_ = std::move (H.name_);
85 keyval_ = std::move (H.keyval_);
86 format_ = H.format_;
87 io = std::move (H.io);
88 datatype_ = std::move (H.datatype_);
89 offset_ = H.offset_;
90 scale_ = H.scale_;
91 realign_perm_ = H.realign_perm_;
92 realign_flip_ = H.realign_flip_;
93 return *this;
94 }
95
97
99 Header (const Header& H) :
100 axes_ (H.axes_),
101 transform_ (H.transform_),
102 name_ (H.name_),
103 keyval_ (H.keyval_),
104 format_ (H.format_),
105 datatype_ (H.datatype_),
106 offset_ (datatype().is_integer() ? H.offset_ : 0.0),
107 scale_ (datatype().is_integer() ? H.scale_ : 1.0),
108 realign_perm_ (H.realign_perm_),
109 realign_flip_ (H.realign_flip_) { }
110
112
114 Header (const HeaderType& original) :
115 Header (static_cast<const Header&> (original)) { }
116
118
120 Header (const HeaderType& original) :
121 transform_ (original.transform()),
122 name_ (original.name()),
123 keyval_ (original.keyval()),
124 format_ (nullptr),
125 datatype_ (DataType::from<typename HeaderType::value_type>()),
126 offset_ (0.0),
127 scale_ (1.0),
128 realign_perm_ {{0, 1, 2}},
129 realign_flip_ {{false, false, false}} {
130 axes_.resize (original.ndim());
131 for (size_t n = 0; n < original.ndim(); ++n) {
132 size(n) = original.size(n);
133 stride(n) = original.stride(n);
134 spacing(n) = original.spacing(n);
135 }
136 }
137
138
140
142 Header& operator= (const Header& H) {
143 axes_ = H.axes_;
144 transform_ = H.transform_;
145 name_ = H.name_;
146 keyval_ = H.keyval_;
147 format_ = H.format_;
148 datatype_ = H.datatype_;
149 offset_ = datatype().is_integer() ? H.offset_ : 0.0;
150 scale_ = datatype().is_integer() ? H.scale_ : 1.0;
151 realign_perm_ = H.realign_perm_;
152 realign_flip_ = H.realign_flip_;
153 io.reset();
154 return *this;
155 }
156
158
160 Header& operator= (const HeaderType& original) {
161 return operator= (static_cast<const Header&> (original));
162 }
163
165
167 Header& operator= (const HeaderType& original) {
168 axes_.resize (original.ndim());
169 for (size_t n = 0; n < original.ndim(); ++n) {
170 size(n) = original.size(n);
171 stride(n) = original.stride(n);
172 spacing(n) = original.spacing(n);
173 }
174 transform_ = original.transform();
175 name_ = original.name();
176 keyval_ = original.keyval();
177 format_ = nullptr;
178 datatype_ = DataType::from<typename HeaderType::value_type>();
179 offset_ = 0.0;
180 scale_ = 1.0;
181 realign_perm_ = {{0, 1, 2}};
182 realign_flip_ = {{false, false, false}};
183 io.reset();
184 return *this;
185 }
186
187 ~Header () {
188 if (io) {
189 try { io->close (*this); }
190 catch (Exception& E) {
191 E.display();
192 }
193 }
194 }
195
196 bool valid () const { return bool (io); }
197 bool operator! () const { return !valid(); }
198
200 const std::string& name () const { return name_; }
202 std::string& name () { return name_; }
203
205 const char* format () const { return format_; }
206
208 const transform_type& transform () const { return transform_; }
210 transform_type& transform () { return transform_; }
211
213 void realignment (std::array<size_t, 3>& perm, std::array<bool, 3>& flip) const { perm = realign_perm_; flip = realign_flip_; }
214
215 class NDimProxy { NOMEMALIGN
216 public:
217 NDimProxy (vector<Axis>& axes) : axes (axes) { }
218 NDimProxy (NDimProxy&&) = default;
219 NDimProxy (const NDimProxy&) = delete;
220 NDimProxy& operator=(NDimProxy&&) = delete;
221 NDimProxy& operator=(const NDimProxy&) = delete;
222
223 operator size_t () const { return axes.size(); }
224 size_t operator= (size_t new_size) { axes.resize (new_size); return new_size; }
225 friend std::ostream& operator<< (std::ostream& stream, const NDimProxy& proxy) {
226 stream << proxy.axes.size();
227 return stream;
228 }
229 private:
230 vector<Axis>& axes;
231 };
232
234 size_t ndim () const { return axes_.size(); }
236 NDimProxy ndim () { return { axes_ }; }
237
239 const ssize_t& size (size_t axis) const;
241 ssize_t& size (size_t axis);
242
244 const default_type& spacing (size_t axis) const;
246 default_type& spacing (size_t axis);
247
249 const ssize_t& stride (size_t axis) const;
251 ssize_t& stride (size_t axis);
252
253 class DataTypeProxy : public DataType { NOMEMALIGN
254 public:
255 DataTypeProxy (Header& H) : DataType (H.datatype_), H (H) { }
256 DataTypeProxy (DataTypeProxy&&) = default;
257 DataTypeProxy (const DataTypeProxy&) = delete;
258 DataTypeProxy& operator=(DataTypeProxy&&) = delete;
259 DataTypeProxy& operator=(const DataTypeProxy&) = delete;
260
261 uint8_t operator()() const { return DataType::operator()(); }
262 const DataType& operator= (const DataType& DT) { DataType::operator= (DT); set(); return *this; }
263 void set_flag (uint8_t flag) { DataType::set_flag (flag); set(); }
264 void unset_flag (uint8_t flag) { DataType::unset_flag (flag); set(); }
265 void set_byte_order_native () { DataType::set_byte_order_native(); set(); }
266 private:
267 Header& H;
268 void set () {
269 H.datatype_ = dt;
270 if (!is_integer())
271 H.reset_intensity_scaling();
272 }
273 };
274
276 DataTypeProxy datatype () { return { *this }; }
278 DataType datatype () const { return datatype_; }
279
281 default_type intensity_offset () const { return offset_; }
283 default_type& intensity_offset () { return offset_; }
285 default_type intensity_scale () const { return scale_; }
287 default_type& intensity_scale () { return scale_; }
288
290 void apply_intensity_scaling (default_type scaling, default_type bias = 0.0) {
291 scale_ *= scaling;
292 offset_ = scaling * offset_ + bias;
293 set_intensity_scaling (scale_, offset_);
294 }
296 void set_intensity_scaling (default_type scaling = 1.0, default_type bias = 0.0) {
297 if (!std::isfinite (scaling) || !std::isfinite (bias) || scaling == 0.0)
298 WARN ("invalid scaling parameters (offset: " + str(bias) + ", scale: " + str(scaling) + ")");
299 scale_ = scaling;
300 offset_ = bias;
301 }
303 void set_intensity_scaling (const Header& H) { set_intensity_scaling (H.intensity_scale(), H.intensity_offset()); }
305 void reset_intensity_scaling () { set_intensity_scaling (); }
306
307 bool is_file_backed () const { return valid() ? io->is_file_backed() : false; }
308
310 void sanitise () {
311 DEBUG ("sanitising image information...");
315 }
316
318
337 template <typename ValueType>
338 Image<ValueType> get_image (bool read_write_if_existing = false);
339
341 const KeyValues& keyval () const { return keyval_; }
343 KeyValues& keyval () { return keyval_; }
345 void merge_keyval (const Header& H);
346
347 static Header open (const std::string& image_name);
348 static Header create (const std::string& image_name, const Header& template_header, bool add_to_command_history = true);
349 static Header scratch (const Header& template_header, const std::string& label = "scratch image");
350
353 static bool do_realign_transform;
354
356 std::string description (bool print_all = false) const;
358 friend std::ostream& operator<< (std::ostream& stream, const Header& H);
359
360 protected:
363 std::string name_;
365 const char* format_;
366
368 std::unique_ptr<ImageIO::Base> io;
373
374
375 void acquire_io (Header& H) { io = std::move (H.io); }
376 void check (const Header& H) const;
377
382 std::array<size_t, 3> realign_perm_;
383 std::array<bool, 3> realign_flip_;
384
388 Stride::sanitise (*this);
389 Stride::actualise (*this);
390 }
391 };
392
394
395
396
397
398 // Can't be a static member function due to memory alignment requirements of vector<>
399 Header concatenate (const vector<Header>& headers, const size_t axis, const bool permit_datatype_mismatch);
400
401
402
403
404
405
406
407 inline const ssize_t& Header::size (size_t axis) const { return axes_[axis].size; }
408 inline ssize_t& Header::size (size_t axis) { return axes_[axis].size; }
409
410 inline const default_type& Header::spacing (size_t axis) const { return axes_[axis].spacing; }
411 inline default_type& Header::spacing (size_t axis) { return axes_[axis].spacing; }
412
413 inline const ssize_t& Header::stride (size_t axis) const { return axes_[axis].stride; }
414 inline ssize_t& Header::stride (size_t axis) { return axes_[axis].stride; }
415
417}
418
419#endif
420
Array & operator=(const MR::Helper::ConstRow< ImageType > &row)
Definition: array.h:25
DataType & operator=(const DataType &) noexcept=default
void set_flag(uint8_t flag)
Definition: datatype.h:115
void set_byte_order_native()
Definition: datatype.h:96
void unset_flag(uint8_t flag)
Definition: datatype.h:118
uint8_t operator()() const
Definition: datatype.h:41
void display(int log_level=0) const
Definition: exception.h:92
void sanitise_transform()
default_type offset_
the values by which to scale the intensities
Definition: header.h:372
const char * format_
Definition: header.h:365
void acquire_io(Header &H)
Definition: header.h:375
friend std::ostream & operator<<(std::ostream &stream, const Header &H)
print out debugging information
void sanitise_voxel_sizes()
void realign_transform()
realign transform to match RAS coordinate system as closely as possible
default_type scale_
Definition: header.h:372
std::array< size_t, 3 > realign_perm_
Definition: header.h:382
vector< Axis > axes_
Definition: header.h:361
void check(const Header &H) const
transform_type transform_
Definition: header.h:362
DataType datatype_
the type of the data as stored on file
Definition: header.h:370
std::unique_ptr< ImageIO::Base > io
additional information relevant for images stored on file
Definition: header.h:368
std::array< bool, 3 > realign_flip_
Definition: header.h:383
KeyValues keyval_
Definition: header.h:364
std::string name_
Definition: header.h:363
void sanitise_strides()
Definition: header.h:387
functions and classes related to image data input/output
Definition: image.h:41
#define WARN(msg)
Definition: exception.h:73
#define DEBUG(msg)
Definition: exception.h:75
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
#define NOMEMALIGN
Definition: memory.h:22
void actualise(HeaderType &header)
convert strides from symbolic to actual strides
Definition: stride.h:239
void sanitise(HeaderType &header)
remove duplicate and invalid strides.
Definition: stride.h:191
void set(HeaderType &header, const List &stride)
set the strides of header from a vector<ssize_t>
Definition: stride.h:135
Definition: base.h:24
std::map< std::string, std::string > KeyValues
used in various places for storing key-value pairs
Definition: types.h:238
Header concatenate(const vector< Header > &headers, const size_t axis, const bool permit_datatype_mismatch)
CHECK_MEM_ALIGN(Header)
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
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
Definition: types.h:234
constexpr default_type NaN
Definition: types.h:230
int axis
Eigen::MatrixXd H
#define MEMALIGN(...)
Definition: types.h:185