BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FourierTransform Class Reference

Fourier transform of vectors (in 1D or 2D) using Fast Fourier Transform (fftw package). More...

Collaboration diagram for FourierTransform:
[legend]

Classes

class  Workspace
 Workspace for Fourier Transform. More...
 

Public Types

typedef std::vector< double > double1d_t
 definition of 1D vector of double More...
 
typedef std::vector< double1d_tdouble2d_t
 definition of 2D vector of double More...
 

Public Member Functions

 FourierTransform ()
 
void fft (const double1d_t &source, double1d_t &result)
 FT in 1D. More...
 
void fft (const double2d_t &source, double2d_t &result)
 FT in 2D. More...
 
void fftshift (double1d_t &result)
 Shift low frequency to the center of 1D FT array. More...
 
void fftshift (double2d_t &result)
 Shift low frequency to the center of 2D FT array. More...
 
void init (int h_src, int w_src)
 prepare arrays for 2D Fourier Transformation (FT) of the given vector More...
 

Private Member Functions

void fftw_forward_FT (const double2d_t &source)
 compute FT of source using Fast Fourier transformation from fftw More...
 

Private Attributes

Workspace ws
 input and output data for fftw3 More...
 

Detailed Description

Fourier transform of vectors (in 1D or 2D) using Fast Fourier Transform (fftw package).

Usage: std::vector<double> signal, result; FourierTransform ft; ft.fft(signal, result)

Given code rely on code from Jeremy Fix page, http://jeremy.fix.free.fr/spip.php?article15, see also "Efficient convolution using the Fast Fourier Transform, Application in C++" by Jeremy Fix, May 30, 2011

Definition at line 39 of file FourierTransform.h.

Member Typedef Documentation

◆ double1d_t

typedef std::vector<double> FourierTransform::double1d_t

definition of 1D vector of double

Definition at line 42 of file FourierTransform.h.

◆ double2d_t

definition of 2D vector of double

Definition at line 45 of file FourierTransform.h.

Constructor & Destructor Documentation

◆ FourierTransform()

FourierTransform::FourierTransform ( )
default

Member Function Documentation

◆ fft() [1/2]

void FourierTransform::fft ( const double1d_t source,
double1d_t result 
)

FT in 1D.

Definition at line 123 of file FourierTransform.cpp.

124 {
125  // we simply create 2d arrays with length of first dimension equal to 1, and call 2d FT
126  double2d_t source2d;
127  source2d.push_back(source);
128 
129  double2d_t result2d;
130  fft(source2d, result2d);
131 
132  if (result2d.size() != 1)
133  throw std::runtime_error("FourierTransform::fft -> Panic in 1d");
134 
135  result = result2d[0];
136 }
void fft(const double1d_t &source, double1d_t &result)
FT in 1D.
std::vector< double1d_t > double2d_t
definition of 2D vector of double

◆ fft() [2/2]

void FourierTransform::fft ( const double2d_t source,
double2d_t result 
)

FT in 2D.

Definition at line 58 of file FourierTransform.cpp.

59 {
60  // rows (h) and columns (w) of the input 'source'
61  int h_src = static_cast<int>(source.size());
62  int w_src = static_cast<int>((source.size() ? source[0].size() : 0));
63 
64  // initialisation
65  init(h_src, w_src);
66 
67  // Compute the forward FT
68  fftw_forward_FT(source);
69 
70  double* ptr = ws.out_fftw;
71  result.clear();
72 
73  // Resize the array for holding the FT output to correct dimensions
74  result.resize(static_cast<size_t>(ws.h_fftw),
75  std::vector<double>(static_cast<size_t>(ws.w_fftw)));
76 
77  // Storing FT output
78  for (size_t i = 0; i < static_cast<size_t>(ws.h_fftw); i++) {
79  size_t k = static_cast<size_t>(ws.h_fftw) - i;
80  if (i == 0)
81  k -= static_cast<size_t>(ws.h_fftw);
82  for (size_t j = 0; j < static_cast<size_t>(ws.w_fftw / 2 + 1); j++) {
83  result[i][j] = *ptr;
84  size_t l = static_cast<size_t>(ws.w_fftw) - j;
85  if (j != 0)
86  result[k][l] = result[i][j];
87  ptr += 2; // Only interested in the magnitudes of the complex Fourier coefficients
88  }
89  }
90 }
double * out_fftw
result of Fourier transformation of source
Workspace ws
input and output data for fftw3
void fftw_forward_FT(const double2d_t &source)
compute FT of source using Fast Fourier transformation from fftw
void init(int h_src, int w_src)
prepare arrays for 2D Fourier Transformation (FT) of the given vector

References fftw_forward_FT(), FourierTransform::Workspace::h_fftw, init(), FourierTransform::Workspace::out_fftw, FourierTransform::Workspace::w_fftw, and ws.

Here is the call graph for this function:

◆ fftshift() [1/2]

void FourierTransform::fftshift ( double1d_t result)

Shift low frequency to the center of 1D FT array.

Definition at line 141 of file FourierTransform.cpp.

142 {
143  // Centering FT around zero frequency
144  size_t col_shift;
145  if (result.size() % 2 == 0)
146  col_shift = result.size() / 2;
147  else
148  col_shift = result.size() / 2 + 1;
149 
150  std::rotate(result.begin(), result.begin() + static_cast<int>(col_shift), result.end());
151 }

◆ fftshift() [2/2]

void FourierTransform::fftshift ( double2d_t result)

