Xmipp  v3.23.11-Nereus
Fourier transforms
Collaboration diagram for Fourier transforms:

Index <--> Frequency, Continuous <--> Discrete

template<typename T >
void FFT_idx2digfreq (T &v, const Matrix1D< int > &idx, Matrix1D< double > &freq)
 
template<typename T >
void digfreq2FFT_idx (T &v, const Matrix1D< double > &freq, Matrix1D< int > &idx)
 
void digfreq2contfreq (const Matrix1D< double > &digfreq, Matrix1D< double > &contfreq, double pixel_size)
 
void contfreq2digfreq (const Matrix1D< double > &contfreq, Matrix1D< double > &digfreq, double pixel_size)
 
#define FFT_IDX2DIGFREQ(idx, size, freq)
 
#define FFT_IDX2DIGFREQ_DOUBLE(idx, size, freq)
 
#define FFT_IDX2DIGFREQ_FAST(idx, size, size_2, isize, freq)   freq = ( ((idx) <= (size_2)) ? (idx) : -(size) + (idx) ) * (isize);
 
#define DIGFREQ2FFT_IDX(freq, size, idx)
 
#define DIGFREQ2FFT_IDX_DOUBLE(freq, size, idx)
 

Format conversions

void Whole2Half (const MultidimArray< std::complex< double > > &in, MultidimArray< std::complex< double > > &out)
 
void Half2Whole (const MultidimArray< std::complex< double > > &in, MultidimArray< std::complex< double > > &out, size_t oridim)
 
void Complex2RealImag (const MultidimArray< std::complex< double > > &in, MultidimArray< double > &real, MultidimArray< double > &imag)
 
void RealImag2Complex (const MultidimArray< double > &real, const MultidimArray< double > &imag, MultidimArray< std::complex< double > > &out)
 

Fourier Transforms

The theoretical relationship between the Fourier transform of a discrete signal and the Fourier transform of the continuous signal is

X(e^jw)=1/T*X_c(jw/T)

Xmipp is not computing X(e^jw) but samples from it so that

X(e^jw)=N*X_XMIPP[k]

where N is the length of the signal being transformed and X_XMIPP[k] is the k-th sample.

The following program illustrates how the continuous, discrete and Xmipp Fourier transform relate

#include <data/matrix1d.h>
#include <data/xmipp_fft.h>
double discreteTransform(double w, int N1) {
if (w==0) return 2*N1+1;
else return sin(w*(N1+0.5))/sin(0.5*w);
}
double continuousTransform(double W, double T1) {
if (W==0) return 2*T1;
else return 2*sin(W*T1)/W;
}
int main() {
try {
x.setXmippOrigin();
double T=0.5;
double T1=6;
int N1=(int)CEIL(T1/T);
// Fill x with a pulse from -N1 to N1 (-T1 to T1 in continuous)
if (ABS(i)<=N1) x(i)=1;
// Compute the Fourier transform
FFT_magnitude(X,Xmag);
// Compute the frequency axes
MultidimArray<double> contfreq(XSIZE(X)), digfreq(XSIZE(X));
FFT_IDX2DIGFREQ(i,XSIZE(X),digfreq(i));
digfreq*=2*PI;
contfreq=digfreq/T;
// Show all Fourier transforms
if (digfreq(i)>=0)
std::cout << digfreq(i) << " " << contfreq(i) << " "
<< XSIZE(X)*Xmag(i) << " "
<< ABS(discreteTransform(digfreq(i),N1)) << " "
<< ABS(continuousTransform(contfreq(i),T1)/T)
<< std::endl;
}
} catch (XmippError XE) {
std::cout << XE << std::endl;
}
return 0;
}
void FourierTransform (const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
 
void InverseFourierTransform (const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out)
 
void FourierTransformHalf (const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
 
void InverseFourierTransformHalf (const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out, int oridim)
 

Operations with the Fourier Transforms

void centerFFT2 (MultidimArray< double > &v)
 
template<typename T >
void CenterFFT (MultidimArray< T > &v, bool forward)
 
void ShiftFFT (MultidimArray< std::complex< double > > &v, double xshift)
 
void ShiftFFT (MultidimArray< std::complex< double > > &v, double xshift, double yshift)
 
void ShiftFFT (MultidimArray< std::complex< double > > &v, double xshift, double yshift, double zshift)
 
void CenterOriginFFT (MultidimArray< std::complex< double > > &v, bool forward)
 
template<typename T >
void xmipp2PSD (const MultidimArray< T > &input, MultidimArray< T > &output, bool takeLog=true)
 
void xmipp2CTF (const MultidimArray< double > &input, MultidimArray< double > &output)
 
#define SWAP_ARRAY(a, b, n)   memcpy(buffer, a, n); memcpy(a, b, n); memcpy(b, buffer, n);
 

Detailed Description

Macro Definition Documentation

◆ DIGFREQ2FFT_IDX

#define DIGFREQ2FFT_IDX (   freq,
  size,
  idx 
)
Value:
{ \
(idx) = (int) (round((size) * (freq))); if ((idx) < 0) (idx) += (int) \
(size); }
int round(double x)
Definition: ap.cpp:7245

Frequency to index (int)

Given a frequency and a size of the FFT, this macro returns the corresponding integer index

Definition at line 61 of file xmipp_fft.h.

◆ DIGFREQ2FFT_IDX_DOUBLE

#define DIGFREQ2FFT_IDX_DOUBLE (   freq,
  size,
  idx 
)
Value:
{ \
(idx) = ((size) * (freq)); if ((idx) < 0) (idx) += (size); }

