Xmipp  v3.23.11-Nereus
xmipp_fftw.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Roberto Marabini (roberto@cnb.csic.es)
4  * Carlos Oscar S. Sorzano (coss@cnb.csic.es)
5  *
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307 USA
22  *
23  * All comments concerning this program package may be sent to the
24  * e-mail address 'xmipp@cnb.csic.es'
25  ***************************************************************************/
26 
27 #include "xmipp_fftw.h"
28 #include "args.h"
29 #include "transformations.h"
30 #include <string.h>
31 #include <pthread.h>
32 
33 static pthread_mutex_t fftw_plan_mutex = PTHREAD_MUTEX_INITIALIZER;
34 bool planCreated=false;
35 int nInstances=0;
36 
37 // Constructors and destructors --------------------------------------------
39 {
40  init();
41  nthreads=1;
42  pthread_mutex_lock(&fftw_plan_mutex);
43  nInstances++;
44  pthread_mutex_unlock(&fftw_plan_mutex);
45  threadsSetOn=false;
46  normSign = FFTW_FORWARD;
47 }
48 
50 {
51  init();
52  pthread_mutex_lock(&fftw_plan_mutex);
53  nInstances++;
54  pthread_mutex_unlock(&fftw_plan_mutex);
55  nthreads=1;
56  threadsSetOn=false;
57  normSign = _normSign;
58 }
59 
61 {
62  REPORT_ERROR(ERR_UNCLASSIFIED,"Fourier transformers should not be copied");
63 }
64 
66 {
67  REPORT_ERROR(ERR_UNCLASSIFIED,"Fourier transformers should not be copied");
68 }
70 {
71  fReal=NULL;
72  fComplex=NULL;
73  fPlanForward = NULL;
74  fPlanBackward = NULL;
75  dataPtr = NULL;
76  complexDataPtr = NULL;
77 }
78 
80 {
81  fFourier.clear();
82  // Anything to do with plans has to be protected for threads!
83  pthread_mutex_lock(&fftw_plan_mutex);
84  if (fPlanForward !=NULL)
85  fftw_destroy_plan(fPlanForward);
86  if (fPlanBackward!=NULL)
87  fftw_destroy_plan(fPlanBackward);
88  pthread_mutex_unlock(&fftw_plan_mutex);
89 
90  init();
91 }
92 
94 {
95  clear();
96 
97  pthread_mutex_lock(&fftw_plan_mutex);
98  nInstances--;
99 
100  // Check if a plan was already created.
101  if (planCreated)
102  {
103  // Check if this is last instance of a FFT.
104  if (nInstances == 0)
105  {
106  destroyThreads();
107  planCreated = false;
108  // Don't call cleanup.
109  // There might be other transformers, and this call would
110  // invalidate it's plans
111 // cleanup();
112  }
113  }
114  pthread_mutex_unlock(&fftw_plan_mutex);
115 }
116 
117 // Initialization ----------------------------------------------------------
119 {
120  return (*fReal);
121 }
122 
124 {
125  return (*fComplex);
126 }
127 
128 
130 {
131  bool updatePlan=false;
132  if (fReal==NULL)
133  updatePlan=true;
134  else if (dataPtr!=MULTIDIM_ARRAY(input))
135  updatePlan=true;
136  else
137  updatePlan=!(fReal->sameShape(input));
138  fFourier.resizeNoCopy(ZSIZE(input),YSIZE(input),XSIZE(input)/2+1);
139  fReal=&input;
140 
141  if (updatePlan)
142  {
144  }
145 }
146 
148 {
149  int ndim=3;
150  if (ZSIZE(*fReal)==1)
151  {
152  ndim=2;
153  if (YSIZE(*fReal)==1)
154  ndim=1;
155  }
156  int N[3];
157  switch (ndim)
158  {
159  case 1:
160  N[0]=XSIZE(*fReal);
161  break;
162  case 2:
163  N[0]=YSIZE(*fReal);
164  N[1]=XSIZE(*fReal);
165  break;
166  case 3:
167  N[0]=ZSIZE(*fReal);
168  N[1]=YSIZE(*fReal);
169  N[2]=XSIZE(*fReal);
170  break;
171  }
172 
173  pthread_mutex_lock(&fftw_plan_mutex);
174  if (fPlanForward!=NULL)
175  fftw_destroy_plan(fPlanForward);
176  fPlanForward=NULL;
177  fPlanForward = fftw_plan_dft_r2c(ndim, N, MULTIDIM_ARRAY(*fReal),
178  (fftw_complex*) MULTIDIM_ARRAY(fFourier), FFTW_ESTIMATE);
179  if (fPlanBackward!=NULL)
180  fftw_destroy_plan(fPlanBackward);
181  fPlanBackward=NULL;
182  fPlanBackward = fftw_plan_dft_c2r(ndim, N,
183  (fftw_complex*) MULTIDIM_ARRAY(fFourier), MULTIDIM_ARRAY(*fReal),
184  FFTW_ESTIMATE);
185  if (fPlanForward == NULL || fPlanBackward == NULL)
186  REPORT_ERROR(ERR_PLANS_NOCREATE, "FFTW plans cannot be created");
188  planCreated = true;
189  pthread_mutex_unlock(&fftw_plan_mutex);
190 }
191 
192 void FourierTransformer::setReal(MultidimArray<std::complex<double> > &input)
193 {
194  bool recomputePlan=false;
195  if (fComplex==NULL)
196  recomputePlan=true;
197  else if (complexDataPtr!=MULTIDIM_ARRAY(input))
198  recomputePlan=true;
199  else
200  recomputePlan=!(fComplex->sameShape(input));
201  fFourier.resizeNoCopy(input);
202  fComplex=&input;
203 
204  if (recomputePlan)
205  {
206  int ndim=3;
207  if (ZSIZE(input)==1)
208  {
209  ndim=2;
210  if (YSIZE(input)==1)
211  ndim=1;
212  }
213  int *N = new int[ndim];
214  switch (ndim)
215  {
216  case 1:
217  N[0]=XSIZE(input);
218  break;
219  case 2:
220  N[0]=YSIZE(input);
221  N[1]=XSIZE(input);
222  break;
223  case 3:
224  N[0]=ZSIZE(input);
225  N[1]=YSIZE(input);
226  N[2]=XSIZE(input);
227  break;
228  }
229 
230  pthread_mutex_lock(&fftw_plan_mutex);
231  if (fPlanForward!=NULL)
232  fftw_destroy_plan(fPlanForward);
233  fPlanForward=NULL;
234  fPlanForward = fftw_plan_dft(ndim, N, (fftw_complex*) MULTIDIM_ARRAY(*fComplex),
235  (fftw_complex*) MULTIDIM_ARRAY(fFourier), FFTW_FORWARD, FFTW_ESTIMATE);
236  if (fPlanBackward!=NULL)
237  fftw_destroy_plan(fPlanBackward);
238  fPlanBackward=NULL;
239  fPlanBackward = fftw_plan_dft(ndim, N, (fftw_complex*) MULTIDIM_ARRAY(fFourier),
240  (fftw_complex*) MULTIDIM_ARRAY(*fComplex), FFTW_BACKWARD, FFTW_ESTIMATE);
241  if (fPlanForward == NULL || fPlanBackward == NULL)
242  REPORT_ERROR(ERR_PLANS_NOCREATE, "FFTW plans cannot be created");
243  delete [] N;
245  pthread_mutex_unlock(&fftw_plan_mutex);
246  }
247 }
248 
249 void FourierTransformer::setFourier(const MultidimArray<std::complex<double> > &inputFourier)
250 {
251  memcpy(MULTIDIM_ARRAY(fFourier),MULTIDIM_ARRAY(inputFourier),
252  MULTIDIM_SIZE(inputFourier)*2*sizeof(double));
253 }
254 
255 // Transform ---------------------------------------------------------------
257 {
258  if (sign == FFTW_FORWARD)
259  {
260  fftw_execute(fPlanForward);
261 
262  if (sign == normSign)
263  {
264  unsigned long int size=0;
265  if(fReal!=NULL)
266  size = MULTIDIM_SIZE(*fReal);
267  else if (fComplex!= NULL)
268  size = MULTIDIM_SIZE(*fComplex);
269  else
270  REPORT_ERROR(ERR_UNCLASSIFIED,"No complex nor real data defined");
271 
272  double isize=1.0/size;
273  double *ptr=(double*)MULTIDIM_ARRAY(fFourier);
274  size_t nmax=(fFourier.nzyxdim/4)*4;
275  for (size_t n=0; n<nmax; n+=4)
276  {
277  *ptr++ *= isize;
278  *ptr++ *= isize;
279  *ptr++ *= isize;
280  *ptr++ *= isize;
281  *ptr++ *= isize;
282  *ptr++ *= isize;
283  *ptr++ *= isize;
284  *ptr++ *= isize;
285  }
286  for (size_t n=nmax; n<fFourier.nzyxdim; ++n)
287  {
288  *ptr++ *= isize;
289  *ptr++ *= isize;
290  }
291  }
292  }
293  else if (sign == FFTW_BACKWARD)
294  {
295  fftw_execute(fPlanBackward);
296 
297  if (sign == normSign)
298  {
299  unsigned long int size=0;
300  if(fReal!=NULL)
301  {
302  size = MULTIDIM_SIZE(*fReal);
303  double isize=1.0/size;
305  DIRECT_MULTIDIM_ELEM(*fReal,n) *= isize;
306  }
307  else if (fComplex!= NULL)
308  {
309  size = MULTIDIM_SIZE(*fComplex);
310  double isize=1.0/size;
311  double *ptr=(double*)MULTIDIM_ARRAY(*fComplex);
313  {
314  *ptr++ *= isize;
315  *ptr++ *= isize;
316  }
317  }
318  else
319  REPORT_ERROR(ERR_UNCLASSIFIED,"No complex nor real data defined");
320  }
321  }
322 }
323 
325 {
326  Transform(FFTW_FORWARD);
327 }
328 
330 {
331  Transform(FFTW_BACKWARD);
332 }
333 
334 // Inforce Hermitian symmetry ---------------------------------------------
336 {
337  int ndim=3;
338  int Zdim=ZSIZE(*fReal);
339  int Ydim=YSIZE(*fReal);
340  if (Zdim==1)
341  {
342  ndim=2;
343  if (Ydim==1)
344  ndim=1;
345  }
346  int yHalf=Ydim/2;
347  if (Ydim%2==0)
348  yHalf--;
349  int zHalf=Zdim/2;
350  if (Zdim%2==0)
351  zHalf--;
352  switch (ndim)
353  {
354  case 2:
355  for (int i=1; i<=yHalf; i++)
356  {
357  int isym=intWRAP(-i,0,Ydim-1);
358  std::complex<double> mean=0.5*(
360  conj(DIRECT_A2D_ELEM(fFourier,isym,0)));
361  DIRECT_A2D_ELEM(fFourier,i,0)=mean;
362  DIRECT_A2D_ELEM(fFourier,isym,0)=conj(mean);
363  }
364  break;
365  case 3:
366  for (int k=0; k<Zdim; k++)
367  {
368  int ksym=intWRAP(-k,0,Zdim-1);
369  for (int i=1; i<=yHalf; i++)
370  {
371  int isym=intWRAP(-i,0,Ydim-1);
372  std::complex<double> mean=0.5*(
374  conj(DIRECT_A3D_ELEM(fFourier,ksym,isym,0)));
375  DIRECT_A3D_ELEM(fFourier,k,i,0)=mean;
376  DIRECT_A3D_ELEM(fFourier,ksym,isym,0)=conj(mean);
377  }
378  }
379  for (int k=1; k<=zHalf; k++)
380  {
381  int ksym=intWRAP(-k,0,Zdim-1);
382  std::complex<double> mean=0.5*(
384  conj(DIRECT_A3D_ELEM(fFourier,ksym,0,0)));
385  DIRECT_A3D_ELEM(fFourier,k,0,0)=mean;
386  DIRECT_A3D_ELEM(fFourier,ksym,0,0)=conj(mean);
387  }
388  break;
389  }
390 }
391 
392 /* FFT Magnitude ------------------------------------------------------- */
393 void FFT_magnitude(const MultidimArray< std::complex<double> > &v,
395 {
396  mag.resizeNoCopy(v);
397  double * ptrv=(double *)MULTIDIM_ARRAY(v);
399  {
400  double re=*ptrv;
401  double im=*(ptrv+1);
402  DIRECT_MULTIDIM_ELEM(mag, n) = sqrt(re*re+im*im);
403  ptrv+=2;
404  }
405 }
406 
407 /* FFT Phase ------------------------------------------------------- */
408 void FFT_phase(const MultidimArray< std::complex<double> > &v,
409  MultidimArray<double> &phase)
410 {
411  phase.resizeNoCopy(v);
413  DIRECT_MULTIDIM_ELEM(phase, n) = atan2(DIRECT_MULTIDIM_ELEM(v,n).imag(), DIRECT_MULTIDIM_ELEM(v, n).real());
414 }
415 
416 void radial_magnitude(const MultidimArray<double> & v, MultidimArray< std::complex< double > > &V,
417  MultidimArray< double >& radialMagnitude)
418 {
419  FourierTransform(v,V);
421  FFT_magnitude(V,Vmag);
422  CenterFFT(Vmag,true);
423  Vmag.setXmippOrigin();
424  MultidimArray<int> radialCount;
425  Matrix1D<int> center(3);
426  radialAverage(Vmag,center,radialMagnitude,radialCount);
427 }
428 
430  const MultidimArray<double> &kernel,
431  MultidimArray<double> &result)
432 {
433  if (&result != &img)
434  result = img;
435 
436  MultidimArray<double> imgTemp;
438  FourierTransformer transformer1(FFTW_BACKWARD), transformer2(FFTW_BACKWARD);
439 
440  transformer2.FourierTransform((MultidimArray<double> &)kernel, FFTK, false);
441 
442  for (size_t n = 0; n < ZSIZE(result); n++)
443  {
444  imgTemp.aliasSlice(result, n);
445  transformer1.FourierTransform(imgTemp, FFTIm, false);
446 
449 
450  transformer1.inverseFourierTransform();
451 
452  CenterFFT(imgTemp, false);
453  }
454 
455 }
456 
458  MultidimArray<double> &kernel,
459  MultidimArray<double> &result)
460 {
461  FourierTransformer transformer1, transformer2;
463  transformer1.FourierTransform(img, FFT1, false);
464  result=kernel;
465  transformer2.FourierTransform(result, FFT2, false);
466 
467  // Multiply FFT1 * FFT2'
468  double dSize=MULTIDIM_SIZE(img);
469  double a, b, c, d; // a+bi, c+di
470  double *ptrFFT2=(double*)MULTIDIM_ARRAY(FFT2);
471  double *ptrFFT1=(double*)MULTIDIM_ARRAY(FFT1);
473  {
474  a=*ptrFFT1++;
475  b=*ptrFFT1++;
476  c=(*ptrFFT2)*dSize;
477  d=(*(ptrFFT2+1))*dSize;
478  *ptrFFT2++ = a*c-b*d;
479  *ptrFFT2++ = b*c+a*d;
480  }
481 
482  // Invert the product, in order to obtain the correlation image
483  transformer2.inverseFourierTransform();
484 
485  // Center the resulting image to compensate for phase shift
486  CenterFFT(result, false);
487 }
488 
489 // Fourier ring correlation -----------------------------------------------
490 //#define SAVE_REAL_PART
493  double sampling_rate,
496  MultidimArray< double >& frc_noise,
498  MultidimArray< double >& error_l2,
499  bool dodpr,
500  bool doRfactor,
501  double minFreq,
502  double maxFreq,
503  double * rFactor)
504 {
505  if (!m1.sameShape(m2))
506  REPORT_ERROR(ERR_MULTIDIM_SIZE,"MultidimArrays have different shapes!");
507 
508  int m1sizeX = XSIZE(m1), m1sizeY = YSIZE(m1), m1sizeZ = ZSIZE(m1);
509 
511  FourierTransformer transformer1(FFTW_BACKWARD);
512  transformer1.FourierTransform(m1, FT1, false);
513 
514 //#define DEBUG
515 #ifdef DEBUG
516  std::cerr << "FT1" << FT1 << std::endl;
517 #endif
518 #undef DEBUG
519 
520 
521  m1.clear(); // Free memory
522 
524  FourierTransformer transformer2(FFTW_BACKWARD);
525  transformer2.FourierTransform(m2, FT2, false);
526  m2.clear(); // Free memory
527 
528  MultidimArray< int > radial_count(m1sizeX/2+1);
529  MultidimArray<double> num, den1, den2, den_dpr;
530  Matrix1D<double> f(3);
531  //to calculate r-factor
532  double rFactorNumerator=0;
533  double rFactorDenominator=0;
534 
535 
536  num.initZeros(radial_count);
537  den1.initZeros(radial_count);
538  den2.initZeros(radial_count);
539 
540  //dpr calculation takes for ever in large volumes
541  //since atan2 is called many times
542  //until atan2 is changed by a table let us make dpr an option
543  if (dodpr)
544  {
545  dpr.initZeros(radial_count);
546  den_dpr.initZeros(radial_count);
547  }
548  freq.initZeros(radial_count);
549  frc.initZeros(radial_count);
550  frc_noise.initZeros(radial_count);
551  error_l2.initZeros(radial_count);
552 #ifdef SAVE_REAL_PART
553 
554  std::vector<double> *realPart=
555  new std::vector<double>[XSIZE(radial_count)];
556 #endif
557 
558  int sizeZ_2 = m1sizeZ/2;
559  if (sizeZ_2==0)
560  sizeZ_2=1;
561  double isizeZ = 1.0/m1sizeZ;
562  int sizeY_2 = m1sizeY/2;
563  double iysize = 1.0/m1sizeY;
564  int sizeX_2 = m1sizeX/2;
565  double ixsize = 1.0/m1sizeX;
566  double R;
567 
568  int ZdimFT1=(int)ZSIZE(FT1);
569  int YdimFT1=(int)YSIZE(FT1);
570  int XdimFT1=(int)XSIZE(FT1);
571 
572  double maxFreq_2 =0.;
573  maxFreq_2 = maxFreq * maxFreq;
574  for (int k=0; k<ZdimFT1; k++)
575  {
576  FFT_IDX2DIGFREQ_FAST(k,m1sizeZ,sizeZ_2,isizeZ,ZZ(f));
577  double fz2=ZZ(f)*ZZ(f);
578  for (int i=0; i<YdimFT1; i++)
579  {
580  FFT_IDX2DIGFREQ_FAST(i,YSIZE(m1),sizeY_2, iysize, YY(f));
581  double fz2_fy2=fz2 + YY(f)*YY(f);
582  for (int j=0; j<XdimFT1; j++)
583  {
584  FFT_IDX2DIGFREQ_FAST(j,m1sizeX, sizeX_2, ixsize, XX(f));
585 
586  double R2 =fz2_fy2 + XX(f)*XX(f);
587  if (R2>maxFreq_2)
588  continue;
589 
590  R = sqrt(R2);
591  int idx = (int)round(R * m1sizeX);
592  std::complex<double> &z1 = dAkij(FT1, k, i, j);
593  std::complex<double> &z2 = dAkij(FT2, k, i, j);
594  double absz1 = abs(z1);
595  double absz2 = abs(z2);
596  dAi(num,idx) += real(conj(z1) * z2);
597  dAi(den1,idx) += absz1*absz1;
598  dAi(den2,idx) += absz2*absz2;
599  dAi(error_l2,idx) += abs(z1-z2);
600  //for calculating r-factor
601  if ( R > minFreq && R < maxFreq)
602  {
603  rFactorNumerator += fabs(absz1 - absz2);
604  rFactorDenominator += absz1;
605  }
606 
607  if (dodpr) //this takes to long for a huge volume
608  {
609  double phaseDiff=atan2(z1.imag(),z1.real()) - atan2(z2.imag(),z2.real());
610  phaseDiff = RAD2DEG(phaseDiff);
611  phaseDiff = realWRAP(phaseDiff,-180, 180);
612  dAi(dpr,idx) += ((absz1+absz2)*phaseDiff*phaseDiff);
613  dAi(den_dpr,idx) += (absz1+absz2);
614 #ifdef SAVE_REAL_PART
615 
616  realPart[idx].push_back(z1.real());
617 #endif
618 
619  }
620  dAi(radial_count,idx)++;
621  }
622  }
623  }
624  //to calculate r-factor
625  if (doRfactor)
626  {
627  //std::cout << "rFactorNumerator = " << rFactorNumerator << std::endl;
628  //std::cout << "rFactorDenominator = " << rFactorDenominator << std::endl;
629  *rFactor = rFactorNumerator / rFactorDenominator;
630 
631  //std::cout << "R-factor = " << rFactorValue << std::endl;
632  //*rFactor = rFactorValue;
633  //std::cout << "R-rFactor = " << *rFactor << std::endl;
634  }
635 
637  {
638  dAi(freq,i) = (double) i / (m1sizeX * sampling_rate);
639  dAi(frc,i) = dAi(num,i)/sqrt(dAi(den1,i)*dAi(den2,i));
640  dAi(frc_noise,i) = 2 / sqrt((double) dAi(radial_count,i));
641  dAi(error_l2,i) /= dAi(radial_count,i);
642 
643  if (dodpr)
644  dAi(dpr,i) = sqrt(dAi(dpr,i) / dAi(den_dpr,i));
645 #ifdef SAVE_REAL_PART
646 
647  std::ofstream fhOut;
648  fhOut.open(((std::string)"PPP_RealPart_"+integerToString(i)+".txt").
649  c_str());
650  for (int j=0; j<realPart[i].size(); j++)
651  fhOut << realPart[i][j] << std::endl;
652  fhOut.close();
653 #endif
654 
655  }
656 }
657 
658 void scaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArray<double> &mdaIn, MultidimArray<double> &mdaOut, int nThreads)
659 {
660  //Mmem = *this
661  //memory for fourier transform output
663  // Perform the Fourier transform
664  FourierTransformer transformerM;
665  transformerM.setThreadsNumber(nThreads);
666  transformerM.FourierTransform(mdaIn, MmemFourier, false);
667 
668  // Create space for the downsampled image and its Fourier transform
669  mdaOut.resizeNoCopy(Zdim, Ydim, Xdim);
670  MultidimArray<std::complex<double> > MpmemFourier;
671  FourierTransformer transformerMp;
672  transformerMp.setReal(mdaOut);
673  transformerMp.getFourierAlias(MpmemFourier);
674 
675  scaleToSizeFourier(mdaIn, mdaOut, MmemFourier, MpmemFourier);
676 
677  // Transform data
678  transformerMp.inverseFourierTransform();
679 }
680 
683 
684 template<typename T>
686  MultidimArray<std::complex<T> > &inFourier, MultidimArray<std::complex<T> > &outFourier) {
687  size_t xsize = std::min(XSIZE(inFourier),XSIZE(outFourier))*sizeof(std::complex<T>);
688  size_t yhalf = std::min(std::min(YSIZE(mdaIn)/2,YSIZE(mdaOut)/2),YSIZE(mdaIn)-1);
689  size_t zhalf = std::min(std::min(ZSIZE(mdaIn)/2,ZSIZE(mdaOut)/2),ZSIZE(mdaIn)-1);
690 
691  size_t kp0=0;
692  size_t kpF=zhalf;
693  size_t ip0=0;
694  size_t ipF=yhalf;
695  size_t km0=ZSIZE(inFourier)>=ZSIZE(outFourier)?(kpF+1):(ZSIZE(outFourier)-(ZSIZE(inFourier)-(zhalf+1)));
696  size_t kmF=ZSIZE(outFourier)-1;
697  size_t im0=YSIZE(inFourier)>=YSIZE(outFourier)?(ipF+1):(YSIZE(outFourier)-(YSIZE(inFourier)-(yhalf+1)));
698  size_t imF=YSIZE(outFourier)-1;
699 
700  //Init with zero
701  outFourier.initZeros();
702 
703  for (size_t k = kp0; k<=kpF; ++k)
704  {
705  for (size_t i=ip0; i<=ipF; ++i)
706  memcpy(&dAkij(outFourier,k,i,0),&dAkij(inFourier,k,i,0),xsize);
707  for (size_t i=im0; i<=imF; ++i) {
708  size_t ip = i + YSIZE(inFourier)-YSIZE(outFourier) ;
709  memcpy(&dAkij(outFourier,k,i,0),&dAkij(inFourier,k,ip,0),xsize);
710  }
711  }
712  for (size_t k = km0; k<=kmF; ++k) {
713  size_t kp = k + ZSIZE(inFourier)-ZSIZE(outFourier) ;
714  for (size_t i=ip0; i<=ipF; ++i)
715  memcpy(&dAkij(outFourier,k,i,0),&dAkij(inFourier,kp,i,0),xsize);
716  for (size_t i=im0; i<=imF; ++i) {
717  size_t ip = i + YSIZE(inFourier)-YSIZE(outFourier) ;
718  memcpy(&dAkij(outFourier,k,i,0),&dAkij(inFourier,kp,ip,0),xsize);
719  }
720  }
721 }
722 
723 void selfScaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArray<double> &mda, int nThreads)
724 {
726  scaleToSizeFourier(Zdim, Ydim, Xdim, mda, aux, nThreads);
727  mda=aux;
728 }
729 
730 
731 void selfScaleToSizeFourier(int Ydim, int Xdim, MultidimArray<double>& Mpmem,int nThreads)
732 {
733  selfScaleToSizeFourier(1, Ydim, Xdim, Mpmem, nThreads);
734 }
735 
736 void selfScaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArrayGeneric &Mpmem, int nThreads)
737 {
739  Mpmem.getImage(aux);
740  selfScaleToSizeFourier(Zdim, Ydim, Xdim, aux, nThreads);
741  Mpmem.setImage(aux);
742 }
743 
744 void selfScaleToSizeFourier(int Ydim, int Xdim, MultidimArrayGeneric &Mpmem, int nThreads)
745 {
747  Mpmem.getImage(aux);
748  selfScaleToSizeFourier(1, Ydim, Xdim, aux, nThreads);
749  Mpmem.setImage(aux);
750 }
751 
753  MultidimArray<double> &spectrum,
754  int spectrum_type)
755 {
757  int xsize = XSIZE(Min);
758  Matrix1D<double> f(3);
759  MultidimArray<double> count(xsize);
760  FourierTransformer transformer;
761 
762  spectrum.initZeros(xsize);
763  count.initZeros();
764  transformer.FourierTransform(Min, Faux, false);
765  if (ZSIZE(Faux)==1)
766  ZZ(f)=0;
768  {
769  FFT_IDX2DIGFREQ(j,xsize,XX(f));
770  FFT_IDX2DIGFREQ(i,YSIZE(Faux),YY(f));
771  if (ZSIZE(Faux)>1)
772  FFT_IDX2DIGFREQ(k,ZSIZE(Faux),ZZ(f));
773  double R=f.module();
774  //if (R>0.5) continue;
775  int idx = round(R*xsize);
776  double F=abs(dAkij(Faux, k, i, j));
777  if (spectrum_type == AMPLITUDE_SPECTRUM)
778  A1D_ELEM(spectrum,idx) += F;
779  else
780  A1D_ELEM(spectrum,idx) += F*F;
781  A1D_ELEM(count,idx) += 1.;
782  }
783  for (int i = 0; i < xsize; i++)
784  if (A1D_ELEM(count,i) > 0.)
785  A1D_ELEM(spectrum,i) /= A1D_ELEM(count,i);
786 }
787 
789  MultidimArray<double> &spectrum,
790  bool leave_origin_intact)
791 {
792 
793  Min.checkDimension(3);
794 
795  MultidimArray<double> div_spec(spectrum);
797  {
798  if (ABS(dAi(spectrum,i)) > 0.)
799  dAi(div_spec,i) = 1./dAi(spectrum,i);
800  else
801  dAi(div_spec,i) = 1.;
802  }
803  multiplyBySpectrum(Min,div_spec,leave_origin_intact);
804 }
805 
807  MultidimArray<double> &spectrum,
808  bool leave_origin_intact)
809 {
810  Min.checkDimension(3);
811 
813  Matrix1D<double> f(3);
814  MultidimArray<double> lspectrum;
815  FourierTransformer transformer;
816  double dim3 = XSIZE(Min)*YSIZE(Min)*ZSIZE(Min);
817 
818  transformer.FourierTransform(Min, Faux, false);
819  lspectrum=spectrum;
820  if (leave_origin_intact)
821  lspectrum(0)=1.;
823  {
824  FFT_IDX2DIGFREQ(j,XSIZE(Min), XX(f));
825  FFT_IDX2DIGFREQ(i,YSIZE(Faux),YY(f));
826  FFT_IDX2DIGFREQ(k,ZSIZE(Faux),ZZ(f));
827  double R=f.module();
828  //if (R > 0.5) continue;
829  int idx=ROUND(R*XSIZE(Min));
830  dAkij(Faux, k, i, j) *= lspectrum(idx) * dim3;
831  }
832  transformer.inverseFourierTransform();
833 }
834 
836  MultidimArray<double> &Mout,
837  int spectrum_type,
838  bool leave_origin_intact)
839 {
840  Min.checkDimension(3);
841 
842  MultidimArray<double> spectrum;
843  getSpectrum(Min,spectrum,spectrum_type);
844  Mout=Min;
845  divideBySpectrum(Mout,spectrum,leave_origin_intact);
846 
847 }
848 
850  MultidimArray<double> &Mout,
851  const MultidimArray<double> &spectrum_ref,
852  int spectrum_type,
853  bool leave_origin_intact)
854 {
855 
856  Min.checkDimension(3);
857 
858  MultidimArray<double> spectrum;
859  getSpectrum(Min,spectrum,spectrum_type);
861  {
862  dAi(spectrum, i) = (dAi(spectrum, i) > 0.) ? dAi(spectrum_ref,i)/ dAi(spectrum, i) : 1.;
863  }
864  Mout=Min;
865  multiplyBySpectrum(Mout,spectrum,leave_origin_intact);
866 
867 }
868 
870  const MultidimArray<double> & m2,
872  CorrelationAux &aux,
873  bool center)
874 {
876  correlation_matrix(aux.FFT1,m2,R,aux,center);
877 }
878 
879 void correlationInFourier(const MultidimArray< std::complex< double > > & FF1, MultidimArray< std::complex< double > > & FF2, double dSize)
880 {
881  // Multiply FFT1 * FFT2'
882  double mdSize=-dSize;
883  double a, b, c, d; // a+bi, c+di
884  double *ptrFFT2=(double*)MULTIDIM_ARRAY(FF2);
885  double *ptrFFT1=(double*)MULTIDIM_ARRAY(FF1);
887  {
888  a=*ptrFFT1++;
889  b=*ptrFFT1++;
890  c=(*ptrFFT2)*dSize;
891  d=(*(ptrFFT2+1))*mdSize;
892  *ptrFFT2++ = a*c-b*d;
893  *ptrFFT2++ = b*c+a*d;
894  }
895 }
896 
897 
898 void correlation_matrix(const MultidimArray< std::complex< double > > & FF1,
899  const MultidimArray<double> & m2,
901  CorrelationAux &aux,
902  bool center)
903 {
904  R=m2;
905  aux.transformer2.FourierTransform(R, aux.FFT2, false);
908  if (center)
909  CenterFFT(R, true);
910 }
911 
912 void correlation_matrix(const MultidimArray< std::complex< double > > & FFT1,
913  const MultidimArray< std::complex< double > > & FFT2,
915  CorrelationAux &aux,
916  bool center)
917 {
918  aux.transformer2.setReal(R);
919  aux.transformer2.setFourier(FFT2);
922  if (center)
923  CenterFFT(R, true);
924 }
925 
926 void fast_correlation_vector(const MultidimArray< std::complex<double> > & FFT1,
927  const MultidimArray< std::complex<double> > & FFT2,
929  FourierTransformer &transformer)
930 {
931  transformer.setFourier(FFT1);
932 
933  // Multiply FFT1 * FFT2'
934  double a, b, c, d; // a+bi, c+di
935  double *ptrFFT2=(double*)MULTIDIM_ARRAY(FFT2);
936  double *ptrFFT1=(double*)&(A1D_ELEM(transformer.fFourier,0));
938  {
939  a=*ptrFFT1;
940  b=*(ptrFFT1+1);
941  c=(*ptrFFT2++);
942  d=(*ptrFFT2++)*(-1);
943  *ptrFFT1++ = a*c-b*d;
944  *ptrFFT1++ = b*c+a*d;
945  }
946 
947  // Invert the product, in order to obtain the correlation image
948  transformer.inverseFourierTransform();
949 
950  // Center the resulting image to obtain a centered autocorrelation
951  R=*transformer.fReal;
952  CenterFFT(R, true);
953  R.setXmippOrigin();
954 }
955 
958 {
959  // Compute the Fourier Transform
960  R=Img;
961  aux.transformer1.FourierTransform(R, aux.FFT1, false);
962 
963  // Multiply FFT1 * FFT1'
964  double dSize=MULTIDIM_SIZE(Img);
966  {
967  double *ptr=(double*)&DIRECT_MULTIDIM_ELEM(aux.FFT1,n);
968  double &realPart=*ptr;
969  double &imagPart=*(ptr+1);
970  realPart=dSize*(realPart*realPart+imagPart*imagPart);
971  imagPart=0;
972  }
973 
974  // Invert the product, in order to obtain the correlation image
976 
977  // Center the resulting image to obtain a centered autocorrelation
978  CenterFFT(R, true);
979 }
980 
981 void randomizePhases(MultidimArray<double> &Min, double wRandom)
982 {
983  FourierTransformer transformer;
985  transformer.FourierTransform(Min,F,false);
986 
987  Matrix1D<double> f(3);
989  {
990  FFT_IDX2DIGFREQ(j,XSIZE(Min), XX(f));
991  FFT_IDX2DIGFREQ(i,YSIZE(F),YY(f));
992  FFT_IDX2DIGFREQ(k,ZSIZE(F),ZZ(f));
993  double w=f.module();
994  if (w > wRandom)
995  {
996  double alpha=rnd_unif(0,2*PI);
997  double c,s;
998  //sincos(alpha,&s,&c);
999  s = sin(alpha);
1000  c = cos(alpha);
1001 
1002  DIRECT_A3D_ELEM(F,k,i,j)*=std::complex<double>(s,c);
1003  }
1004  }
1005  transformer.inverseFourierTransform();
1006 }
Just to locate unclassified errors.
Definition: xmipp_error.h:192
#define dAi(v, i)
int nInstances
Definition: xmipp_fftw.cpp:35
int * nmax
#define YSIZE(v)
void min(Image< double > &op1, const Image< double > &op2)
void FFT_phase(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &phase)
Definition: xmipp_fftw.cpp:408
FourierTransformer transformer1
Definition: xmipp_fftw.h:555
void adaptSpectrum(MultidimArray< double > &Min, MultidimArray< double > &Mout, const MultidimArray< double > &spectrum_ref, int spectrum_type, bool leave_origin_intact)
Definition: xmipp_fftw.cpp:849
double module() const
Definition: matrix1d.h:983
alglib::complex conj(const alglib::complex &z)
Definition: ap.cpp:4988
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
template void scaleToSizeFourier< double >(MultidimArray< double > &mdaIn, MultidimArray< double > &mdaOut, MultidimArray< std::complex< double > > &inFourier, MultidimArray< std::complex< double > > &outFourier)
void setThreadsNumber(int tNumber)
Definition: xmipp_fftw.h:119
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
bool planCreated
Definition: xmipp_fftw.cpp:34
double sign
doublereal * c
#define MULTIDIM_SIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
MultidimArray< std::complex< double > > fFourier
Definition: xmipp_fftw.h:70
void sqrt(Image< double > &op)
void destroyThreads(void)
Definition: xmipp_fftw.h:150
void correlationInFourier(const MultidimArray< std::complex< double > > &FF1, MultidimArray< std::complex< double > > &FF2, double dSize)
Definition: xmipp_fftw.cpp:879
#define DIRECT_A2D_ELEM(v, i, j)
#define A1D_ELEM(v, i)
void correlation_matrix(const MultidimArray< double > &m1, const MultidimArray< double > &m2, MultidimArray< double > &R, CorrelationAux &aux, bool center)
Definition: xmipp_fftw.cpp:869
#define MULTIDIM_ARRAY(v)
doublereal * w
void abs(Image< double > &op)
void frc_dpr(MultidimArray< double > &m1, MultidimArray< double > &m2, double sampling_rate, MultidimArray< double > &freq, MultidimArray< double > &frc, MultidimArray< double > &frc_noise, MultidimArray< double > &dpr, MultidimArray< double > &error_l2, bool dodpr, bool doRfactor, double minFreq, double maxFreq, double *rFactor)
Definition: xmipp_fftw.cpp:491
FourierTransformer & operator=(const FourierTransformer &other)
Definition: xmipp_fftw.cpp:65
String integerToString(int I, int _width, char fill_with)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(V)
void convolutionFFTStack(const MultidimArray< double > &img, const MultidimArray< double > &kernel, MultidimArray< double > &result)
Definition: xmipp_fftw.cpp:429
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(v)
MultidimArray< std::complex< double > > * fComplex
Definition: xmipp_fftw.h:67
void auto_correlation_matrix(const MultidimArray< double > &Img, MultidimArray< double > &R, CorrelationAux &aux)
Definition: xmipp_fftw.cpp:957
#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
MultidimArray< double > * fReal
Definition: xmipp_fftw.h:64
void aliasSlice(const MultidimArray< T > &m, size_t select_slice)
void getSpectrum(MultidimArray< double > &Min, MultidimArray< double > &spectrum, int spectrum_type)
Definition: xmipp_fftw.cpp:752
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
const MultidimArray< double > & getReal() const
Definition: xmipp_fftw.cpp:118
double rnd_unif()
void getImage(MultidimArray< T > &M) const
#define FFT_IDX2DIGFREQ_FAST(idx, size, size_2, isize, freq)
Definition: xmipp_fft.h:54
doublereal * b
#define XX(v)
Definition: matrix1d.h:85
void setReal(MultidimArray< double > &img)
Definition: xmipp_fftw.cpp:129
void Transform(int sign)
Definition: xmipp_fftw.cpp:256
double * f
void setFourier(const MultidimArray< std::complex< double > > &imgFourier)
Definition: xmipp_fftw.cpp:249
bool sameShape(const MultidimArrayBase &op) const
fftw_plan fPlanBackward
Definition: xmipp_fftw.h:76
void multiplyBySpectrum(MultidimArray< double > &Min, MultidimArray< double > &spectrum, bool leave_origin_intact)
Definition: xmipp_fftw.cpp:806
#define XSIZE(v)
void setImage(MultidimArray< T > &M)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
void radialAverage(const MultidimArray< double > &VolFourierMag, const MultidimArray< double > &V, MultidimArray< double > &radial_mean)
#define dAkij(V, k, i, j)
#define ABS(x)
Definition: xmipp_macros.h:142
#define ZSIZE(v)
void fast_correlation_vector(const MultidimArray< std::complex< double > > &FFT1, const MultidimArray< std::complex< double > > &FFT2, MultidimArray< double > &R, FourierTransformer &transformer)
Definition: xmipp_fftw.cpp:926
#define DIRECT_MULTIDIM_ELEM(v, n)
#define ROUND(x)
Definition: xmipp_macros.h:210
void selfScaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArray< double > &mda, int nThreads)
Definition: xmipp_fftw.cpp:723
void convolutionFFT(MultidimArray< double > &img, MultidimArray< double > &kernel, MultidimArray< double > &result)
Definition: xmipp_fftw.cpp:457
fftw_plan fPlanForward
Definition: xmipp_fftw.h:73
void scaleToSizeFourier(int Zdim, int Ydim, int Xdim, MultidimArray< double > &mdaIn, MultidimArray< double > &mdaOut, int nThreads)
Definition: xmipp_fftw.cpp:658
MultidimArray< std::complex< double > > FFT1
Definition: xmipp_fftw.h:554
#define DIRECT_A3D_ELEM(v, k, i, j)
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
std::complex< double > * complexDataPtr
Definition: xmipp_fftw.h:358
#define j
const MultidimArray< std::complex< double > > & getComplex() const
Definition: xmipp_fftw.cpp:123
#define YY(v)
Definition: matrix1d.h:93
FFT Plan cannot be created.
Definition: xmipp_error.h:184
void randomizePhases(MultidimArray< double > &Min, double wRandom)
Definition: xmipp_fftw.cpp:981
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
int round(double x)
Definition: ap.cpp:7245
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
void getFourierAlias(T &V)
Definition: xmipp_fftw.h:207
void radial_magnitude(const MultidimArray< double > &v, MultidimArray< std::complex< double > > &V, MultidimArray< double > &radialMagnitude)
Definition: xmipp_fftw.cpp:416
void whitenSpectrum(MultidimArray< double > &Min, MultidimArray< double > &Mout, int spectrum_type, bool leave_origin_intact)
Definition: xmipp_fftw.cpp:835
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
MultidimArray< std::complex< double > > FFT2
Definition: xmipp_fftw.h:554
#define AMPLITUDE_SPECTRUM
Definition: xmipp_fftw.h:669
void initZeros(const MultidimArray< T1 > &op)
#define PI
Definition: tools.h:43
void enforceHermitianSymmetry()
Definition: xmipp_fftw.cpp:335
FourierTransformer transformer2
Definition: xmipp_fftw.h:555
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
Definition: xmipp_fftw.cpp:393
int * n
#define ZZ(v)
Definition: matrix1d.h:101
void divideBySpectrum(MultidimArray< double > &Min, MultidimArray< double > &spectrum, bool leave_origin_intact)
Definition: xmipp_fftw.cpp:788
doublereal * a
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272