Xmipp  v3.23.11-Nereus
image_rotational_pca.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar Sanchez Sorzano coss@cnb.csic.es (2002)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 // Translated from MATLAB code by Yoel Shkolnisky
27 
28 #include "image_rotational_pca.h"
30 #include "core/transformations.h"
31 #include "core/xmipp_funcs.h"
32 
33 // Empty constructor =======================================================
35 {
36  rank = 0;
37  verbose = 1;
38 }
39 
40 // MPI destructor
42 {
43  clearHbuffer();
44 }
45 
46 void
48 {
49  int nmax = Hbuffer.size();
50  for (int n = 0; n < nmax; n++)
51  delete[] Hbuffer[n];
52  Hbuffer.clear();
53 }
54 
55 // Read arguments ==========================================================
56 void
58 {
59  fnIn = getParam("-i");
60  fnRoot = getParam("--oroot");
61  Neigen = getIntParam("--eigenvectors");
62  Nits = getIntParam("--iterations");
63  max_shift_change = getDoubleParam("--max_shift_change");
64  psi_step = getDoubleParam("--psi_step");
65  shift_step = getDoubleParam("--shift_step");
66  maxNimgs = getIntParam("--maxImages");
67  Nthreads = getIntParam("--thr");
68 }
69 
70 // Show ====================================================================
71 void
73 {
74  if (!verbose)
75  return;
76  std::cout << "Input: " << fnIn << std::endl
77  << "Output root: " << fnRoot << std::endl
78  << "Number eigenvectors: " << Neigen << std::endl
79  << "Number iterations: " << Nits << std::endl << "Psi step: "
80  << psi_step << std::endl << "Max shift change: " << max_shift_change
81  << " step: " << shift_step << std::endl << "Max images: "
82  << maxNimgs << std::endl << "Number of threads: " << Nthreads
83  << std::endl;
84 }
85 
86 // usage ===================================================================
87 void
89 {
91  "Makes a rotational invariant representation of the image collection");
93  " -i <selfile> : Selfile with experimental images");
94  addParamsLine(" --oroot <rootname> : Rootname for output");
95  addParamsLine(" [--eigenvectors <N=200>] : Number of eigenvectors");
96  addParamsLine(" [--iterations <N=2>] : Number of iterations");
98  " [--max_shift_change <r=0>] : Maximum change allowed in shift");
99  addParamsLine(" [--psi_step <ang=1>] : Step in psi in degrees");
100  addParamsLine(" [--shift_step <r=1>] : Step in shift in pixels");
101  addParamsLine(" [--maxImages <N=-1>] : Maximum number of images");
102  addParamsLine(" [--thr <N=1>] : Number of threads");
103  addExampleLine("Typical use (4 nodes with 4 processors):", false);
105  "mpirun -np 4 `which xmipp_mpi_image_rotational_pca` -i images.stk --oroot images_eigen --thr 4");
106 }
107 
109 {
110  MetaDataVec MDaux;
111  MDaux.randomize(MDin);
112  MDin.selectPart(MDaux, 0, maxNimgs);
113 }
115 {
116 }
117 
119 {
120  fileMutex = std::make_unique<Mutex>();
121  threadMutex = std::make_unique<Mutex>();
122  taskDistributor = std::make_unique<ThreadTaskDistributor>(Nimgs, XMIPP_MAX(1,Nimgs/5));
123 }
124 
125 // Produce side info =====================================================
127 {
128  time_config();
129  MetaDataVec MDin(fnIn);
130 
131  if (maxNimgs > 0)
132  selectPartFromMd(MDin);
133 
134  Nimg = MDin.size();
135  size_t Ydim, Zdim, Ndim;
136  getImageSize(MDin, Xdim, Ydim, Zdim, Ndim);
137  Nangles = (int)floor(360.0 / psi_step);
138  Nshifts = (int)((2 * max_shift_change + 1) / shift_step);
139  Nshifts *= Nshifts;
140 
141  // Construct mask
144  double R2 = 0.25 * Xdim * Xdim;
146  A2D_ELEM(mask,i,j)=(i*i+j*j<R2);
147  Npixels = (int) mask.sum();
148 
149  // Thread Manager
150  thMgr = std::make_unique<ThreadManager>(Nthreads, this);
152  Matrix2D<double> dummyMatrix, dummyHblock, dummyW;
153  dummyW.resizeNoCopy(Npixels, Neigen + 2);
154  dummyHblock.resizeNoCopy(2 * Nangles * Nshifts, Neigen + 2);
155  for (int n = 0; n < Nthreads; ++n)
156  {
157  Wnode.push_back(dummyW);
158  Hblock.push_back(dummyHblock);
159  A.push_back(dummyMatrix);
160  I.push_back(dummy);
161  Iaux.push_back(dummy());
162  MD.push_back(MDin);
163  }
164 
165  Matrix2D<double> &W = Wnode[0];
166  FileName fnMatrixF(fnRoot + "_matrixF.raw");
167  FileName fnMatrixH(fnRoot + "_matrixH.raw");
168 
169  if (IS_MASTER)
170  {
171  // F (#images*#shifts*#angles) x (#eigenvectors+2)*(its+1)
173  Nimg * 2 * Nangles * Nshifts * (Neigen + 2) * (Nits + 1)
174  * sizeof(double));
175  // H (#images*#shifts*#angles) x (#eigenvectors+2)
177  Nimg * 2 * Nangles * Nshifts * (Neigen + 2) * sizeof(double));
178 
179  // Initialize with random numbers between -1 and 1
181  MAT_ELEM(W,i,j)=rnd_unif(-1.0,1.0);
182  }
183 
184  comunicateMatrix(W);
185 
186  F.mapToFile(fnMatrixF, (Neigen + 2) * (Nits + 1),
187  Nimg * 2 * Nangles * Nshifts);
188  H.mapToFile(fnMatrixH, Nimg * 2 * Nangles * Nshifts, Neigen + 2);
189 
190  // Prepare buffer
191  for (int n = 0; n < HbufferMax; n++)
192  Hbuffer.push_back(
193  new double[MAT_XSIZE(dummyHblock) * MAT_YSIZE(dummyHblock)]);
194 
195  // Construct a FileTaskDistributor
196  MDin.findObjects(objId);
197  size_t Nimgs = objId.size();
198  createMutexes(Nimgs);
199 }
200 
201 // Buffer =================================================================
202 void ProgImageRotationalPCA::writeToHBuffer(int idx, double *dest)
203 {
204  threadMutex->lock();
205  int n=HbufferDestination.size();
206  const Matrix2D<double> &Hblock_idx=Hblock[idx];
207  // COSS std::cout << "Copying block " << idx << " into " << n << "(" << Hbuffer.size() << ")" << std::endl;
208  memcpy(Hbuffer[n],&MAT_ELEM(Hblock_idx,0,0),MAT_XSIZE(Hblock_idx)*MAT_YSIZE(Hblock_idx)*sizeof(double));
209  HbufferDestination.push_back(dest);
210  if (n==(HbufferMax-1))
211  flushHBuffer();
212  threadMutex->unlock();
213 }
214 
216 {
217  int nmax=HbufferDestination.size();
218  const Matrix2D<double> &Hblock_0=Hblock[0];
219  fileMutex->lock();
220  for (int n=0; n<nmax; ++n)
221  memcpy(HbufferDestination[n],Hbuffer[n],MAT_XSIZE(Hblock_0)*MAT_YSIZE(Hblock_0)*sizeof(double));
222  fileMutex->unlock();
223  HbufferDestination.clear();
224 }
225 
226 // Apply T ================================================================
228 {
229  auto *self=(ProgImageRotationalPCA *) thArg.workClass;
230  //MpiNode *node=self->node;
231  int rank = self->rank;
232  std::vector<size_t> &objId=self->objId;
233  MetaDataVec &MD=self->MD[thArg.thread_id];
234 
235  Image<double> &I=self->I[thArg.thread_id];
236  MultidimArray<double> &Iaux=self->Iaux[thArg.thread_id];
237  Matrix2D<double> &Wnode=self->Wnode[thArg.thread_id];
238  Matrix2D<double> &Hblock=self->Hblock[thArg.thread_id];
239  Matrix2D<double> &A=self->A[thArg.thread_id];
240  Matrix2D<double> &H=self->H;
242  Wnode.initZeros(self->Npixels,MAT_XSIZE(H));
243 
244  const int unroll=8;
245  const int jmax=(MAT_XSIZE(Wnode)/unroll)*unroll;
246 
247  size_t first, last;
248  if (IS_MASTER && thArg.thread_id==0)
249  {
250  std::cout << "Applying T ...\n";
251  init_progress_bar(objId.size());
252  }
253  while (self->taskDistributor->getTasks(first, last))
254  {
255  for (size_t idx=first; idx<=last; ++idx)
256  {
257  // Read image
258  I.readApplyGeo(MD,objId[idx]);
259  MultidimArray<double> &mI=I();
260 
261  // Locate the corresponding index in Matrix H
262  // and copy a block in memory to speed up calculations
263  size_t Hidx=idx*2*self->Nangles*self->Nshifts;
264  memcpy(&MAT_ELEM(Hblock,0,0),&MAT_ELEM(H,Hidx,0),MAT_XSIZE(Hblock)*MAT_YSIZE(Hblock)*sizeof(double));
265 
266  // For each rotation, shift and mirror
267  int block_idx=0;
268  for (int mirror=0; mirror<2; ++mirror)
269  {
270  if (mirror)
271  {
272  mI.selfReverseX();
273  mI.setXmippOrigin();
274  }
275  for (double psi=0; psi<360; psi+=self->psi_step)
276  {
277  rotation2DMatrix(psi,A,true);
278  for (double y=-self->max_shift_change; y<=self->max_shift_change; y+=self->shift_step)
279  {
280  MAT_ELEM(A,1,2)=y;
281  for (double x=-self->max_shift_change; x<=self->max_shift_change; x+=self->shift_step, ++block_idx)
282  {
283  MAT_ELEM(A,0,2)=x;
284 
285  // Rotate and shift image
286  applyGeometry(xmipp_transformation::LINEAR,Iaux,mI,A,xmipp_transformation::IS_INV,true);
287 
288  // Update Wnode
289  int i=0;
291  {
292  if (DIRECT_MULTIDIM_ELEM(mask,n)==0)
293  continue;
294  double pixval=DIRECT_MULTIDIM_ELEM(Iaux,n);
295  double *ptrWnode=&MAT_ELEM(Wnode,i,0);
296  double *ptrHblock=&MAT_ELEM(Hblock,block_idx,0);
297  for (int j=0; j<jmax; j+=unroll, ptrHblock+=unroll, ptrWnode+=unroll)
298  {
299  (*ptrWnode) +=pixval*(*ptrHblock);
300  (*(ptrWnode+1)) +=pixval*(*(ptrHblock+1));
301  (*(ptrWnode+2)) +=pixval*(*(ptrHblock+2));
302  (*(ptrWnode+3)) +=pixval*(*(ptrHblock+3));
303  (*(ptrWnode+4)) +=pixval*(*(ptrHblock+4));
304  (*(ptrWnode+5)) +=pixval*(*(ptrHblock+5));
305  (*(ptrWnode+6)) +=pixval*(*(ptrHblock+6));
306  (*(ptrWnode+7)) +=pixval*(*(ptrHblock+7));
307  }
308  for (size_t j=jmax; j<MAT_XSIZE(Wnode); ++j, ptrHblock+=1, ptrWnode+=1)
309  (*ptrWnode) +=pixval*(*ptrHblock );
310  ++i;
311  }
312  }
313  }
314  }
315  }
316  }
317  if (IS_MASTER && thArg.thread_id==0)
318  progress_bar(last);
319  }
320 }
321 
323 {
324 }
325 
327 {
328  Matrix2D<double> &Wnode_0=Wnode[0];
329  Wnode_0.initZeros(Npixels,MAT_XSIZE(H));
330  taskDistributor->reset();
331  thMgr->run(threadApplyT);
332 
333  // Gather all Wnodes from all threads
334  for (int n=1; n<Nthreads; ++n)
335  Wnode_0 += Wnode[n];
336  allReduceApplyT(Wnode_0);
337  if (IS_MASTER)
338  progress_bar(objId.size());
339 }
340 
341 // Apply T ================================================================
343 {
344  auto *self=(ProgImageRotationalPCA *) thArg.workClass;
345  //MpiNode *node=self->node;
346  int rank = self->rank;
347  std::vector<size_t> &objId=self->objId;
348  MetaDataVec &MD=self->MD[thArg.thread_id];
349 
350  Image<double> &I=self->I[thArg.thread_id];
351  MultidimArray<double> &Iaux=self->Iaux[thArg.thread_id];
352  Matrix2D<double> &A=self->A[thArg.thread_id];
353  Matrix2D<double> &Hblock=self->Hblock[thArg.thread_id];
354  Matrix2D<double> &H=self->H;
355  Matrix2D<double> &Wtranspose=self->Wtranspose;
357 
358  const size_t unroll=8;
359  const size_t nmax=(MAT_XSIZE(Wtranspose)/unroll)*unroll;
360 
361  size_t first, last;
362  if (IS_MASTER && thArg.thread_id==0)
363  {
364  std::cout << "Applying Tt ...\n";
365  init_progress_bar(objId.size());
366  }
367  while (self->taskDistributor->getTasks(first, last))
368  {
369  for (size_t idx=first; idx<=last; ++idx)
370  {
371  // Read image
372  I.readApplyGeo(MD,objId[idx]);
373  MultidimArray<double> &mI=I();
374 
375  // For each rotation and shift
376  int block_idx=0;
377  for (int mirror=0; mirror<2; ++mirror)
378  {
379  if (mirror)
380  {
381  mI.selfReverseX();
382  mI.setXmippOrigin();
383  }
384  for (double psi=0; psi<360; psi+=self->psi_step)
385  {
386  rotation2DMatrix(psi,A,true);
387  for (double y=-self->max_shift_change; y<=self->max_shift_change; y+=self->shift_step)
388  {
389  MAT_ELEM(A,1,2)=y;
390  for (double x=-self->max_shift_change; x<=self->max_shift_change; x+=self->shift_step, ++block_idx)
391  {
392  MAT_ELEM(A,0,2)=x;
393 
394  // Rotate and shift image
395  applyGeometry(xmipp_transformation::LINEAR,Iaux,mI,A,xmipp_transformation::IS_INV,true);
396 
397  // Update Hblock
398  for (size_t j=0; j<MAT_XSIZE(Hblock); j++)
399  {
400  double dotproduct=0;
401  const double *ptrIaux=MULTIDIM_ARRAY(Iaux);
402  unsigned char *ptrMask=&DIRECT_MULTIDIM_ELEM(mask,0);
403  const double *ptrWtranspose=&MAT_ELEM(Wtranspose,j,0);
404  for (size_t n=0; n<nmax; n+=unroll, ptrIaux+=unroll, ptrMask+=unroll)
405  {
406  if (*ptrMask)
407  dotproduct+=(*ptrIaux)*(*ptrWtranspose++);
408  if (*(ptrMask+1))
409  dotproduct+=(*(ptrIaux+1))*(*ptrWtranspose++);
410  if (*(ptrMask+2))
411  dotproduct+=(*(ptrIaux+2))*(*ptrWtranspose++);
412  if (*(ptrMask+3))
413  dotproduct+=(*(ptrIaux+3))*(*ptrWtranspose++);
414  if (*(ptrMask+4))
415  dotproduct+=(*(ptrIaux+4))*(*ptrWtranspose++);
416  if (*(ptrMask+5))
417  dotproduct+=(*(ptrIaux+5))*(*ptrWtranspose++);
418  if (*(ptrMask+6))
419  dotproduct+=(*(ptrIaux+6))*(*ptrWtranspose++);
420  if (*(ptrMask+7))
421  dotproduct+=(*(ptrIaux+7))*(*ptrWtranspose++);
422  }
423  for (size_t n=nmax; n<MAT_XSIZE(Wtranspose); ++n, ++ptrMask, ++ptrIaux)
424  if (*ptrMask)
425  dotproduct+=(*ptrIaux)*(*ptrWtranspose++);
426  MAT_ELEM(Hblock,block_idx,j)=dotproduct;
427  }
428  }
429  }
430  }
431  }
432 
433  // Locate the corresponding index in Matrix H
434  // and copy block to disk
435  size_t Hidx=idx*2*self->Nangles*self->Nshifts;
436  // COSS std::cout << "idx=" << idx << " Hidx=" << Hidx << std::endl;
437  // COSS std::cout << "H shape " << MAT_YSIZE(H) << " x " << MAT_XSIZE(H) << std::endl;
438  self->writeToHBuffer(thArg.thread_id,&MAT_ELEM(H,Hidx,0));
439  }
440  if (IS_MASTER && thArg.thread_id==0)
441  progress_bar(last);
442  }
443 }
444 
446 {
447  // Compute W transpose to accelerate memory access
448  Matrix2D<double> &W=Wnode[0];
451  MAT_ELEM(Wtranspose,i,j) = MAT_ELEM(W,j,i);
452 
453  taskDistributor->reset();
454  thMgr->run(threadApplyTt);
455  flushHBuffer();
456  if (IS_MASTER)
457  progress_bar(objId.size());
458 }
459 
460 // QR =====================================================================
462 {
463  size_t jQ=0;
464  Matrix1D<double> qj1, qj2;
465  int iBlockMax=MAT_XSIZE(F)/4;
466 
467  for (size_t j1=0; j1<MAT_YSIZE(F); j1++)
468  {
469  F.getRow(j1,qj1);
470  // Project twice in the already established subspace
471  // One projection should be enough but Gram-Schmidt suffers
472  // from numerical problems
473  for (int it=0; it<2; it++)
474  {
475  for (size_t j2=0; j2<jQ; j2++)
476  {
477  F.getRow(j2,qj2);
478 
479  // Compute dot product
480  double s12=qj1.dotProduct(qj2);
481 
482  // Subtract the part of qj2 from qj1
483  double *ptr1=&VEC_ELEM(qj1,0);
484  const double *ptr2=&VEC_ELEM(qj2,0);
485  for (int i=0; i<iBlockMax; i++)
486  {
487  (*ptr1++)-=s12*(*ptr2++);
488  (*ptr1++)-=s12*(*ptr2++);
489  (*ptr1++)-=s12*(*ptr2++);
490  (*ptr1++)-=s12*(*ptr2++);
491  }
492  for (size_t i=iBlockMax*4; i<MAT_XSIZE(F); ++i)
493  (*ptr1++)-=s12*(*ptr2++);
494  }
495  }
496 
497  // Keep qj1 in Q if it has enough norm
498  double Rii=qj1.module();
499  if (Rii>1e-14)
500  {
501  // Make qj1 to be unitary and store in Q
502  qj1/=Rii;
503  F.setRow(jQ++,qj1);
504  }
505  }
506  return jQ;
507 }
508 
509 // Copy H to F ============================================================
511 {
512  size_t Hidx=block*MAT_XSIZE(H);
514  MAT_ELEM(F,Hidx+j,i)=MAT_ELEM(H,i,j);
515 }
516 
518 {
519  std::cout << "Performing QR decomposition ..." << std::endl;
520  qrDim = QR();
521 }
522 
524 {
525  FileName(fnRoot+"_matrixH.raw").createEmptyFileWithGivenLength(Nimg*2*Nangles*Nshifts*qrDim*sizeof(double));
526  H.mapToFile(fnRoot+"_matrixH.raw",MAT_XSIZE(F),qrDim);
528  MAT_ELEM(H,i,j)=MAT_ELEM(F,j,i);
529 }
530 
532 {
533  // Apply SVD and extract the basis
534  std::cout << "Performing SVD decomposition ..." << std::endl;
535  // SVD of W
536  Matrix2D<double> U,V;
538  svdcmp(Wnode[0],U,S,V);
539 
540  // Keep the first Neigen images from U
542  I().resizeNoCopy(Xdim,Xdim);
543  const MultidimArray<double> &mI=I();
544  FileName fnImg;
545  MetaDataVec MD;
546  for (int eig=0; eig<Neigen; eig++)
547  {
548  int Un=0;
551  DIRECT_MULTIDIM_ELEM(mI,n)=MAT_ELEM(U,Un++,eig);
552  fnImg.compose(eig+1,fnRoot,"stk");
553  I.write(fnImg);
554  size_t id=MD.addObject();
555  MD.setValue(MDL_IMAGE,fnImg,id);
556  MD.setValue(MDL_WEIGHT,VEC_ELEM(S,eig),id);
557  }
558  MD.write(fnRoot+".xmd");
559 }
560 
561 
562 // Run ====================================================================
564 {
565  show();
566  produceSideInfo();
567 
568  // Compute matrix F:
569  // Set H pointing to the first block of F
570  applyTt();// H=Tt(W)
571  copyHtoF(0);
572  for (int it=0; it<Nits; it++)
573  {
574  applyT(); // W=T(H)
575  applyTt();// H=Tt(W)
576  copyHtoF(it+1);
577  }
578  H.clear();
579  clearHbuffer();
580 
581  // QR decomposition of matrix F
582  int qrDim;
583 
584  comunicateQrDim(qrDim);
585 
586  if (qrDim==0)
587  REPORT_ERROR(ERR_VALUE_INCORRECT,"No subspace have been found");
588 
589  mapMatrix(qrDim);
590  F.clear();
591 
592  // Apply T
593  for (int n=0; n<Nthreads; ++n)
594  Hblock[n].resizeNoCopy(2*Nangles*Nshifts,qrDim);
595  applyT();
596 
597  // Free memory
598  H.clear();
599  Hblock.clear();
600 
601  applySVD();
602 
603  // Clean files
604  if (IS_MASTER)
605  {
606  unlink((fnRoot+"_matrixH.raw").c_str());
607  unlink((fnRoot+"_matrixF.raw").c_str());
608  }
609 }
void produceSideInfo()
Produce side info.
ProgImageRotationalPCA()
Empty constructor.
#define FOR_ALL_ELEMENTS_IN_MATRIX2D(m)
Definition: matrix2d.h:104
std::vector< Matrix2D< double > > Wnode
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
void init_progress_bar(long total)
int * nmax
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
virtual void copyHtoF(int block)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
double module() const
Definition: matrix1d.h:983
std::unique_ptr< ThreadManager > thMgr
double getDoubleParam(const char *param, int arg=0)
__host__ __device__ float2 floor(const float2 v)
virtual void createMutexes(size_t Nimgs)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
std::vector< Matrix2D< double > > A
std::vector< double * > Hbuffer
virtual void selectPartFromMd(MetaData &MDin)
void mapToFile(const FileName &fn, int Ydim, int Xdim, size_t offset=0)
Definition: matrix2d.cpp:1079
void resizeNoCopy(const MultidimArray< T1 > &v)
std::vector< Matrix2D< double > > Hblock
MultidimArray< unsigned char > mask
static double * y
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
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)
void createEmptyFileWithGivenLength(size_t length=0) const
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
virtual void comunicateQrDim(int &qrDim)
#define MULTIDIM_ARRAY(v)
virtual void selectPart(const MetaData &mdIn, size_t startPosition, size_t numberOfObjects, const MDLabel sortLabel=MDL_OBJID)=0
void compose(const String &str, const size_t no, const String &ext="")
virtual void allReduceApplyT(Matrix2D< double > &Wnode_0)
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
std::vector< Image< double > > I
std::vector< MetaDataVec > MD
void randomize(const MetaData &MDin)
doublereal * x
size_t size() const override
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
std::unique_ptr< Mutex > threadMutex
void resizeNoCopy(int Ydim, int Xdim)
Definition: matrix2d.h:534
void time_config()
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
double rnd_unif()
void clear()
Definition: matrix2d.h:473
glob_log first
const char * getParam(const char *param, int arg=0)
bool setValue(const MDObject &mdValueIn, size_t id)
double dotProduct(const Matrix1D< T > &op1) const
Definition: matrix1d.cpp:704
size_t addObject() override
void findObjects(std::vector< size_t > &objectsOut, const MDQuery &query) const override
#define IS_MASTER
std::vector< double * > HbufferDestination
void progress_bar(long rlen)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
std::unique_ptr< ThreadTaskDistributor > taskDistributor
std::vector< size_t > objId
#define DIRECT_MULTIDIM_ELEM(v, n)
void addExampleLine(const char *example, bool verbatim=true)
std::unique_ptr< Mutex > fileMutex
int verbose
Verbosity level.
double dummy
void * workClass
The class in which threads will be working.
void svdcmp(const Matrix2D< T > &a, Matrix2D< double > &u, Matrix1D< double > &w, Matrix2D< double > &v)
Definition: matrix2d.cpp:125
void rotation2DMatrix(T ang, Matrix2D< T > &result, bool homogeneous)
#define j
void threadApplyT(ThreadArgument &thArg)
void threadApplyTt(ThreadArgument &thArg)
void setRow(size_t i, const Matrix1D< T > &v)
Definition: matrix2d.cpp:910
virtual void mapMatrix(int qrDim)
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
double psi(const double x)
void initZeros()
Definition: matrix2d.h:626
int thread_id
The thread id.
void readParams()
Read argument from command line.
void addUsageLine(const char *line, bool verbatim=false)
int getIntParam(const char *param, int arg=0)
Incorrect value received.
Definition: xmipp_error.h:195
void getRow(size_t i, Matrix1D< T > &v) const
Definition: matrix2d.cpp:871
int * n
Name of an image (std::string)
void writeToHBuffer(int idx, double *dest)
double sum() const
std::vector< MultidimArray< double > > Iaux
void addParamsLine(const String &line)
< Score 4 for volumes
virtual void comunicateMatrix(Matrix2D< double > &W)
Matrix2D< double > Wtranspose