Frequency to index (double)

Given a frequency and a size of the FFT, this macro returns the corresponding double index

Definition at line 70 of file xmipp_fft.h.

◆ FFT_IDX2DIGFREQ

#define FFT_IDX2DIGFREQ (   idx,
  size,
  freq 
)
Value:
freq = (size<=1)? 0:(( (((int)idx) <= (((int)(size)) >> 1)) ? ((int)(idx)) : -((int)(size)) + ((int)(idx))) / \
(double)(size));

Index to frequency

Given an index and a size of the FFT, this function returns the corresponding digital frequency (-1/2 to 1/2)

Definition at line 46 of file xmipp_fft.h.

◆ FFT_IDX2DIGFREQ_DOUBLE

#define FFT_IDX2DIGFREQ_DOUBLE (   idx,
  size,
  freq 
)
Value:
freq = (size<=1)? 0:(( (((double)idx) <= (((double)(size)) / 2.0)) ? ((double)(idx)) : -((double)(size)) + ((double)(idx))) / \
(double)(size));

Definition at line 50 of file xmipp_fft.h.

◆ FFT_IDX2DIGFREQ_FAST

#define FFT_IDX2DIGFREQ_FAST (   idx,
  size,
  size_2,
  isize,
  freq 
)    freq = ( ((idx) <= (size_2)) ? (idx) : -(size) + (idx) ) * (isize);

Definition at line 54 of file xmipp_fft.h.

◆ SWAP_ARRAY

#define SWAP_ARRAY (   a,
  b,
  n 
)    memcpy(buffer, a, n); memcpy(a, b, n); memcpy(b, buffer, n);

Faster version of CenterFFT (now just for even images)

Definition at line 278 of file xmipp_fft.h.

Function Documentation

◆ CenterFFT()

template<typename T >
void CenterFFT ( MultidimArray< T > &  v,
bool  forward 
)

CenterFFT Relation with Matlab fftshift: forward true is equals to fftshift and forward false equals to ifftshift

Definition at line 291 of file xmipp_fft.h.

292 {
293  bool firstTime=true; // First time executing inner loops.
294 
295  // Check dimension is between 1 and 3 inclusive.
296  if ( v.getDim() > 0 && v.getDim() <= 3)
297  {
298  // Shift in the X direction
299  size_t l=0;
300 
301  // Shift in the X direction
302  if (((l = XSIZE(v)) > 1) && (YSIZE(v) == 1) && (ZSIZE(v) == 1))
303  {
304  size_t firstHalfSize=0;
305  size_t secondHalfSize=0;
306  MultidimArray< T > aux;
307 
308  if (forward)
309  {
310  firstHalfSize = (l + 1) / 2;
311  secondHalfSize = l - firstHalfSize;
312  aux.resizeNoCopy( firstHalfSize);
313 
314  for (size_t k = 0; k < ZSIZE(v); k++)
315  {
316  for (size_t i = 0; i < YSIZE(v); i++)
317  {
318  memcpy( &dAi(aux, 0), &dAkij(v, k, i, 0), sizeof(T)*firstHalfSize);
319  memcpy( &dAkij(v, k, i, 0), &dAkij(v, k, i, firstHalfSize), sizeof(T)*secondHalfSize);
320  memcpy( &dAkij(v, k, i, secondHalfSize), &dAi(aux, 0), sizeof(T)*firstHalfSize);
321  }
322  }
323  }
324  else
325  {
326  secondHalfSize = (l + 1) / 2;
327  firstHalfSize = l - secondHalfSize;
328  aux.resizeNoCopy( secondHalfSize);
329 
330  for (size_t k = 0; k < ZSIZE(v); k++)
331  {
332  for (size_t i = 0; i < YSIZE(v); i++)
333  {
334  memcpy( &dAi(aux, 0), &dAkij(v, k, i, firstHalfSize), sizeof(T)*secondHalfSize);
335  memcpy( &dAkij(v, k, i, secondHalfSize), &dAkij(v, k, i, 0), sizeof(T)*firstHalfSize);
336  memcpy( &dAkij(v, k, i, 0), &dAi(aux, 0), sizeof(T)*secondHalfSize);
337  }
338  }
339  }
340  }
341  else
342  {
343  // 3D
344  MultidimArray< T > aux;
345  size_t l=0;
346  long int shift;
347 
348  int i=0; // Loop counter.
349  int halfRows=0; // Half rows of the matrix.
350  int rowSize=0; // Size in bytes of the row.
351 
352  // Size in bytes of first and second half row.
353  int firstHalfRowSize=0, secondHalfRowSize=0;
354 
355  // # elements in first and second half row.
356  int nElemsFirstHalf_X=0, nElemsSecondHalf_X=0;
357 
358  MultidimArray< T > tempVector; // Temporary vector.
359 
360  bool isOdd=false; // Odd # rows in matrix.
361  MultidimArray< T > savedRow; // Temporary vector in odd matrix.
362 
363  // Execute FFT in 2 dimensions before 3D.
364  if (forward)
365  {
366  for (size_t k=0; k<ZSIZE(v); k++)
367  {
368  // Pointers to upper and lower half matrix.
369  T *upperHalfPtr, *lowerHalfSrcPtr, *lowerHalfDestPtr;
370 
371  // This is computed first time only.
372  if (firstTime)
373  {
374  firstTime = false;
375 
376  // Compute # elements in each half vector in X-dimension.
377  nElemsFirstHalf_X = (XSIZE(v) + 1) / 2;
378  nElemsSecondHalf_X = XSIZE(v) - nElemsFirstHalf_X;
379 
380  // Compute X dimension size in bytes.
381  rowSize = XSIZE(v)*sizeof(T);
382 
383  // Allocate temporary vector.
384  firstHalfRowSize = nElemsFirstHalf_X*sizeof(T);
385  secondHalfRowSize = rowSize - firstHalfRowSize;
386  tempVector.resizeNoCopy( XSIZE(v));
387 
388  // Compute # iterations.
389  halfRows = YSIZE(v) / 2;
390 
391  // If even # rows then save row located in the middle of the matrix.
392  if ((YSIZE(v) % 2) != 0)
393  {
394  isOdd = true;
395  savedRow.resizeNoCopy( XSIZE(v));
396  }
397  }
398 
399  // Initialize pointers to upper and lower matrix rows.
400  upperHalfPtr = &dAkij(v, k, 0, 0);
401  lowerHalfSrcPtr = upperHalfPtr + (halfRows*XSIZE(v));
402  lowerHalfDestPtr = lowerHalfSrcPtr;
403 
404  // If even # rows then save row located in the middle of the matrix.
405  if (isOdd)
406  {
407  memcpy( &dAi(savedRow,0), lowerHalfSrcPtr, rowSize);
408 
409  // Source and destination rows are not the same in odd matrix.
410  lowerHalfSrcPtr = lowerHalfSrcPtr + XSIZE(v);
411  }
412 
413  // Half of the rows must be exchanged.
414  for (i=0; i<halfRows ;i++)
415  {
416  memcpy( &dAi(tempVector,0), upperHalfPtr, rowSize);
417  memcpy( upperHalfPtr, lowerHalfSrcPtr + nElemsFirstHalf_X, secondHalfRowSize);
418  memcpy( upperHalfPtr + nElemsSecondHalf_X, lowerHalfSrcPtr, firstHalfRowSize);
419  memcpy( lowerHalfDestPtr, &dAi(tempVector, nElemsFirstHalf_X), secondHalfRowSize);
420  memcpy( lowerHalfDestPtr + nElemsSecondHalf_X, &dAi(tempVector,0), firstHalfRowSize);
421 
422  upperHalfPtr = upperHalfPtr + XSIZE(v);
423  lowerHalfSrcPtr = lowerHalfSrcPtr + XSIZE(v);
424  lowerHalfDestPtr = lowerHalfDestPtr + XSIZE(v);
425  }
426 
427  // If # rows is odd then restore last row.
428  if (isOdd)
429  {
430  memcpy( lowerHalfDestPtr + nElemsSecondHalf_X, &dAi(savedRow,0), firstHalfRowSize);
431  memcpy( lowerHalfDestPtr, &dAi(savedRow, nElemsFirstHalf_X), secondHalfRowSize);
432  }
433  }
434  }
435  else
436  {
437  for (size_t k = 0; k<ZSIZE(v); k++)
438  {
439  // Pointers to upper and lower half matrix.
440  T *upperHalfSrcPtr, *upperHalfDestPtr, *lowerHalfPtr;
441 
442  // This is computed first time only.
443  if (firstTime)
444  {
445  firstTime = false;
446 
447  // Compute # elements in each half vector in X-dimension.
448  nElemsSecondHalf_X = (XSIZE(v) + 1) / 2;
449  nElemsFirstHalf_X = XSIZE(v) - nElemsSecondHalf_X;
450 
451  // Allocate temporary vector.
452  rowSize = XSIZE(v)*sizeof(T);
453  firstHalfRowSize = nElemsFirstHalf_X*sizeof(T);
454  secondHalfRowSize = rowSize - firstHalfRowSize;
455  tempVector.resizeNoCopy(rowSize);
456 
457  // Compute # iterations.
458  halfRows = YSIZE(v) / 2;
459 
460  // If odd # rows then save last row.
461  if ((YSIZE(v) % 2) != 0)
462  {
463  isOdd = true;
464  savedRow.resizeNoCopy(XSIZE(v));
465  }
466  }
467 
468  // Initialize pointers to quadrants.
469  upperHalfSrcPtr = &dAkij(v, k, halfRows-1, 0);
470  lowerHalfPtr = &dAkij(v, k, YSIZE(v)-1, 0);
471  upperHalfDestPtr = upperHalfSrcPtr;
472 
473  // If odd # rows then save last row.
474  if (isOdd)
475  {
476  // Source and destination rows are not the same in odd matrix.
477  upperHalfDestPtr = upperHalfDestPtr + XSIZE(v);
478 
479  memcpy( &dAi(savedRow,0), upperHalfDestPtr, rowSize);
480  }
481 
482  // Half of the rows must be exchanged.
483  for (i=0; i<halfRows ;i++)
484  {
485  memcpy( &dAi(tempVector, 0), upperHalfSrcPtr, rowSize);
486  memcpy( upperHalfDestPtr, lowerHalfPtr + nElemsFirstHalf_X, secondHalfRowSize);
487  memcpy( upperHalfDestPtr + nElemsSecondHalf_X, lowerHalfPtr, firstHalfRowSize);
488  memcpy( lowerHalfPtr, &dAi(tempVector, nElemsFirstHalf_X), secondHalfRowSize);
489  memcpy( lowerHalfPtr + nElemsSecondHalf_X, &dAi(tempVector,0), firstHalfRowSize);
490 
491  upperHalfSrcPtr = upperHalfSrcPtr - XSIZE(v);
492  lowerHalfPtr = lowerHalfPtr - XSIZE(v);
493  upperHalfDestPtr = upperHalfDestPtr - XSIZE(v);
494  }
495 
496  // If # rows is odd then restore row at medium position.
497  if (isOdd)
498  {
499  memcpy( upperHalfDestPtr + nElemsSecondHalf_X, &dAi(savedRow, 0), firstHalfRowSize);
500  memcpy( upperHalfDestPtr, &dAi(savedRow, nElemsFirstHalf_X), secondHalfRowSize);
501  }
502  }
503  }
504 
505  // Shift in the Z direction
506  if ((l = ZSIZE(v)) > 1)
507  {
508  aux.resizeNoCopy(l);
509  shift = (long int)(l / 2);
510 
511  if (!forward)
512  shift = -shift;
513  size_t lmax=(l/4)*4;
514  for (size_t i = 0; i < YSIZE(v); i++)
515  {
516  for (size_t j = 0; j < XSIZE(v); j++)
517  {
518  // Shift the input in an auxiliary vector
519  for (size_t k = 0; k < l; k++)
520  {
521  size_t kp = k + shift;
522  if (-shift > (long int)k)
523  kp += l;
524  else if (kp >= l)
525  kp -= l;
526 
527  dAi(aux,kp) = dAkij(v, k, i, j);
528  }
529 
530  // Copy the vector
531  const T* ptrAux=&dAi(aux,0);
532  for (size_t k = 0; k < lmax; k+=4,ptrAux+=4)
533  {
534  dAkij(v, k, i, j) = *ptrAux;
535  dAkij(v, k+1, i, j) = *(ptrAux+1);
536  dAkij(v, k+2, i, j) = *(ptrAux+2);
537  dAkij(v, k+3, i, j) = *(ptrAux+3);
538  }
539  for (size_t k = lmax; k < l; ++k, ++ptrAux)
540  {
541  dAkij(v, k, i, j) = *ptrAux;
542  }
543  }
544  }
545  }
546  }
547  }
548  else
549  {
550  REPORT_ERROR(ERR_MULTIDIM_DIM,"CenterFFT ERROR: Dimension should be 1, 2 or 3");
551  }
552 }
#define dAi(v, i)
#define YSIZE(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void resizeNoCopy(const MultidimArray< T1 > &v)
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
#define XSIZE(v)
#define dAkij(V, k, i, j)
#define ZSIZE(v)
#define j
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173

◆ centerFFT2()

void centerFFT2 ( MultidimArray< double > &  v)

Center FFT for 2D arrays. The function is optimized for the particular case of 2D.

Definition at line 276 of file xmipp_fft.cpp.

277 {
278  if (v.getDim() == 2)
279  {
280  //Just separe the even and odd dimensions case
281  if (XSIZE(v) % 2 == 0 && YSIZE(v) % 2 == 0)
282  {
283  int xsize = XSIZE(v);
284  int xhalf = xsize / 2;
285  int yhalf = YSIZE(v) / 2;
286  double * posA = MULTIDIM_ARRAY(v);
287  double * posB = posA + xhalf;
288  double * posC = posA + xsize * yhalf;
289  double * posD = posC + xhalf;
290  double * buffer=new double[xhalf];
291  size_t bytes = xhalf * sizeof(double);
292 
293  for (int i = 0; i < yhalf; ++i,
294  posA += xsize, posB += xsize, posC += xsize, posD += xsize)
295  {
296  SWAP_ARRAY(posA, posD, bytes);
297  SWAP_ARRAY(posB, posC, bytes);
298  }
299  delete []buffer;
300  }
301  else
302  {
303  //todo: implementation for the odd case needed
304  CenterFFT(v, true);
305  }
306  }
307  else
308  std::cerr <<"bad dim: " << v.getDim() << std::endl;
309 }
#define YSIZE(v)
HBITMAP buffer
Definition: svm-toy.cpp:37
#define MULTIDIM_ARRAY(v)
#define i
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
#define XSIZE(v)
#define SWAP_ARRAY(a, b, n)
Definition: xmipp_fft.h:278

◆ CenterOriginFFT()

void CenterOriginFFT ( MultidimArray< std::complex< double > > &  v,
bool  forward 
)

Place the origin of the FFT at the center of the vector and back

Changes the real and the fourier space origin

Definition at line 386 of file xmipp_fft.cpp.

387 {
388  if ( v.getDim() == 1 )
389  {
390  // 1D
391  double xshift = -(double)(int)(XSIZE(v) / 2);
392  if (forward)
393  {
394  ShiftFFT(v, xshift);
395  CenterFFT(v, forward);
396  }
397  else
398  {
399  CenterFFT(v, forward);
400  ShiftFFT(v, -xshift);
401  }
402  }
403  else if ( v.getDim() == 2)
404  {
405  // 2D
406 
407  double xshift = -(double)(int)(XSIZE(v) / 2);
408  double yshift = -(double)(int)(YSIZE(v) / 2);
409  if (forward)
410  {
411  ShiftFFT(v, xshift, yshift);
412  CenterFFT(v, forward);
413  }
414  else
415  {
416  CenterFFT(v, forward);
417  ShiftFFT(v, -xshift, -yshift);
418  }
419  }
420  else if ( v.getDim() == 3)
421  {
422  // 3D
423  double xshift = -(double)(int)(XSIZE(v) / 2);
424  double yshift = -(double)(int)(YSIZE(v) / 2);
425  double zshift = -(double)(int)(ZSIZE(v) / 2);
426  if (forward)
427  {
428  ShiftFFT(v, xshift, yshift, zshift);
429  CenterFFT(v, forward);
430  }
431  else
432  {
433  CenterFFT(v, forward);
434  ShiftFFT(v, -xshift, -yshift, -zshift);
435  }
436  }
437  else
438  REPORT_ERROR(ERR_MULTIDIM_DIM,"CenterOriginFFT ERROR: only valis for 1D or 2D or 3D");
439 }
#define YSIZE(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void ShiftFFT(MultidimArray< std::complex< double > > &v, double xshift)
Definition: xmipp_fft.cpp:311
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
#define XSIZE(v)
#define ZSIZE(v)
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173