Shift low frequency to the center of 2D FT array.

Definition at line 95 of file FourierTransform.cpp.

96 {
97  // Centering FT around zero frequency
98  size_t row_shift;
99  if (result.size() % 2 == 0)
100  row_shift = result.size() / 2;
101  else
102  row_shift = result.size() / 2 + 1;
103 
104  size_t col_shift;
105  if (result[0].size() % 2 == 0)
106  col_shift = result[0].size() / 2;
107  else
108  col_shift = result[0].size() / 2 + 1;
109 
110  // First, shifting the rows
111  std::rotate(result.begin(), result.begin() + static_cast<int>(row_shift), result.end());
112 
113  // Second, shifting the cols
114  for (size_t i = 0; i < static_cast<size_t>(ws.h_fftw); i++) {
115  std::rotate(result[i].begin(), result[i].begin() + static_cast<int>(col_shift),
116  result[i].end());
117  }
118 }

References FourierTransform::Workspace::h_fftw, and ws.

◆ fftw_forward_FT()

void FourierTransform::fftw_forward_FT ( const double2d_t source)
private

compute FT of source using Fast Fourier transformation from fftw

Definition at line 191 of file FourierTransform.cpp.

192 {
193  if (ws.h_fftw <= 0 || ws.w_fftw <= 0)
194  throw std::runtime_error(
195  "FourierTransform::fftw_forward_FT() -> Panic! Initialisation is missed.");
196 
197  double *ptr, *ptr_end;
198 
199  // Initializing the content of ws.in_src to zero for all elements
200  for (ptr = ws.in_src, ptr_end = ws.in_src + ws.h_fftw * ws.w_fftw; ptr != ptr_end; ++ptr)
201  *ptr = 0.0;
202 
203  // Building the input signal for fftw algorithm
204  for (size_t row = 0; row < static_cast<size_t>(ws.h_src); ++row)
205  for (size_t col = 0; col < static_cast<size_t>(ws.w_src); ++col)
206  ws.in_src[(static_cast<int>(row) % ws.h_fftw) * ws.w_fftw
207  + (static_cast<int>(col) % ws.w_fftw)] += src[row][col];
208 
209  // Computing the FFT with fftw plan
210  fftw_execute(ws.p_forw_src);
211 
212  double re_out, im_out;
213  for (ptr = ws.out_fftw, ptr_end = ws.out_fftw + 2 * ws.h_fftw * (ws.w_fftw / 2 + 1);
214  ptr != ptr_end; ++ptr) {
215  re_out = *ptr;
216  im_out = *(++ptr);
217 
218  // magnitude
219  *(ptr - 1) = sqrt(re_out * re_out + im_out * im_out);
220  // phase
221  *ptr = atan2(im_out, re_out);
222  }
223 }
int h_src
Here, h = height (# rows), w = width (# columns)

References FourierTransform::Workspace::h_fftw, FourierTransform::Workspace::h_src, FourierTransform::Workspace::in_src, FourierTransform::Workspace::out_fftw, FourierTransform::Workspace::p_forw_src, FourierTransform::Workspace::w_fftw, FourierTransform::Workspace::w_src, and ws.

Referenced by fft().

◆ init()

void FourierTransform::init ( int  h_src,
int  w_src 
)

prepare arrays for 2D Fourier Transformation (FT) of the given vector

Definition at line 156 of file FourierTransform.cpp.

157 {
158  if (!h_src || !w_src) {
159  std::ostringstream os;
160  os << "FourierTransform::init() -> Panic! Wrong dimensions " << h_src << " " << w_src
161  << std::endl;
162  throw std::runtime_error(os.str());
163  }
164 
165  ws.clear();
166  ws.h_src = h_src;
167  ws.w_src = w_src;
168 
169  ws.h_fftw = h_src;
170  ws.w_fftw = w_src;
171 
172  ws.in_src = new double[static_cast<size_t>(ws.h_fftw * ws.w_fftw)];
173  ws.out_fftw = static_cast<double*>(
174  fftw_malloc(sizeof(fftw_complex) * static_cast<size_t>(ws.h_fftw * (ws.w_fftw / 2 + 1))));
175 
176  // Initialization of the plans
177  ws.p_forw_src = fftw_plan_dft_r2c_2d(ws.h_fftw, ws.w_fftw, ws.in_src,
178  (fftw_complex*)ws.out_fftw, FFTW_ESTIMATE);
179  // ws.p_forw_src = fftw_plan_dft_r2c_2d(ws.h_fftw, ws.w_fftw, ws.in_src,
180  // static_cast<double*>(ws.out_src), FFTW_ESTIMATE);
181 
182  if (ws.p_forw_src == nullptr)
183  throw std::runtime_error(
184  "FourierTransform::init() -> Error! Can't initialise p_forw_src plan.");
185 }

References FourierTransform::Workspace::clear(), FourierTransform::Workspace::h_fftw, FourierTransform::Workspace::h_src, FourierTransform::Workspace::in_src, FourierTransform::Workspace::out_fftw, FourierTransform::Workspace::p_forw_src, FourierTransform::Workspace::w_fftw, FourierTransform::Workspace::w_src, and ws.

Referenced by fft().

Here is the call graph for this function:

Member Data Documentation

◆ ws

Workspace FourierTransform::ws
private

input and output data for fftw3

Definition at line 94 of file FourierTransform.h.

Referenced by fft(), fftshift(), fftw_forward_FT(), and init().


The documentation for this class was generated from the following files: