BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FourierTransform Class Reference
Collaboration diagram for FourierTransform:

Classes

class  Workspace
 

Public Types

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

Public Member Functions

 FourierTransform ()
 
void fft (const double1d_t &source, double1d_t &result)
 
void fftshift (double1d_t &result)
 
void fft (const double2d_t &source, double2d_t &result)
 
void fftshift (double2d_t &result)
 
void init (int h_src, int w_src)
 

Private Member Functions

void fftw_forward_FT (const double2d_t &source)
 

Private Attributes

Workspace ws
 

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 34 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 38 of file FourierTransform.h.

◆ double2d_t

definition of 2D vector of double

Definition at line 41 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 124 of file FourierTransform.cpp.

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

Referenced by IntensityDataFunctions::FT2DArray().

◆ fftshift() [1/2]

void FourierTransform::fftshift ( double1d_t result)

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

Definition at line 142 of file FourierTransform.cpp.

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

Referenced by IntensityDataFunctions::FT2DArray().

◆ fft() [2/2]

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

FT in 2D.

Definition at line 59 of file FourierTransform.cpp.

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

void FourierTransform::fftshift ( double2d_t result)

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

Definition at line 96 of file FourierTransform.cpp.

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

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

◆ init()

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

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

Definition at line 157 of file FourierTransform.cpp.

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

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:

◆ 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 192 of file FourierTransform.cpp.

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

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().

Member Data Documentation

◆ ws

Workspace FourierTransform::ws
private

input and output data for fftw3

Definition at line 91 of file FourierTransform.h.

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


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