◆ Complex2RealImag()

void Complex2RealImag ( const MultidimArray< std::complex< double > > &  in,
MultidimArray< double > &  real,
MultidimArray< double > &  imag 
)

Conversion from complex -> real,imag

Convert complex -> real,imag Fourier transforms 2D. –

Definition at line 103 of file xmipp_fft.cpp.

106 {
107  real.resizeNoCopy(in);
108  imag.resizeNoCopy(in);
110  MULTIDIM_ARRAY(imag), MULTIDIM_SIZE(in));
111 }
#define MULTIDIM_SIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define MULTIDIM_ARRAY(v)
void Complex2RealImag(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &real, MultidimArray< double > &imag)
Definition: xmipp_fft.cpp:103

◆ contfreq2digfreq()

void contfreq2digfreq ( const Matrix1D< double > &  contfreq,
Matrix1D< double > &  digfreq,
double  pixel_size 
)
inline

Continuous to Digital frequency

The pixel size must be given in Amstrongs. The digital frequency is between [-1/2,1/2]

Definition at line 139 of file xmipp_fft.h.

142 {
143  digfreq.resizeNoCopy(contfreq);
145  VEC_ELEM(digfreq,i) = VEC_ELEM(contfreq,i) * pixel_size;
146 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define i
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458

◆ digfreq2contfreq()

void digfreq2contfreq ( const Matrix1D< double > &  digfreq,
Matrix1D< double > &  contfreq,
double  pixel_size 
)
inline

Digital to Continuous frequency

The pixel size must be given in Amstrongs. The digital frequency is between [-1/2,1/2]

Definition at line 125 of file xmipp_fft.h.

128 {
129  contfreq.resizeNoCopy(digfreq);
131  VEC_ELEM(contfreq,i) = VEC_ELEM(digfreq,i) / pixel_size;
132 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define i
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458

◆ digfreq2FFT_idx()

template<typename T >
void digfreq2FFT_idx ( T &  v,
const Matrix1D< double > &  freq,
Matrix1D< int > &  idx 
)

Frequency to index

This function can be used with vectors of any size (1,2,3). The Digital spectrum is lim:confirm bd ited between -1/2 and 1/2. If the vector has got more than 3 coordinates, then an exception is thrown

Definition at line 106 of file xmipp_fft.h.

107 {
108  if (VEC_XSIZE(freq) < 1 || VEC_XSIZE(freq) > 3)
109  REPORT_ERROR(ERR_MATRIX_SIZE, "digfreq2FFT_idx: freq is not of the correct size");
110 
111  idx.resizeNoCopy(VEC_XSIZE(freq));
112 
113  int size[3];
114  v.getSize(size);
115 
117  DIGFREQ2FFT_IDX(VEC_ELEM(freq,i), size[i], VEC_ELEM(idx,i));
118 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Problem with matrix size.
Definition: xmipp_error.h:152
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
#define DIGFREQ2FFT_IDX(freq, size, idx)
Definition: xmipp_fft.h:61
#define i
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458

◆ FFT_idx2digfreq()

template<typename T >
void FFT_idx2digfreq ( T &  v,
const Matrix1D< int > &  idx,
Matrix1D< double > &  freq 
)

Index to frequency

This function can be used with vectors of any size (1,2,3). The Digital spectrum is limited between -1/2 and 1/2. If the vector has got more than 3 coordinates, then an exception is thrown

Definition at line 80 of file xmipp_fft.h.

81 {
82  if (VEC_XSIZE(idx) < 1 || VEC_XSIZE(idx) > 3)
83  REPORT_ERROR(ERR_MATRIX_SIZE, "FFT_idx2digfreq: Index is not of the correct size");
84 
85  freq.resizeNoCopy(VEC_XSIZE(idx));
86 
87  switch (VEC_XSIZE(idx))
88  {
89  case 3:
90  FFT_IDX2DIGFREQ(VEC_ELEM(idx,2), ZSIZE(v), VEC_ELEM(freq,2));
91  case 2:
92  FFT_IDX2DIGFREQ(VEC_ELEM(idx,1), YSIZE(v), VEC_ELEM(freq,1));
93  case 1:
94  FFT_IDX2DIGFREQ(VEC_ELEM(idx,0), XSIZE(v), VEC_ELEM(freq,0));
95  }
96 }
#define YSIZE(v)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Problem with matrix size.
Definition: xmipp_error.h:152
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
#define FFT_IDX2DIGFREQ(idx, size, freq)
Definition: xmipp_fft.h:46
#define XSIZE(v)
#define ZSIZE(v)
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458

◆ FourierTransform()

void FourierTransform ( const MultidimArray< double > &  in,
MultidimArray< std::complex< double > > &  out 
)

Direct Fourier Transform

Direct Fourier Transform nD ----------------------------------------—

Definition at line 124 of file xmipp_fft.cpp.

126 {
127  if ( in.getDim() == 1 )
128  {
129  // 1D
130  int N = XSIZE(in);
131  MultidimArray<double> re(in), tmp(N), im(N), cas(N);
132  out.resizeNoCopy(N);
133 
134  GetCaS(MULTIDIM_ARRAY(cas), N);
136  MULTIDIM_ARRAY(tmp), MULTIDIM_ARRAY(cas), N);
138  MULTIDIM_ARRAY(out), N);
139  }
140  else
141  {
142  // 2D and 3D
143  int Status;
144  MultidimArray<double> re(in), im;
145  im.resizeNoCopy(in);
146  out.resizeNoCopy(in);
148  MULTIDIM_ARRAY(im), XSIZE(in), YSIZE(in), ZSIZE(in), &Status);
149  RealImag2Complex(re,im,out);
150  }
151 
152 }
#define YSIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define MULTIDIM_ARRAY(v)
int DftRealToRealImaginary(double R2Re[], double ImOut[], double *Tmp, double CaS[], long SignalLength)
int GetCaS(double CaS[], long SignalLength)
int VolumeDftRealToRealImaginary(double *Re2Re, double *ImOut, long Nx, long Ny, long Nz, int *Status)
void RealImag2Complex(const MultidimArray< double > &real, const MultidimArray< double > &imag, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:114
#define XSIZE(v)
#define ZSIZE(v)

◆ FourierTransformHalf()

void FourierTransformHalf ( const MultidimArray< double > &  in,
MultidimArray< std::complex< double > > &  out 
)

Direct Fourier Transform, output half of (centro-symmetric) transform

Direct Fourier Transform 1D / 2D, output half of (centro-symmetric) transform -—

Definition at line 187 of file xmipp_fft.cpp.

189 {
190 
192  FourierTransform(in, aux);
193  Whole2Half(aux, out);
194 }
void Whole2Half(const MultidimArray< std::complex< double > > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:34
void FourierTransform(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:124

◆ Half2Whole()

void Half2Whole ( const MultidimArray< std::complex< double > > &  in,
MultidimArray< std::complex< double > > &  out,
size_t  oridim 
)

Conversion from half -> whole

Convert half -> whole of (centro-symmetric) Fourier transforms 2D. –

Definition at line 66 of file xmipp_fft.cpp.

68 {
69  if (in.getDim() == 1)
70  {
71  // 1D
72  out.resizeNoCopy(oridim);
73  for (size_t j = 0; j < XSIZE(in); j++)
75  for (size_t j = XSIZE(in); j < oridim; j++)
76  DIRECT_A1D_ELEM(out,j) = conj(DIRECT_A1D_ELEM(in,oridim - j));
77  }
78  else if (in.getDim() == 2)
79  {
80  // 2D
81  out.resizeNoCopy(oridim, XSIZE(in));
82 
83  // Old part
84  for (size_t i = 0; i < YSIZE(in); i++)
85  for (size_t j = 0; j < XSIZE(in); j++)
86  dAij(out, i, j) = dAij(in, i, j);
87 
88  // Complete first column of old part
89  for (size_t j = YSIZE(in); j < XSIZE(in); j++)
90  dAij(out, 0, j) = conj(dAij(in, 0, XSIZE(in) - j));
91 
92  // New part
93  for (size_t i = YSIZE(in); i < oridim; i++)
94  {
95  dAij(out, i, 0) = conj(dAij(in, oridim - i, 0));
96  for (size_t j = 1; j < XSIZE(in); j++)
97  dAij(out, i, j) = conj(dAij(in, oridim - i, XSIZE(in) - j));
98  }
99  }
100 }
#define YSIZE(v)
alglib::complex conj(const alglib::complex &z)
Definition: ap.cpp:4988
void resizeNoCopy(const MultidimArray< T1 > &v)
#define dAij(M, i, j)
#define i
#define DIRECT_A1D_ELEM(v, i)
#define XSIZE(v)
#define j

◆ InverseFourierTransform()

void InverseFourierTransform ( const MultidimArray< std::complex< double > > &  in,
MultidimArray< double > &  out 
)

Inverse Fourier Transform

Inverse Fourier Transform nD. --------------------------------------—

Definition at line 155 of file xmipp_fft.cpp.

157 {
158  if ( in.getDim() == 1 )
159  {
160  // 1D
161  int N = XSIZE(in);
162  MultidimArray<double> tmp(N), im(N), cas(N);
163  out.resizeNoCopy(N);
164 
165  GetCaS(MULTIDIM_ARRAY(cas), N);
167  MULTIDIM_ARRAY(im), N);
169  MULTIDIM_ARRAY(tmp), MULTIDIM_ARRAY(cas), N);
170  }
171  else
172  {
173  // 2D and 3D
174  int Status;
176  out.resizeNoCopy(in);
177  im.resizeNoCopy(in);
178  Complex2RealImag(in, out, im);
180  MULTIDIM_ARRAY(im),
181  XSIZE(in), YSIZE(in), ZSIZE(in), &Status);
182  }
183 }
#define YSIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define MULTIDIM_ARRAY(v)
int InvDftRealImaginaryToReal(double Re2R[], double ImIn[], double *Tmp, double CaS[], long SignalLength)
int VolumeInvDftRealImaginaryToReal(double *Re2Re, double *ImIn, long Nx, long Ny, long Nz, int *Status)
int GetCaS(double CaS[], long SignalLength)
#define XSIZE(v)
#define ZSIZE(v)
void Complex2RealImag(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &real, MultidimArray< double > &imag)
Definition: xmipp_fft.cpp:103

