Xmipp  v3.23.11-Nereus
reconstruct_fourier.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  * Jose Roman Bilbao-Castro (jrbcast@ace.ual.es)
6  * Vahid Abrishami (vabrishami@cnb.csic.es)
7  *
8  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23  * 02111-1307 USA
24  *
25  * All comments concerning this program package may be sent to the
26  * e-mail address 'xmipp@cnb.csic.es'
27  ***************************************************************************/
28 
29 #include "reconstruct_fourier.h"
30 #include "core/bilib/kernel.h"
31 #include "core/matrix2d.h"
32 #include "core/symmetries.h"
34 
35 // Define params
37 {
38  //usage
39  addUsageLine("Generate 3D reconstructions from projections using direct Fourier interpolation with arbitrary geometry.");
40  addUsageLine("Kaisser-windows are used for interpolation in Fourier space.");
41  //params
42  addParamsLine(" -i <md_file> : Metadata file with input projections");
43  addParamsLine(" [-o <volume_file=\"rec_fourier.vol\">] : Filename for output volume");
44  addParamsLine(" [--iter <iterations=1>] : Number of iterations for weight correction");
45  addParamsLine(" [--sym <symfile=c1>] : Enforce symmetry in projections");
46  addParamsLine(" [--padding <proj=2.0> <vol=2.0>] : Padding used for projections and volume");
47  addParamsLine(" [--prepare_fsc <fscfile>] : Filename root for FSC files");
48  addParamsLine(" [--max_resolution <p=0.5>] : Max resolution (Nyquist=0.5)");
49  addParamsLine(" [--weight] : Use weights stored in the image metadata");
50  addParamsLine(" [--thr <threads=1> <rows=1>] : Number of concurrent threads and rows processed at time by a thread");
51  addParamsLine(" [--blob <radius=1.9> <order=0> <alpha=15>] : Blob parameters");
52  addParamsLine(" : radius in pixels, order of Bessel function in blob and parameter alpha");
53  addParamsLine(" [--useCTF] : Use CTF information if present");
54  addParamsLine(" [--sampling <Ts=1>] : sampling rate of the input images in Angstroms/pixel");
55  addParamsLine(" : It is only used when correcting for the CTF");
56  addParamsLine(" [--phaseFlipped] : Give this flag if images have been already phase flipped");
57  addParamsLine(" [--minCTF <ctf=0.01>] : Minimum value of the CTF that will be inverted");
58  addParamsLine(" : CTF values (in absolute value) below this one will not be corrected");
59  addExampleLine("For reconstruct enforcing i3 symmetry and using stored weights:", false);
60  addExampleLine(" xmipp_reconstruct_fourier -i reconstruction.sel --sym i3 --weight");
61 }
62 
63 // Read arguments ==========================================================
65 {
66  fn_sel = getParam("-i");
67  fn_out = getParam("-o");
68  fn_sym = getParam("--sym");
69  if(checkParam("--prepare_fsc"))
70  fn_fsc = getParam("--prepare_fsc");
71  do_weights = checkParam("--weight");
72  padding_factor_proj = getDoubleParam("--padding", 0);
73  padding_factor_vol = getDoubleParam("--padding", 1);
74  blob.radius = getDoubleParam("--blob", 0);
75  blob.order = getIntParam("--blob", 1);
76  blob.alpha = getDoubleParam("--blob", 2);
77  maxResolution = getDoubleParam("--max_resolution");
78  numThreads = getIntParam("--thr");
79  thrWidth = getIntParam("--thr", 1);
80  NiterWeight = getIntParam("--iter");
81  useCTF = checkParam("--useCTF");
82  phaseFlipped = checkParam("--phaseFlipped");
83  minCTF = getDoubleParam("--minCTF");
84  if (useCTF)
85  Ts=getDoubleParam("--sampling");
86 }
87 
88 // Show ====================================================================
90 {
91  if (verbose > 0)
92  {
93  std::cout << " =====================================================================" << std::endl;
94  std::cout << " Direct 3D reconstruction method using Kaiser windows as interpolators" << std::endl;
95  std::cout << " =====================================================================" << std::endl;
96  std::cout << " Input selfile : " << fn_sel << std::endl;
97  std::cout << " padding_factor_proj : " << padding_factor_proj << std::endl;
98  std::cout << " padding_factor_vol : " << padding_factor_vol << std::endl;
99  std::cout << " Output volume : " << fn_out << std::endl;
100  if (fn_sym != "")
101  std::cout << " Symmetry file for projections : " << fn_sym << std::endl;
102  if (fn_fsc != "")
103  std::cout << " File root for FSC files: " << fn_fsc << std::endl;
104  if (do_weights)
105  std::cout << " Use weights stored in the image headers or doc file" << std::endl;
106  else
107  std::cout << " Do NOT use weights" << std::endl;
108  if (useCTF)
109  std::cout << "Using CTF information" << std::endl
110  << "Sampling rate: " << Ts << std::endl
111  << "Phase flipped: " << phaseFlipped << std::endl
112  << "Minimum CTF: " << minCTF << std::endl;
113  std::cout << "\n Interpolation Function"
114  << "\n blrad : " << blob.radius
115  << "\n blord : " << blob.order
116  << "\n blalpha : " << blob.alpha
117  //<< "\n sampling_rate : " << sampling_rate
118  << "\n max_resolution : " << maxResolution
119  << "\n -----------------------------------------------------------------" << std::endl;
120  }
121 }
122 
123 // Main routine ------------------------------------------------------------
125 {
126  show();
127  produceSideinfo();
128  // Process all images in the selfile
129  if (verbose)
130  {
131  if (NiterWeight!=0)
133  else
135  }
136  // Create threads stuff
138  pthread_mutex_init( &workLoadMutex, nullptr);
139  statusArray = nullptr;
140  th_ids = (pthread_t *)malloc( numThreads * sizeof( pthread_t));
141  th_args = (ImageThreadParams *) malloc ( numThreads * sizeof( ImageThreadParams ) );
142 
143  // Create threads
144  for ( int nt = 0 ; nt < numThreads ; nt ++ )
145  {
146  // Passing parameters to each thread
147  th_args[nt].parent = this;
148  th_args[nt].myThreadID = nt;
149  th_args[nt].selFile = new MetaDataVec(SF);
150  pthread_create( (th_ids+nt) , nullptr, processImageThread, (void *)(th_args+nt) );
151  }
152 
153  //Computing interpolated volume
154  processImages(0, SF.size() - 1, !fn_fsc.empty(), false);
155 
156  // Correcting the weights
157  correctWeight();
158 
159  //Saving the volume
161 
163 
164  // Waiting for threads to finish
165  barrier_wait( &barrier );
166  for ( int nt = 0 ; nt < numThreads ; nt ++ )
167  pthread_join(*(th_ids+nt), nullptr);
169 
170  // Deallocate resources.
171  if ( statusArray != nullptr)
172  {
173  free(statusArray);
174  }
175  for (int nt=0; nt<numThreads ;nt++)
176  {
177  delete(th_args[nt].selFile);
178  }
179  free(th_ids);
180  free(th_args);
181 }
182 
183 
185 {
186  // Translate the maximum resolution to digital frequency
187  // maxResolution=sampling_rate/maxResolution;
189 
190  // Read the input images
191  SF.read(fn_sel);
192  SF.removeDisabled();
193 
194  // Ask for memory for the output volume and its Fourier transform
195  size_t objId = SF.firstRowId();
196  FileName fnImg;
197  SF.getValue(MDL_IMAGE,fnImg,objId);
198  Image<double> I;
199  I.read(fnImg, HEADER);
200  int Ydim=YSIZE(I());
201  int Xdim=XSIZE(I());
202  if (Ydim!=Xdim)
203  REPORT_ERROR(ERR_MULTIDIM_SIZE,"This algorithm only works for squared images");
204  imgSize=Xdim;
207 
208  //use threads for volume inverse fourier transform, plan is created in setReal()
211 
212  Vout().clear(); // Free the memory so that it is available for FourierWeights
216 
217  // Ask for memory for the padded images
218  auto paddedImgSize=(size_t)(Xdim*padding_factor_proj);
219  paddedImg.resize(paddedImgSize,paddedImgSize);
222 
223  // Build a table of blob values
227 
228  struct blobtype blobFourier,blobnormalized;
229  blobFourier=blob;
230  //Sjors 18aug10 blobFourier.radius/=(padding_factor_proj*Xdim);
231  blobFourier.radius/=(padding_factor_vol*Xdim);
232  blobnormalized=blob;
233  blobnormalized.radius/=((double)padding_factor_proj/padding_factor_vol);
234  double deltaSqrt = (blob.radius*blob.radius) /(BLOB_TABLE_SIZE_SQRT-1);
235  double deltaFourier = (sqrt(3.)*Xdim/2.)/(BLOB_TABLE_SIZE_SQRT-1);
236 
237  // The interpolation kernel must integrate to 1
238  double iw0 = 1.0 / blob_Fourier_val(0.0, blobnormalized);
239  //Sjors 18aug10 double padXdim3 = padding_factor_proj * Xdim;
240  double padXdim3 = padding_factor_vol * Xdim;
241  padXdim3 = padXdim3 * padXdim3 * padXdim3;
242  double blobTableSize = blob.radius*sqrt(1./ (BLOB_TABLE_SIZE_SQRT-1));
243  //***
244  //Following commented line seems to be the right thing but I do not understand it
245  //double fourierBlobTableSize = (sqrt(3.)*Xdim*Xdim/2.)*blobFourier.radius *sqrt(1./ (BLOB_TABLE_SIZE_SQRT-1));
247 
248  {
249  //use a r*r sample instead of r
250  //DIRECT_VEC_ELEM(blob_table,i) = blob_val(delta*i, blob) *iw0;
251  VEC_ELEM(blobTableSqrt,i) = blob_val(blobTableSize*sqrt((double)i), blob) *iw0;
252  //***
253  //DIRECT_VEC_ELEM(fourierBlobTableSqrt,i) =
254  // blob_Fourier_val(fourierBlobTableSize*sqrt(i), blobFourier)*padXdim3 *iw0;
256  blob_Fourier_val(deltaFourier*i, blobFourier)*padXdim3 *iw0;
257  //#define DEBUG
258 #ifdef DEBUG
259 
260  std::cout << VEC_ELEM(Fourier_blob_table,i)
261  << " " << VEC_ELEM(fourierBlobTableSqrt,i)
262  << std::endl;
263 #endif
264  #undef DEBUG
265 
266  }
267  //iDelta = 1/delta;
268  iDeltaSqrt = 1/deltaSqrt;
269  iDeltaFourier = 1/deltaFourier;
270 
271  // Get symmetries
272  Matrix2D<double> Identity(3,3);
273  Identity.initIdentity();
274  R_repository.push_back(Identity);
275  if (fn_sym != "")
276  {
277  SymList SL;
279  for (int isym = 0; isym < SL.trueSymsNo(); isym++)
280  {
281  Matrix2D<double> L(4, 4), R(4, 4);
282  SL.getMatrices(isym, L, R);
283  R.resize(3, 3);
284  R_repository.push_back(R);
285  }
286  }
287 }
288 
289 void * ProgRecFourier::processImageThread( void * threadArgs )
290 {
291 
292  auto * threadParams = (ImageThreadParams *) threadArgs;
293  ProgRecFourier * parent = threadParams->parent;
294  barrier_t * barrier = &(parent->barrier);
295 
296  int minSeparation;
297 
298  if ( (int)ceil(parent->blob.radius) > parent->thrWidth )
299  minSeparation = (int)ceil(parent->blob.radius);
300  else
301  minSeparation = parent->thrWidth;
302 
303  minSeparation+=1;
304 
305  Matrix2D<double> localA(3, 3), localAinv(3, 3);
306  MultidimArray< std::complex<double> > localPaddedFourier;
307  MultidimArray<double> localPaddedImg;
308  FourierTransformer localTransformerImg;
309 
310  std::vector<size_t> objId;
311 
312  threadParams->selFile->findObjects(objId);
313  ApplyGeoParams params;
314  params.only_apply_shifts = true;
315  MultidimArray<int> zWrapped(3*parent->volPadSizeZ),yWrapped(3*parent->volPadSizeY),xWrapped(3*parent->volPadSizeX),
316  zNegWrapped, yNegWrapped, xNegWrapped;
317  zWrapped.initConstant(-1);
318  yWrapped.initConstant(-1);
319  xWrapped.initConstant(-1);
320  zWrapped.setXmippOrigin();
321  yWrapped.setXmippOrigin();
322  xWrapped.setXmippOrigin();
323  zNegWrapped=zWrapped;
324  yNegWrapped=yWrapped;
325  xNegWrapped=xWrapped;
326 
327  MultidimArray<double> x2precalculated(XSIZE(xWrapped)), y2precalculated(XSIZE(yWrapped)), z2precalculated(XSIZE(zWrapped));
328  x2precalculated.initConstant(-1);
329  y2precalculated.initConstant(-1);
330  z2precalculated.initConstant(-1);
331  x2precalculated.setXmippOrigin();
332  y2precalculated.setXmippOrigin();
333  z2precalculated.setXmippOrigin();
334 
335  bool hasCTF=(threadParams->selFile->containsLabel(MDL_CTF_MODEL) || threadParams->selFile->containsLabel(MDL_CTF_DEFOCUSU)) &&
336  parent->useCTF;
337  if (hasCTF)
338  {
339  threadParams->ctf.enable_CTF=true;
340  threadParams->ctf.enable_CTFnoise=false;
341  }
342  do
343  {
344  barrier_wait( barrier );
345 
346  switch ( parent->threadOpCode )
347  {
348  case PRELOAD_IMAGE:
349  {
350 
351  threadParams->read = 0;
352 
353  if ( threadParams->imageIndex >= 0 )
354  {
355  // Read input image
356  double rot, tilt, psi, weight;
357  Projection proj;
358 
359  //Read projection from selfile, read also angles and shifts if present
360  //but only apply shifts
361 
362  proj.readApplyGeo(*(threadParams->selFile), objId[threadParams->imageIndex], params);
363  rot = proj.rot();
364  tilt = proj.tilt();
365  psi = proj.psi();
366  weight = proj.weight();
367  if (hasCTF)
368  {
369  threadParams->ctf.readFromMetadataRow(*(threadParams->selFile),objId[threadParams->imageIndex]);
370  // threadParams->ctf.Tm=threadParams->parent->Ts;
371  threadParams->ctf.produceSideInfo();
372  }
373 
374  threadParams->weight = 1.;
375 
376  if(parent->do_weights)
377  threadParams->weight = weight;
378  else if (!parent->do_weights)
379  {
380  weight=1.0;
381  }
382  else if (weight==0.0)
383  {
384  threadParams->read = 2;
385  break;
386  }
387 
388  // Copy the projection to the center of the padded image
389  // and compute its Fourier transform
390  proj().setXmippOrigin();
391  auto localPaddedImgSize=(size_t)(parent->imgSize*parent->padding_factor_proj);
392  if (threadParams->reprocessFlag)
393  localPaddedFourier.initZeros(localPaddedImgSize,localPaddedImgSize/2+1);
394  else
395  {
396  localPaddedImg.initZeros(localPaddedImgSize,localPaddedImgSize);
397  localPaddedImg.setXmippOrigin();
398  const MultidimArray<double> &mProj=proj();
400  A2D_ELEM(localPaddedImg,i,j)=A2D_ELEM(mProj,i,j);
401  // COSS A2D_ELEM(localPaddedImg,i,j)=weight*A2D_ELEM(mProj,i,j);
402  CenterFFT(localPaddedImg,true);
403 
404  // Fourier transformer for the images
405  localTransformerImg.setReal(localPaddedImg);
406  localTransformerImg.FourierTransform();
407  localTransformerImg.getFourierAlias(localPaddedFourier);
408  }
409 
410  // Compute the coordinate axes associated to this image
411  Euler_angles2matrix(rot, tilt, psi, localA);
412  localAinv=localA.transpose();
413 
414  threadParams->localweight = weight;
415  threadParams->localAInv = &localAinv;
416  threadParams->localPaddedFourier = &localPaddedFourier;
417  //#define DEBUG22
418 #ifdef DEBUG22
419 
420  {//CORRECTO
421 
422  if(threadParams->myThreadID%1==0)
423  {
424  proj.write((std::string) integerToString(threadParams->myThreadID) + "_" +\
425  integerToString(threadParams->imageIndex) + "proj.spi");
426 
427  ImageXmipp save44;
428  save44()=localPaddedImg;
429  save44.write((std::string) integerToString(threadParams->myThreadID) + "_" +\
430  integerToString(threadParams->imageIndex) + "local_padded_img.spi");
431 
432  FourierImage save33;
433  save33()=localPaddedFourier;
434  save33.write((std::string) integerToString(threadParams->myThreadID) + "_" +\
435  integerToString(threadParams->imageIndex) + "local_padded_fourier.spi");
436  FourierImage save22;
437  //save22()=*paddedFourier;
438  save22().alias(*(threadParams->localPaddedFourier));
439  save22.write((std::string) integerToString(threadParams->myThreadID) + "_" +\
440  integerToString(threadParams->imageIndex) + "_padded_fourier.spi");
441  }
442 
443  }
444 #endif
445  #undef DEBUG22
446 
447  threadParams->read = 1;
448  }
449  break;
450  }
451  case EXIT_THREAD:
452  return nullptr;
453  case PROCESS_WEIGHTS:
454  {
455 
456  // Get a first approximation of the reconstruction
457  double corr2D_3D=pow(parent->padding_factor_proj,2.)/
458  (parent->imgSize* pow(parent->padding_factor_vol,3.));
459  // Divide by Zdim because of the
460  // the extra dimension added
461  // and padding differences
462  MultidimArray<double> &mFourierWeights=parent->FourierWeights;
463  for (int k=threadParams->myThreadID; k<=FINISHINGZ(mFourierWeights); k+=parent->numThreads)
464  for (int i=STARTINGY(mFourierWeights); i<=FINISHINGY(mFourierWeights); i++)
465  for (int j=STARTINGX(mFourierWeights); j<=FINISHINGX(mFourierWeights); j++)
466  {
467  if (parent->NiterWeight==0)
468  A3D_ELEM(parent->VoutFourier,k,i,j)*=corr2D_3D;
469  else
470  {
471  double weight_kij=A3D_ELEM(mFourierWeights,k,i,j);
472  if (1.0/weight_kij>ACCURACY)
473  A3D_ELEM(parent->VoutFourier,k,i,j)*=corr2D_3D*A3D_ELEM(mFourierWeights,k,i,j);
474  else
475  A3D_ELEM(parent->VoutFourier,k,i,j)=0;
476  }
477  }
478  break;
479  }
480  case PROCESS_IMAGE:
481  {
482  MultidimArray< std::complex<double> > *paddedFourier = threadParams->paddedFourier;
483  if (threadParams->weight==0.0)
484  break;
485  bool reprocessFlag = threadParams->reprocessFlag;
486  int * statusArray = parent->statusArray;
487 
488  int minAssignedRow;
489  int maxAssignedRow;
490  bool breakCase;
491  bool assigned;
492 
493  // Get the inverse of the sampling rate
494  // double iTs=parent->padding_factor_proj/parent->Ts;
495  double iTs=1.0/parent->Ts; // The padding factor is not considered here, but later when the indexes
496  // // are converted to digital frequencies
497  do
498  {
499  minAssignedRow = -1;
500  maxAssignedRow = -1;
501  breakCase = false;
502  assigned = false;
503 
504  do
505  {
506  pthread_mutex_lock( &(parent->workLoadMutex) );
507 
508  if ( parent->rowsProcessed == YSIZE(*paddedFourier) )
509  {
510  pthread_mutex_unlock( &(parent->workLoadMutex) );
511  breakCase = true;
512  break;
513  }
514 
515  for (size_t w = 0 ; w < YSIZE(*paddedFourier) ; w++ )
516  {
517  if ( statusArray[w]==0 )
518  {
519  assigned = true;
520  minAssignedRow = w;
521  maxAssignedRow = w+minSeparation-1;
522 
523  if ( maxAssignedRow > (int)(YSIZE(*paddedFourier)-1) )
524  maxAssignedRow = YSIZE(*paddedFourier)-1;
525 
526  for ( int in = (minAssignedRow - minSeparation) ; in < (int)minAssignedRow ; in ++ )
527  {
528  if ( ( in >= 0 ) && ( in < (int)YSIZE(*paddedFourier) ))
529  {
530  if ( statusArray[in] > -1 )
531  statusArray[in]++;
532  }
533  }
534 
535  for ( int in = minAssignedRow ; in <= (int)maxAssignedRow ; in ++ )
536  {
537  if ( ( in >= 0 ) && ( in < (int)YSIZE(*paddedFourier) ))
538  {
539  if ( statusArray[in] == 0 )
540  {
541  statusArray[in] = -1;
542  parent->rowsProcessed++;
543  }
544  }
545  }
546 
547  for ( int in = maxAssignedRow+1 ; in <= (maxAssignedRow+minSeparation) ; in ++ )
548  {
549  if ( ( in >= 0 ) && ( in < (int)YSIZE(*paddedFourier) ))
550  {
551  if ( statusArray[in] > -1 )
552  statusArray[in]++;
553  }
554  }
555 
556  break;
557  }
558  }
559 
560  pthread_mutex_unlock( &(parent->workLoadMutex) );
561  }
562  while ( !assigned );
563 
564  if ( breakCase == true )
565  {
566  break;
567  }
568 
569  Matrix2D<double> * A_SL = threadParams->symmetry;
570 
571  // Loop over all Fourier coefficients in the padded image
572  Matrix1D<double> freq(3), gcurrent(3), real_position(3), contFreq(3);
573  Matrix1D<int> corner1(3), corner2(3);
574 
575  // Some alias and calculations moved from heavy loops
576  double wCTF=1, wModulator=1.0;
577  double blobRadiusSquared = parent->blob.radius * parent->blob.radius;
578  double iDeltaSqrt = parent->iDeltaSqrt;
580  int xsize_1 = XSIZE(parent->VoutFourier) - 1;
581  int zsize_1 = ZSIZE(parent->VoutFourier) - 1;
583  MultidimArray<double> &fourierWeights = parent->FourierWeights;
584  // MultidimArray<double> &prefourierWeights = parent->preFourierWeights;
585  // Get i value for the thread
586  for (int i = minAssignedRow; i <= maxAssignedRow ; i ++ )
587  {
588  // Discarded rows can be between minAssignedRow and maxAssignedRow, check
589  if ( statusArray[i] == -1 )
590  for (int j=STARTINGX(*paddedFourier); j<=FINISHINGX(*paddedFourier); j++)
591  {
592  // Compute the frequency of this coefficient in the
593  // universal coordinate system
594  FFT_IDX2DIGFREQ(j,XSIZE(parent->paddedImg),XX(freq));
595  FFT_IDX2DIGFREQ(i,YSIZE(parent->paddedImg),YY(freq));
596  ZZ(freq)=0;
597  if (XX(freq)*XX(freq)+YY(freq)*YY(freq)>parent->maxResolution2)
598  continue;
599  wModulator=1.0;
600  if (hasCTF && !reprocessFlag)
601  {
602  XX(contFreq)=XX(freq)*iTs;
603  YY(contFreq)=YY(freq)*iTs;
604  threadParams->ctf.precomputeValues(XX(contFreq),YY(contFreq));
605  //wCTF=threadParams->ctf.getValueAt();
606  wCTF=threadParams->ctf.getValuePureNoKAt();
607  //wCTF=threadParams->ctf.getValuePureWithoutDampingAt();
608 
609  if (std::isnan(wCTF))
610  {
611  if (i==0 && j==0)
612  wModulator=wCTF=1.0;
613  else
614  wModulator=wCTF=0.0;
615  }
616  if (fabs(wCTF)<parent->minCTF)
617  {
618  wModulator=fabs(wCTF);
619  wCTF=SGN(wCTF);
620  }
621  else
622  wCTF=1.0/wCTF;
623  if (parent->phaseFlipped)
624  wCTF=fabs(wCTF);
625  }
626 
628  M3x3_BY_V3x1(freq,*A_SL,freq);
629 
630  // Look for the corresponding index in the volume Fourier transform
631  DIGFREQ2FFT_IDX_DOUBLE(XX(freq),parent->volPadSizeX,XX(real_position));
632  DIGFREQ2FFT_IDX_DOUBLE(YY(freq),parent->volPadSizeY,YY(real_position));
633  DIGFREQ2FFT_IDX_DOUBLE(ZZ(freq),parent->volPadSizeZ,ZZ(real_position));
634 
635  // Put a box around that coefficient
636  XX(corner1)=CEIL (XX(real_position)-parent->blob.radius);
637  YY(corner1)=CEIL (YY(real_position)-parent->blob.radius);
638  ZZ(corner1)=CEIL (ZZ(real_position)-parent->blob.radius);
639  XX(corner2)=FLOOR(XX(real_position)+parent->blob.radius);
640  YY(corner2)=FLOOR(YY(real_position)+parent->blob.radius);
641  ZZ(corner2)=FLOOR(ZZ(real_position)+parent->blob.radius);
642 
643 #ifdef DEBUG
644 
645  std::cout << "Idx Img=(0," << i << "," << j << ") -> Freq Img=("
646  << freq.transpose() << ") ->\n Idx Vol=("
647  << real_position.transpose() << ")\n"
648  << " Corner1=" << corner1.transpose() << std::endl
649  << " Corner2=" << corner2.transpose() << std::endl;
650 #endif
651  // Loop within the box
652  auto *ptrIn=(double *)&(A2D_ELEM(*paddedFourier, i,j));
653 
654  // Some precalculations
655  for (int intz = ZZ(corner1); intz <= ZZ(corner2); ++intz)
656  {
657  double z = intz - ZZ(real_position);
658  A1D_ELEM(z2precalculated,intz)=z*z;
659  if (A1D_ELEM(zWrapped,intz)<0)
660  {
661  int iz, izneg;
662  fastIntWRAP(iz, intz, 0, zsize_1);
663  A1D_ELEM(zWrapped,intz)=iz;
664  int miz=-iz;
665  fastIntWRAP(izneg, miz,0,zsize_1);
666  A1D_ELEM(zNegWrapped,intz)=izneg;
667  }
668  }
669  for (int inty = YY(corner1); inty <= YY(corner2); ++inty)
670  {
671  double y = inty - YY(real_position);
672  A1D_ELEM(y2precalculated,inty)=y*y;
673  if (A1D_ELEM(yWrapped,inty)<0)
674  {
675  int iy, iyneg;
676  fastIntWRAP(iy, inty, 0, zsize_1);
677  A1D_ELEM(yWrapped,inty)=iy;
678  int miy=-iy;
679  fastIntWRAP(iyneg, miy,0,zsize_1);
680  A1D_ELEM(yNegWrapped,inty)=iyneg;
681  }
682  }
683  for (int intx = XX(corner1); intx <= XX(corner2); ++intx)
684  {
685  double x = intx - XX(real_position);
686  A1D_ELEM(x2precalculated,intx)=x*x;
687  if (A1D_ELEM(xWrapped,intx)<0)
688  {
689  int ix, ixneg;
690  fastIntWRAP(ix, intx, 0, zsize_1);
691  A1D_ELEM(xWrapped,intx)=ix;
692  int mix=-ix;
693  fastIntWRAP(ixneg, mix,0,zsize_1);
694  A1D_ELEM(xNegWrapped,intx)=ixneg;
695  }
696  }
697 
698  // Actually compute
699  for (int intz = ZZ(corner1); intz <= ZZ(corner2); ++intz)
700  {
701  double z2 = A1D_ELEM(z2precalculated,intz);
702  int iz=A1D_ELEM(zWrapped,intz);
703  int izneg=A1D_ELEM(zNegWrapped,intz);
704 
705  for (int inty = YY(corner1); inty <= YY(corner2); ++inty)
706  {
707  double y2z2 = A1D_ELEM(y2precalculated,inty) + z2;
708  if (y2z2 > blobRadiusSquared)
709  continue;
710  int iy=A1D_ELEM(yWrapped,inty);
711  int iyneg=A1D_ELEM(yNegWrapped,inty);
712 
713  int size1=YXSIZE(VoutFourier)*izneg+(iyneg*XSIZE(VoutFourier));
714  int size2=YXSIZE(VoutFourier)*iz+(iy*XSIZE(VoutFourier));
715  int fixSize=0;
716 
717  for (int intx = XX(corner1); intx <= XX(corner2); ++intx)
718  {
719  // Compute distance to the center of the blob
720  // Compute blob value at that distance
721  double d2 = A1D_ELEM(x2precalculated,intx) + y2z2;
722 
723  if (d2 > blobRadiusSquared)
724  continue;
725  auto aux = (int)(d2 * iDeltaSqrt + 0.5);//Same as ROUND but avoid comparison
726  double w = VEC_ELEM(blobTableSqrt, aux)*threadParams->weight *wModulator;
727 
728  // Look for the location of this logical index
729  // in the physical layout
730 #ifdef DEBUG
731 
732  std::cout << " gcurrent=" << gcurrent.transpose()
733  << " d=" << d << std::endl;
734  std::cout << " 1: intx=" << intx
735  << " inty=" << inty
736  << " intz=" << intz << std::endl;
737 #endif
738 
739  int ix=A1D_ELEM(xWrapped,intx);
740 #ifdef DEBUG
741 
742  std::cout << " 2: ix=" << ix << " iy=" << iy
743  << " iz=" << iz << std::endl;
744 #endif
745 
746  bool conjugate=false;
747  int izp, iyp, ixp;
748  if (ix > xsize_1)
749  {
750  izp = izneg;
751  iyp = iyneg;
752  ixp = A1D_ELEM(xNegWrapped,intx);
753  conjugate=true;
754  fixSize = size1;
755  }
756  else
757  {
758  izp=iz;
759  iyp=iy;
760  ixp=ix;
761  fixSize = size2;
762  }
763 #ifdef DEBUG
764  std::cout << " 3: ix=" << ix << " iy=" << iy
765  << " iz=" << iz << " conj="
766  << conjugate << std::endl;
767 #endif
768 
769  // Add the weighted coefficient
770  if (reprocessFlag)
771  {
772  // Use VoutFourier as temporary to save the memory
773  auto *ptrOut=(double *)&(DIRECT_A3D_ELEM(VoutFourier, izp,iyp,ixp));
774  DIRECT_A3D_ELEM(fourierWeights, izp,iyp,ixp) += (w * ptrOut[0]);
775  }
776  else
777  {
778  double wEffective=w*wCTF;
779  size_t memIdx=fixSize + ixp;//YXSIZE(VoutFourier)*(izp)+((iyp)*XSIZE(VoutFourier))+(ixp);
780  auto *ptrOut=(double *)&(DIRECT_A1D_ELEM(VoutFourier, memIdx));
781  ptrOut[0] += wEffective * ptrIn[0];
782  DIRECT_A1D_ELEM(fourierWeights, memIdx) += w;
783 
784  if (conjugate)
785  ptrOut[1]-=wEffective*ptrIn[1];
786  else
787  ptrOut[1]+=wEffective*ptrIn[1];
788  }
789  }
790  }
791  }
792  }
793  }
794 
795  pthread_mutex_lock( &(parent->workLoadMutex) );
796 
797  for ( int w = (minAssignedRow - minSeparation) ; w < minAssignedRow ; w ++ )
798  {
799  if ( ( w >= 0 ) && ( w < (int)YSIZE(*paddedFourier) ))
800  {
801  if ( statusArray[w] > 0 )
802  {
803  statusArray[w]--;
804  }
805  }
806  }
807 
808  for ( int w = maxAssignedRow+1 ; w <= (maxAssignedRow+minSeparation) ; w ++ )
809  {
810  if ( ( w >= 0 ) && ( w < (int)YSIZE(*paddedFourier) ))
811  {
812  if ( statusArray[w] > 0 )
813  {
814  statusArray[w]--;
815  }
816  }
817  }
818 
819  pthread_mutex_unlock( &(parent->workLoadMutex) );
820 
821  }
822  while (!breakCase);
823  break;
824  }
825  default:
826  break;
827  }
828 
829  barrier_wait( barrier );
830  }
831  while ( 1 );
832 }
833 
834 //#define DEBUG
835 void ProgRecFourier::processImages( int firstImageIndex, int lastImageIndex, bool saveFSC, bool reprocessFlag)
836 {
837  MultidimArray< std::complex<double> > *paddedFourier;
838 
839  auto repaint = (int)ceil((double)SF.size()/60);
840 
841  bool processed;
842  int imgno = 0;
843  int imgIndex = firstImageIndex;
844 
845  // This index tells when to save work for later FSC usage
846  int FSCIndex = (firstImageIndex + lastImageIndex)/2;
847 
848  // Index of the image that has just been processed. Used for
849  // FSC purposes
850  int current_index;
851 
852  do
853  {
855 
856  for ( int nt = 0 ; nt < numThreads ; nt ++ )
857  {
858  if ( imgIndex <= lastImageIndex )
859  {
860  th_args[nt].imageIndex = imgIndex;
861  th_args[nt].reprocessFlag = reprocessFlag;
862  imgIndex++;
863  }
864  else
865  {
866  th_args[nt].imageIndex = -1;
867  }
868  }
869 
870  // Awaking sleeping threads
871  barrier_wait( &barrier );
872  // here each thread is reading a different image and compute fft
873  // Threads are working now, wait for them to finish
874  // processing current projection
875  barrier_wait( &barrier );
876 
877  // each threads have read a different image and now
878  // all the thread will work in a different part of a single image.
880 
881  processed = false;
882 
883  for ( int nt = 0 ; nt < numThreads ; nt ++ )
884  {
885  if ( th_args[nt].read == 2 )
886  processed = true;
887  else if ( th_args[nt].read == 1 )
888  {
889  processed = true;
890  if (verbose) {
891  if (imgno % repaint == 0)
892  progress_bar(imgno);
893  imgno++;
894  }
895 
896  double weight = th_args[nt].localweight;
897  paddedFourier = th_args[nt].localPaddedFourier;
898  current_index = th_args[nt].imageIndex;
899  Matrix2D<double> *Ainv = th_args[nt].localAInv;
900 
901  //#define DEBUG22
902 #ifdef DEBUG22
903 
904  {
905  static int ii=0;
906  if(ii%1==0)
907  {
908  FourierImage save22;
909  //save22()=*paddedFourier;
910  save22().alias(*paddedFourier);
911  save22.write((std::string) integerToString(ii) + "_padded_fourier.spi");
912  }
913  ii++;
914  }
915 #endif
916  #undef DEBUG22
917 
918  // Initialized just once
919  if ( statusArray == nullptr )
920  {
921  statusArray = (int *) malloc ( sizeof(int) * paddedFourier->ydim );
922  }
923 
924  // Determine how many rows of the fourier
925  // transform are of interest for us. This is because
926  // the user can avoid to explore at certain resolutions
927  auto conserveRows=(size_t)ceil((double)paddedFourier->ydim * maxResolution * 2.0);
928  conserveRows=(size_t)ceil((double)conserveRows/2.0);
929 
930  // Loop over all symmetries
931  for (size_t isym = 0; isym < R_repository.size(); isym++)
932  {
933  rowsProcessed = 0;
934 
935  // Compute the coordinate axes of the symmetrized projection
936  Matrix2D<double> A_SL=R_repository[isym]*(*Ainv);
937 
938  // Fill the thread arguments for each thread
939  for ( int th = 0 ; th < numThreads ; th ++ )
940  {
941  // Passing parameters to each thread
942  th_args[th].symmetry = &A_SL;
943  th_args[th].paddedFourier = paddedFourier;
944  th_args[th].weight = weight;
945  th_args[th].reprocessFlag = reprocessFlag;
946  }
947 
948  // Init status array
949  for (size_t i = 0 ; i < paddedFourier->ydim ; i ++ )
950  {
951  if ( i >= conserveRows && i < (paddedFourier->ydim-conserveRows))
952  {
953  // -2 means "discarded"
954  statusArray[i] = -2;
955  rowsProcessed++;
956  }
957  else
958  {
959  statusArray[i] = 0;
960  }
961  }
962 
963  // Awaking sleeping threads
964  barrier_wait( &barrier );
965  // Threads are working now, wait for them to finish
966  // processing current projection
967  barrier_wait( &barrier );
968 
969  //#define DEBUG2
970 #ifdef DEBUG2
971 
972  {
973  static int ii=0;
974  if(ii%1==0)
975  {
976  Image<double> save;
977  save().alias( FourierWeights );
978  save.write((std::string) integerToString(ii) + "_1_Weights.vol");
979 
981  save2().alias( VoutFourier );
982  save2.write((std::string) integerToString(ii) + "_1_Fourier.vol");
983  }
984  ii++;
985  }
986 #endif
987  #undef DEBUG2
988 
989  }
990 
991  if ( current_index == FSCIndex && saveFSC )
992  {
993  // Save Current Fourier, Reconstruction and Weights
994  Image<double> save;
995  save().alias( FourierWeights );
996  save.write((std::string)fn_fsc + "_1_Weights.vol");
997 
999  save2().alias( VoutFourier );
1000  save2.write((std::string) fn_fsc + "_1_Fourier.vol");
1001 
1002  finishComputations(FileName((std::string) fn_fsc + "_1_recons.vol"));
1003  Vout().initZeros(volPadSizeZ, volPadSizeY, volPadSizeX);
1005  Vout().clear();
1009  }
1010  }
1011  }
1012  }
1013  while ( processed );
1014 
1015  if( saveFSC )
1016  {
1017  // Save Current Fourier, Reconstruction and Weights
1018  Image<double> auxVolume;
1019  auxVolume().alias( FourierWeights );
1020  auxVolume.write((std::string)fn_fsc + "_2_Weights.vol");
1021 
1022  Image< std::complex<double> > auxFourierVolume;
1023  auxFourierVolume().alias( VoutFourier );
1024  auxFourierVolume.write((std::string) fn_fsc + "_2_Fourier.vol");
1025 
1026  finishComputations(FileName((std::string) fn_fsc + "_2_recons.vol"));
1027 
1028  Vout().initZeros(volPadSizeZ, volPadSizeY, volPadSizeX);
1030  Vout().clear();
1034 
1035  auxVolume.sumWithFile(fn_fsc + "_1_Weights.vol");
1036  auxVolume.sumWithFile(fn_fsc + "_2_Weights.vol");
1037  auxFourierVolume.sumWithFile(fn_fsc + "_1_Fourier.vol");
1038  auxFourierVolume.sumWithFile(fn_fsc + "_2_Fourier.vol");
1039  remove((fn_fsc + "_1_Weights.vol").c_str());
1040  remove((fn_fsc + "_2_Weights.vol").c_str());
1041  remove((fn_fsc + "_1_Fourier.vol").c_str());
1042  remove((fn_fsc + "_2_Fourier.vol").c_str());
1043 
1044  /*
1045  //Save SUM
1046  //this is an image but not an xmipp image
1047  auxFourierVolume.write((std::string)fn_fsc + "_all_Fourier.vol",
1048  false,VDOUBLE);
1049  auxVolume.write((std::string)fn_fsc + "_all_Weight.vol",
1050  false,VDOUBLE);
1051  //
1052  */
1053  }
1054 }
1055 
1057 {
1058  // If NiterWeight=0 then set the weights to one
1060  if (NiterWeight==0)
1061  {
1064 
1065  }
1066  else
1067  {
1068  // Temporary save the Fourier of the volume
1070  VoutFourierTmp=VoutFourier;
1072  // Prepare the VoutFourier
1074  {
1075  auto *ptrOut=(double *)&(DIRECT_A3D_ELEM(VoutFourier, k,i,j));
1076  if (fabs(A3D_ELEM(FourierWeights,k,i,j))>1e-3)
1077  ptrOut[0] = 1.0/DIRECT_A3D_ELEM(FourierWeights, k,i,j);
1078  }
1079 
1080  for (int i=1;i<NiterWeight;i++)
1081  {
1084  processImages(0, SF.size() - 1, !fn_fsc.empty(), true);
1087  {
1088  auto *ptrOut=(double *)&(DIRECT_A3D_ELEM(VoutFourier, k,i,j));
1089  if (fabs(A3D_ELEM(FourierWeights,k,i,j))>1e-3)
1090  ptrOut[0] /= A3D_ELEM(FourierWeights,k,i,j);
1091  }
1092  }
1094  {
1095  // Put back the weights to FourierWeights from temporary variable VoutFourier
1096  auto *ptrOut=(double *)&(DIRECT_A3D_ELEM(VoutFourier, k,i,j));
1097  A3D_ELEM(FourierWeights,k,i,j) = ptrOut[0];
1098  }
1100  }
1101 }
1102 
1104 {
1105  //#define DEBUG_VOL
1106 #ifdef DEBUG_VOL
1107  {
1108  VolumeXmipp save;
1109  save().alias( FourierWeights );
1110  save.write((std::string) fn_out + "Weights.vol");
1111 
1112  FourierVolume save2;
1113  save2().alias( VoutFourier );
1114  save2.write((std::string) fn_out + "FourierVol.vol");
1115  }
1116 #endif
1117 
1118  // Enforce symmetry in the Fourier values as well as the weights
1119  // Sjors 19aug10 enforceHermitianSymmetry first checks ndim...
1120  Vout().initZeros(volPadSizeZ,volPadSizeY,volPadSizeX);
1123  //forceWeightSymmetry(preFourierWeights);
1124 
1125  // Tell threads what to do
1126  //#define DEBUG_VOL1
1127 #ifdef DEBUG_VOL1
1128 
1129  {
1130  Image<double> save;
1131  save().alias( FourierWeights );
1132  save.write((std::string) fn_out + "hermiticWeights.vol");
1133 
1135  save2().alias( VoutFourier );
1136  save2.write((std::string) fn_out + "hermiticFourierVol.vol");
1137  }
1138 #endif
1140  // Awake threads
1141  barrier_wait( &barrier );
1142  // Threads are working now, wait for them to finish
1143  barrier_wait( &barrier );
1144 
1146  CenterFFT(Vout(),false);
1147 
1148  // Correct by the Fourier transform of the blob
1149  Vout().setXmippOrigin();
1153  double pad_relation= ((double)padding_factor_proj/padding_factor_vol);
1154  pad_relation = (pad_relation * pad_relation * pad_relation);
1155 
1156  MultidimArray<double> &mVout=Vout();
1157  double ipad_relation=1.0/pad_relation;
1158  double meanFactor2=0;
1160  {
1161  double radius=sqrt((double)(k*k+i*i+j*j));
1162  double aux=radius*iDeltaFourier;
1163  double factor = Fourier_blob_table(ROUND(aux));
1164  double factor2=(pow(Sinc(radius/(2*imgSize)),2));
1165  if (NiterWeight!=0)
1166  {
1167  A3D_ELEM(mVout,k,i,j) /= (ipad_relation*factor2*factor);
1168  meanFactor2+=factor2;
1169  }
1170  else
1171  A3D_ELEM(mVout,k,i,j) /= (ipad_relation*factor);
1172  }
1173  if (NiterWeight!=0)
1174  {
1175  meanFactor2/=MULTIDIM_SIZE(mVout);
1177  A3D_ELEM(mVout,k,i,j) *= meanFactor2;
1178  }
1179  Vout.write(out_name);
1180 }
1181 
1182 void ProgRecFourier::setIO(const FileName &fn_in, const FileName &fn_out)
1183 {
1184  this->fn_sel = fn_in;
1185  this->fn_out = fn_out;
1186 }
1187 
1189 {
1190  int yHalf=YSIZE(FourierWeights)/2;
1191  if (YSIZE(FourierWeights)%2==0)
1192  yHalf--;
1193  int zHalf=ZSIZE(FourierWeights)/2;
1194  if (ZSIZE(FourierWeights)%2==0)
1195  zHalf--;
1196  auto zsize=(int)ZSIZE(FourierWeights);
1197  int zsize_1=zsize-1;
1198  int ysize_1=(int)YSIZE(FourierWeights)-1;
1199  for (int k=0; k<zsize; k++)
1200  {
1201  int ksym=intWRAP(-k,0,zsize_1);
1202  for (int i=1; i<=yHalf; i++)
1203  {
1204  int isym=intWRAP(-i,0,ysize_1);
1205  double mean=0.5*(
1206  DIRECT_A3D_ELEM(FourierWeights,k,i,0)+
1207  DIRECT_A3D_ELEM(FourierWeights,ksym,isym,0));
1208  DIRECT_A3D_ELEM(FourierWeights,k,i,0)=
1209  DIRECT_A3D_ELEM(FourierWeights,ksym,isym,0)=mean;
1210  }
1211  }
1212  for (int k=1; k<=zHalf; k++)
1213  {
1214  int ksym=intWRAP(-k,0,zsize_1);
1215  double mean=0.5*(
1216  DIRECT_A3D_ELEM(FourierWeights,k,0,0)+
1217  DIRECT_A3D_ELEM(FourierWeights,ksym,0,0));
1218  DIRECT_A3D_ELEM(FourierWeights,k,0,0)=
1219  DIRECT_A3D_ELEM(FourierWeights,ksym,0,0)=mean;
1220  }
1221 }
int thrWidth
How many image rows are processed at a time by a single thread.
int barrier_init(barrier_t *barrier, int needed)
void init_progress_bar(long total)
struct blobtype blob
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
double alpha
Smoothness parameter.
Definition: blobs.h:121
Defocus U (Angstroms)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
MultidimArray< double > paddedImg
double maxResolution
Max resolution in Angstroms.
double getDoubleParam(const char *param, int arg=0)
virtual void read(int argc, const char **argv, bool reportErrors=true)
int NiterWeight
Number of iterations for the weight.
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
#define FINISHINGX(v)
void setThreadsNumber(int tNumber)
Definition: xmipp_fftw.h:119
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
double psi(const size_t n=0) const
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
#define MULTIDIM_SIZE(v)
constexpr int PROCESS_WEIGHTS
void sqrt(Image< double > &op)
int numThreads
Number of threads to use in parallel to process a single image.
constexpr int PROCESS_IMAGE
static double * y
int readSymmetryFile(FileName fn_sym, double accuracy=SYM_ACCURACY)
Definition: symmetries.cpp:33
barrier_t barrier
To create a barrier synchronization for threads.
FourierTransformer transformerImg
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define A1D_ELEM(v, i)
constexpr int PRELOAD_IMAGE
doublereal * w
void initConstant(T val)
Name for the CTF Model (std::string)
String integerToString(int I, int _width, char fill_with)
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(V)
double rot(const size_t n=0) const
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
#define FINISHINGZ(v)
#define DIGFREQ2FFT_IDX_DOUBLE(freq, size, idx)
Definition: xmipp_fft.h:70
void finishComputations(const FileName &out_name)
double weight(const size_t n=0) const
#define STARTINGX(v)
int * statusArray
A status array for each row in an image (processing, processed,etc..)
int barrier_destroy(barrier_t *barrier)
doublereal * x
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
size_t size() const override
#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
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
#define ACCURACY
double tilt(const size_t n=0) const
#define STARTINGY(v)
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
#define A3D_ELEM(V, k, i, j)
ImageThreadParams * th_args
Contains parameters passed to each thread.
#define BLOB_TABLE_SIZE_SQRT
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
#define DIRECT_A1D_ELEM(v, i)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
MultidimArray< std::complex< double > > VoutFourier
pthread_mutex_t workLoadMutex
Controls mutual exclusion on critical zones of code.
#define FLOOR(x)
Definition: xmipp_macros.h:240
const char * getParam(const char *param, int arg=0)
void processImages(int firstImageIndex, int lastImageIndex, bool saveFSC=false, bool reprocessFlag=false)
Process one image.
#define XX(v)
Definition: matrix1d.h:85
void correctWeight()
Method for the correction of the fourier coefficients.
void setReal(MultidimArray< double > &img)
Definition: xmipp_fftw.cpp:129
if(fabs(c[*nmax+ *nmax *c_dim1])==0.e0)
#define CEIL(x)
Definition: xmipp_macros.h:225
void readParams()
Read arguments from command line.
int in
size_t firstRowId() const override
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
void progress_bar(long rlen)
void write(const FileName &fn) const
#define blob_Fourier_val(w, blob)
Definition: blobs.h:174
free((char *) ob)
#define ZSIZE(v)
double z
void addExampleLine(const char *example, bool verbatim=true)
MultidimArray< std::complex< double > > * localPaddedFourier
#define ROUND(x)
Definition: xmipp_macros.h:210
Matrix1D< double > Fourier_blob_table
static void * processImageThread(void *threadArgs)
Defines what a thread should do.
void produceSideinfo()
Produce side info: fill arrays with relevant transformation matrices.
int verbose
Verbosity level.
Image< double > Vout
#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)
pthread_t * th_ids
IDs for the threads.
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
Matrix1D< double > fourierBlobTableSqrt
#define YY(v)
Definition: matrix1d.h:93
ProgRecFourier * parent
double Sinc(double Argument)
bool getValue(MDObject &mdValueOut, size_t id) const override
MultidimArray< double > FourierWeights
virtual void setIO(const FileName &fn_in, const FileName &fn_out)
Functions of common reconstruction interface.
MultidimArray< std::complex< double > > VoutFourierTmp
#define FINISHINGY(v)
MultidimArray< std::complex< double > > * paddedFourier
virtual void removeDisabled()
void getFourierAlias(T &V)
Definition: xmipp_fftw.h:207
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
double psi(const double x)
void write(const FileName &fn) const
Definition: matrix2d.cpp:113
FourierTransformer transformerVol
int order
Derivation order and Bessel function order.
Definition: blobs.h:118
Matrix2D< double > * localAInv
bool checkParam(const char *param)
int threadOpCode
Tells the threads what to do next.
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
Matrix2D< double > * symmetry
constexpr int EXIT_THREAD
std::vector< Matrix2D< double > > R_repository
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
#define blob_val(r, blob)
Definition: blobs.h:139
#define fastIntWRAP(y, x, x0, xF)
Definition: xmipp_macros.h:280
Matrix1D< double > blobTableSqrt
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
void sumWithFile(const FileName &fn)
Definition: xmipp_image.h:1105
int barrier_wait(barrier_t *barrier)
void defineParams()
Read arguments from command line.
int getIntParam(const char *param, int arg=0)
void enforceHermitianSymmetry()
Definition: xmipp_fftw.cpp:335
int trueSymsNo() const
Definition: symmetries.h:283
#define YXSIZE(v)
#define SGN(x)
Definition: xmipp_macros.h:155
double radius
Spatial radius in Universal System units.
Definition: blobs.h:115
Name of an image (std::string)
#define ZZ(v)
Definition: matrix1d.h:101
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272
void clear()
Definition: xmipp_image.h:144
void addParamsLine(const String &line)
void initIdentity()
Definition: matrix2d.h:673
void forceWeightSymmetry(MultidimArray< double > &FourierWeights)
Force the weights to be symmetrized.
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
size_t rowsProcessed
Number of rows already processed on an image.