Developer documentation
Version 3.0.3-105-gd3941f44
fft.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 __image_filter_fft_h__
18#define __image_filter_fft_h__
19
20#include <complex>
21
22#include <unsupported/Eigen/FFT>
23
24#include "datatype.h"
25#include "memory.h"
26#include "image.h"
27#include "algo/copy.h"
28#include "algo/threaded_copy.h"
29#include "filter/base.h"
30
31namespace MR
32{
33 namespace Filter
34 {
35
40
50 class FFT : public Base { MEMALIGN(FFT)
51 public:
52
53 template <class HeaderType>
54 FFT (const HeaderType& in, const bool inverse) :
55 Base (in),
57 centre_zero_ (false)
58 {
59 for (size_t axis = 0; axis != std::min<size_t> (size_t(3), in.ndim()); ++axis)
60 axes_to_process.push_back (axis);
63 }
64
65
66 void set_axes (const vector<uint32_t>& in)
67 {
68 axes_to_process.clear();
69 for (auto i : in) {
70 if (i >= this->ndim())
71 throw Exception ("Axis index " + str(i) + " for FFT image filter exceeds number of image dimensions (" + str(this->ndim()) + ")");
72 axes_to_process.push_back (i);
73 }
74 }
75
76
77 void set_centre_zero (const bool i)
78 {
79 centre_zero_ = i;
80 }
81
82
83 template <class InputComplexImageType, class OutputComplexImageType>
84 void operator() (InputComplexImageType& input, OutputComplexImageType& output)
85 {
86
87 std::shared_ptr<ProgressBar> progress (message.size() ? new ProgressBar (message, axes_to_process.size() + 2) : nullptr);
88
89 auto temp = Image<cdouble>::scratch (*this);
90 copy (input, temp);
91 if (progress)
92 ++(*progress);
93
95 vector<size_t> axes = Stride::order (temp);
96 for (size_t n = 0; n < axes.size(); ++n) {
97 if (axes[n] == *axis) {
98 axes.erase (axes.begin() + n);
99 break;
100 }
101 }
102 FFTKernel<decltype(temp)> kernel (temp, *axis, inverse);
103 ThreadedLoop (temp, axes, 1).run (kernel);
104 if (progress) ++(*progress);
105 }
106
107 if (centre_zero_) {
108 for (auto l = Loop (output)(output); l; ++l) {
109 assign_pos_of (output).to (temp);
110 for (vector<size_t>::const_iterator flip_axis = axes_to_process.begin(); flip_axis != axes_to_process.end(); ++flip_axis)
111 temp.index(*flip_axis) = (temp.index(*flip_axis) >= (temp.size (*flip_axis) / 2)) ?
112 (temp.index(*flip_axis) - (temp.size (*flip_axis) / 2)) :
113 (temp.index(*flip_axis) + (temp.size (*flip_axis) / 2));
114 output.value() = temp.value();
115 }
116 } else {
117 copy (temp, output);
118 }
119 }
120
121
122 protected:
123
124 const bool inverse;
127
128 template <class ComplexImageType>
129 class FFTKernel { MEMALIGN(FFTKernel)
130 public:
131 FFTKernel (const ComplexImageType& voxel, const size_t FFT_axis, const bool inverse_FFT) :
132 vox (voxel),
133 data_in (vox.size (FFT_axis)),
134 data_out (data_in.size()),
135 axis (FFT_axis),
136 inverse (inverse_FFT) { }
137
138 void operator () (const Iterator& pos) {
139 assign_pos_of (pos).to (vox);
140 for (vox.index(axis) = 0; vox.index(axis) < vox.size(axis); ++vox.index(axis))
141 data_in[vox.index(axis)] = cdouble (vox.value());
142 if (inverse)
143 fft.inv (data_out, data_in);
144 else
145 fft.fwd (data_out, data_in);
146 for (vox.index(axis) = 0; vox.index(axis) < vox.size(axis); ++vox.index(axis))
147 vox.value() = typename ComplexImageType::value_type (data_out[vox.index(axis)]);
148 }
149
150 protected:
151 ComplexImageType vox;
152 Eigen::Matrix<cdouble, Eigen::Dynamic, 1> data_in, data_out;
153 Eigen::FFT<double> fft;
154 size_t axis;
156 };
157
158 };
159
160
161
162 template <class ImageType>
163 void fft (ImageType&& vox, const size_t axis, const bool inverse = false) {
164 auto axes = Stride::order (vox);
165 for (size_t n = 0; n < axes.size(); ++n)
166 if (axis == axes[n])
167 axes.erase (axes.begin() + n);
168
169 struct Kernel { MEMALIGN(Kernel)
170 Kernel (const ImageType& v, size_t axis, bool inverse) :
171 data_in (v.size (axis)), data_out (data_in.size()), axis (axis), inverse (inverse) { }
172
173 void operator ()(ImageType& v) {
174 for (auto l = Loop (axis, axis+1) (v); l; ++l)
175 data_in[v[axis]] = cdouble (v.value());
176 if (inverse)
177 fft.inv (data_out, data_in);
178 else
179 fft.fwd (data_out, data_in);
180 for (auto l = Loop (axis, axis+1) (v); l; ++l)
181 v.value() = typename std::remove_reference<ImageType>::type::value_type (data_out[v[axis]]);
182 }
183 Eigen::FFT<double> fft;
184 Eigen::Matrix<cdouble, Eigen::Dynamic, 1> data_in, data_out;
185 const size_t axis;
186 const bool inverse;
187 } kernel (vox, axis, inverse);
188
189 ThreadedLoop ("performing in-place FFT", vox, axes)
190 .run (kernel, vox);
191 }
192
193
194
195
196 }
197}
198
199
200#endif
static constexpr uint8_t CFloat64
Definition: datatype.h:174
void set_byte_order_native()
Definition: datatype.h:96
std::string message
Definition: base.h:66
a filter to perform an FFT on an image
Definition: fft.h:50
DataType datatype_
the type of the data as stored on file
Definition: header.h:370
static Image scratch(const Header &template_header, const std::string &label="scratch image")
Definition: image.h:195
a dummy image to iterate over, useful for multi-threaded looping.
Definition: iterator.h:29
implements a progress meter to provide feedback to the user
Definition: progressbar.h:58
Eigen::Matrix< cdouble, Eigen::Dynamic, 1 > data_out
Definition: fft.h:152
void fft(ImageType &&vox, const size_t axis, const bool inverse=false)
Definition: fft.h:163
ComplexImageType vox
Definition: fft.h:151
Eigen::Matrix< cdouble, Eigen::Dynamic, 1 > data_in
Definition: fft.h:152
const bool inverse
Definition: fft.h:124
vector< size_t > axes_to_process
Definition: fft.h:125
Eigen::FFT< double > fft
Definition: fft.h:153
bool centre_zero_
Definition: fft.h:126
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
MR::default_type value_type
Definition: typedefs.h:33
vector< size_t > order(const HeaderType &header, size_t from_axis=0, size_t to_axis=std::numeric_limits< size_t >::max())
sort range of axes with respect to their absolute stride.
Definition: stride.h:159
Definition: base.h:24
std::complex< double > cdouble
Definition: types.h:217
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247
ThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> ThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
Multi-threaded loop object.
void copy(InputImageType &&source, OutputImageType &&destination, size_t from_axis=0, size_t to_axis=std::numeric_limits< size_t >::max())
Definition: copy.h:27
int axis
#define MEMALIGN(...)
Definition: types.h:185