◆ InverseFourierTransformHalf()

void InverseFourierTransformHalf ( const MultidimArray< std::complex< double > > &  in,
MultidimArray< double > &  out,
int  oridim 
)

Inverse Fourier Transform 1D, input half of (centro-symmetric) transform

Inverse Fourier Transform 1D / 2D, input half of (centro-symmetric) transform -—

Definition at line 197 of file xmipp_fft.cpp.

199 {
200 
202  Half2Whole(in, aux, oridim);
203  InverseFourierTransform(aux, out);
204  out.setXmippOrigin();
205 }
void InverseFourierTransform(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out)
Definition: xmipp_fft.cpp:155
void Half2Whole(const MultidimArray< std::complex< double > > &in, MultidimArray< std::complex< double > > &out, size_t oridim)
Definition: xmipp_fft.cpp:66

◆ RealImag2Complex()

void RealImag2Complex ( const MultidimArray< double > &  real,
const MultidimArray< double > &  imag,
MultidimArray< std::complex< double > > &  out 
)

Conversion from real,imag -> complex

Convert real,imag -> complex Fourier transforms 3D. –

Definition at line 114 of file xmipp_fft.cpp.

117 {
118  out.resizeNoCopy(real);
120  MULTIDIM_ARRAY(out), MULTIDIM_SIZE(real));
121 }
#define MULTIDIM_SIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define MULTIDIM_ARRAY(v)
void RealImag2Complex(const MultidimArray< double > &real, const MultidimArray< double > &imag, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:114

◆ ShiftFFT() [1/3]

void ShiftFFT ( MultidimArray< std::complex< double > > &  v,
double  xshift 
)

FFT shift 1D

Calculates the Fourier Transform of the shifted real-space vector by phase shifts in Fourier space

Definition at line 311 of file xmipp_fft.cpp.

313 {
314  v.checkDimension(1);
315  double dotp, a, b, c, d, ac, bd, ab_cd;
316  double xxshift = xshift / (double)XSIZE(v);
318  {
319  dotp = -2 * PI * ((double)(i) * xxshift);
320  a = cos(dotp);
321  b = sin(dotp);
322  c = DIRECT_A1D_ELEM(v,i).real();
323  d = DIRECT_A1D_ELEM(v,i).imag();
324  ac = a * c;
325  bd = b * d;
326  ab_cd = (a + b) * (c + d); // (ab_cd-ac-bd = ad+bc : but needs 4 multiplications)
327  DIRECT_A1D_ELEM(v,i) = std::complex<double>(ac - bd, ab_cd - ac - bd);
328  }
329 }
doublereal * c
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(v)
#define i
doublereal * d
#define DIRECT_A1D_ELEM(v, i)
doublereal * b
#define XSIZE(v)
#define PI
Definition: tools.h:43
doublereal * a

◆ ShiftFFT() [2/3]

void ShiftFFT ( MultidimArray< std::complex< double > > &  v,
double  xshift,
double  yshift 
)

FFT shift 2D

Calculates the Fourier Transform of the shifted real-space vector by phase shifts in Fourier space

Definition at line 331 of file xmipp_fft.cpp.

333 {
334  v.checkDimension(2);
335  double dotp, a, b, c, d, ac, bd, ab_cd;
336  double xxshift = xshift / (double)XSIZE(v);
337  double yyshift = yshift / (double)YSIZE(v);
339  {
340  dotp = -2 * PI * ((double)(j) * xxshift + (double)(i) * yyshift);
341  a = cos(dotp);
342  b = sin(dotp);
343  c = DIRECT_A2D_ELEM(v,i,j).real();
344  d = DIRECT_A2D_ELEM(v,i,j).imag();
345  ac = a * c;
346  bd = b * d;
347  ab_cd = (a + b) * (c + d);
348  DIRECT_A2D_ELEM(v,i,j) = std::complex<double>(ac - bd, ab_cd - ac - bd);
349  }
350 }
#define YSIZE(v)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
doublereal * c
#define DIRECT_A2D_ELEM(v, i, j)
#define i
doublereal * d
doublereal * b
#define XSIZE(v)
#define j
#define PI
Definition: tools.h:43
doublereal * a

◆ ShiftFFT() [3/3]

void ShiftFFT ( MultidimArray< std::complex< double > > &  v,
double  xshift,
double  yshift,
double  zshift 
)

FFT shift 3D

Calculates the Fourier Transform of the shifted real-space vector by phase shifts in Fourier space

Definition at line 352 of file xmipp_fft.cpp.

354 {
355  v.checkDimension(3);
356  double dotp, a, b, c, d, ac, bd, ab_cd;
357  double xxshift = -2 * PI * xshift / (double)XSIZE(v);
358  double yyshift = -2 * PI * yshift / (double)YSIZE(v);
359  double zzshift = -2 * PI * zshift / (double)ZSIZE(v);
360  for (size_t k=0; k<ZSIZE(v); ++k)
361  {
362  double zdot=(double)(k) * zzshift;
363  for (size_t i=0; i<YSIZE(v); ++i)
364  {
365  double zydot=zdot+(double)(i) * yyshift;
366  for (size_t j=0; j<XSIZE(v); ++j)
367  {
368  double *ptrv_kij=(double *)&DIRECT_A3D_ELEM(v,k,i,j);
369  dotp = (double)(j) * xxshift + zydot;
370  //sincos(dotp,&b,&a);
371  b = sin(dotp);
372  a = cos(dotp);
373  c = *ptrv_kij;
374  d = *(ptrv_kij+1);
375  ac = a * c;
376  bd = b * d;
377  ab_cd = (a + b) * (c + d);
378  *ptrv_kij = ac - bd;
379  *(ptrv_kij+1) = ab_cd - ac - bd;
380  }
381  }
382  }
383 }
#define YSIZE(v)
doublereal * c
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
doublereal * d
doublereal * b
#define XSIZE(v)
#define ZSIZE(v)
#define DIRECT_A3D_ELEM(v, k, i, j)
#define j
#define PI
Definition: tools.h:43
doublereal * a

◆ Whole2Half()

void Whole2Half ( const MultidimArray< std::complex< double > > &  in,
MultidimArray< std::complex< double > > &  out 
)

Conversion from whole -> half

Convert whole -> half of (centro-symmetric) Fourier transforms 1D. –

Definition at line 34 of file xmipp_fft.cpp.

36 {
37  if (in.getDim() == 1)
38  {
39  // 1D
40  int ldim = (int)(XSIZE(in) / 2) + 1;
41  out.resize(ldim);
42  for (int j = 0; j < ldim; j++)
43  out(j) = in(j);
44  }
45  else if (in.getDim() == 2)
46  {
47  // 2D
48  // This assumes squared images...
49  int ldim = (int)(YSIZE(in) / 2) + 1;
50 
51  out.initZeros(ldim, XSIZE(in));
52  // Fill first column only half
53  for (int j = 0; j < ldim; j++)
54  dAij(out, 0, j) = dAij(in, 0, j);
55  // Fill rest
56  for (int i = 1; i < ldim; i++)
57  for (size_t j = 0; j < XSIZE(in); j++)
58  dAij(out, i, j) = dAij(in, i, j);
59  }
60  else
61  REPORT_ERROR(ERR_MULTIDIM_DIM,"ERROR: Whole2Half only implemented for 1D and 2D multidimArrays");
62 
63 }
#define YSIZE(v)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
#define dAij(M, i, j)
#define i
int in
#define XSIZE(v)
#define j
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
void initZeros(const MultidimArray< T1 > &op)

◆ xmipp2CTF()

void xmipp2CTF ( const MultidimArray< double > &  input,
MultidimArray< double > &  output 
)

Xmipp image -> Xmipp CTF. The log10 is taken, outliers rejected and the image is reorganized.

Definition at line 472 of file xmipp_fft.cpp.

473 {
474  output = input;
475  CenterFFT(output, true);
476 
477  // Prepare PSD part
478  double min_val = output(0, XSIZE(output) - 1);
479  double max_val = min_val;
480  bool first = true;
481  int Xdim = XSIZE(output);
482  int Ydim = YSIZE(output);
484  {
485  if ((i < Ydim / 2 && j >= Xdim / 2) || (i >= Ydim / 2 && j < Xdim / 2))
486  {
487  if (output(i, j) > XMIPP_EQUAL_ACCURACY &&
488  (output(i, j) < min_val || first))
489  min_val = output(i, j);
490  if (output(i, j) > XMIPP_EQUAL_ACCURACY &&
491  (output(i, j) > max_val || first))
492  {
493  max_val = output(i, j);
494  first = false;
495  }
496  }
497  }
498  MultidimArray<double> left(YSIZE(output), XSIZE(output));
499  min_val = 10 * log10(min_val);
501  {
502  if ((i < Ydim / 2 && j >= Xdim / 2) || (i >= Ydim / 2 && j < Xdim / 2))
503  {
504  if (output(i, j) > XMIPP_EQUAL_ACCURACY)
505  left(i, j) = 10 * log10(output(i, j));
506  else
507  left(i, j) = min_val;
508  }
509  }
510  reject_outliers(left);
511 
512  // Join both parts
514  if ((i < Ydim / 2 && j >= Xdim / 2) || (i >= Ydim / 2 && j < Xdim / 2))
515  output(i, j) = left(i, j);
516  else
517  output(i, j) = ABS(output(i, j));
518 }
#define YSIZE(v)
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
glob_log first
void reject_outliers(T &v, double percentil_out=0.25)
Definition: histogram.h:605
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define XSIZE(v)
#define ABS(x)
Definition: xmipp_macros.h:142
void log10(Image< double > &op)
#define j

◆ xmipp2PSD()

template<typename T >
void xmipp2PSD ( const MultidimArray< T > &  input,
MultidimArray< T > &  output,
bool  takeLog = true 
)

Xmipp image -> Xmipp PSD. The log10 is taken, outliers rejected and the image is reorganized.

Definition at line 443 of file xmipp_fft.cpp.

445 {
446  output = input;
447  CenterFFT(output, true);
448  if (takeLog) {
449  auto min_val = std::numeric_limits<T>::max();
451  {
452  auto pixval=A2D_ELEM(output,i,j);
453  if (pixval > 0 && pixval < min_val)
454  min_val = pixval;
455  }
456  min_val = 10 * log10(min_val);
458  {
459  auto pixval=A2D_ELEM(output,i,j);
460  if (pixval > 0)
461  A2D_ELEM(output,i,j) = 10 * log10(pixval);
462  else
463  A2D_ELEM(output,i,j) = min_val;
464  }
465  }
466  reject_outliers(output);
467 }
#define A2D_ELEM(v, i, j)
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
void reject_outliers(T &v, double percentil_out=0.25)
Definition: histogram.h:605
void max(Image< double > &op1, const Image< double > &op2)
void log10(Image< double > &op)
#define j