Xmipp  v3.23.11-Nereus
multidim_array.h
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
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 #ifndef CORE_MULTIDIM_ARRAY_H
27 #define CORE_MULTIDIM_ARRAY_H
28 
29 #include "xmipp_macros.h" // to define XMIPP_MMAP
30 #ifdef XMIPP_MMAP
31 #include <sys/mman.h>
32 #endif
33 #include <complex>
34 #include "matrix1d.h"
35 #include "xmipp_random_mode.h"
36 #include "multidim_array_base.h"
37 #include "xmipp_memory.h"
38 #include "axis_view.h"
39 
40 template<typename T>
41 class Matrix2D;
42 
43 extern int bestPrecision(float F, int _width);
44 extern String floatToString(float F, int _width, int _prec);
45 
48 
49 
50 
51 // Forward declarations ====================================================
52 template<typename T>
53 class MultidimArray;
54 
55 template<typename T>
56 void coreArrayByScalar(const MultidimArray<T>& op1, const T& op2,
57  MultidimArray<T>& result, char operation);
58 
59 template<typename T>
60 void coreScalarByArray(const T& op1, const MultidimArray<T>& op2,
61  MultidimArray<T>& result, char operation);
62 
63 template<typename T>
64 void coreArrayByArray(const MultidimArray<T>& op1, const MultidimArray<T>& op2,
65  MultidimArray<T>& result, char operation);
66 template<typename T>
68  MultidimArray<T>& result, char operation,
69  const MultidimArray<T> *mask);
70 
71 
72 
73 
74 
75 template<typename T>
76 class MultidimArray: public MultidimArrayBase
77 {
78 public:
79  /* The array itself.
80  The array is always a 3D array (Z,Y,X). For vectors the size of the array
81  is (1,1,X) and for matrices (1,Y,X). The pixel (i,j) (y,x) is at the
82  position data[i*Xdim+j] or data[y*Xdim+x]
83  */
84  T* data;
85 
86 public:
88 
89 
95  {
96  coreInit();
97  }
98 
102  MultidimArray(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, T *data) {
103  this->coreInit();
104  this->setDimensions(Xdim, Ydim, Zdim, Ndim);
105  this->data = data;
106  this->nzyxdimAlloc = this->nzyxdim;
107  this->destroyData = false;
108  }
109 
110 
115  MultidimArray(size_t Ndim, int Zdim, int Ydim, int Xdim)
116  {
117  coreInit();
118  coreAllocate(Ndim, Zdim, Ydim, Xdim);
119  }
120 
125  MultidimArray( int Zdim, int Ydim, int Xdim)
126  {
127  coreInit();
128  coreAllocate(1UL, Zdim, Ydim, Xdim);
129  }
130 
135  MultidimArray(int Ydim, int Xdim)
136  {
137  coreInit();
138  coreAllocate(1UL, 1, Ydim, Xdim);
139  }
140 
145  MultidimArray(int Xdim)
146  {
147  coreInit();
148  coreAllocate(1UL, 1, 1, Xdim);
149  }
150 
161  {
162  coreInit();
163  *this = V;
164  }
165 
176  {
177  coreInit();
178  swap(V);
179  }
180 
186  {
187  coreInit();
188  coreAllocate(1, 1, 1, V.size());
189  for (size_t i = 0; i < V.size(); i++)
190  DIRECT_A1D_ELEM(*this,i) = VEC_ELEM(V,i);
191  }
192 
198  MultidimArray(const std::vector<T> &vector)
199  {
200  coreInit();
201  coreAllocate(1, 1, 1, vector.size());
202  for (size_t i = 0; i < vector.size(); i++)
203  DIRECT_A1D_ELEM(*this,i) = vector[i];
204  }
205 
206 
209  virtual ~MultidimArray()
210  {
211  coreDeallocate();
212  }
213 
216  void clear()
217  {
218  coreDeallocate();
219  coreInit();
220  }
222 
224 
225 
229  void coreInit() noexcept
230  {
231  xdim = yxdim = zyxdim = nzyxdim = 0;
232  ydim = zdim = ndim = 0;
233  zinit = yinit = xinit = 0;
234  data = NULL;
235  nzyxdimAlloc = 0;
236  destroyData = true;
237  mmapOn = false;
238  mFd = NULL;
239  }
240 
241  void swap(MultidimArray<T>& other) noexcept
242  {
243  std::swap(xdim, other.xdim);
244  std::swap(ydim, other.ydim);
245  std::swap(zdim, other.zdim);
246  std::swap(ndim, other.ndim);
247  std::swap(yxdim, other.yxdim);
248  std::swap(zyxdim, other.zyxdim);
249  std::swap(nzyxdim, other.nzyxdim);
250  std::swap(xinit, other.xinit);
251  std::swap(yinit, other.yinit);
252  std::swap(zinit, other.zinit);
253  std::swap(data, other.data);
254  std::swap(nzyxdimAlloc, other.nzyxdimAlloc);
255  std::swap(destroyData, other.destroyData);
256  std::swap(mmapOn, other.mmapOn);
257  std::swap(mFd, other.mFd);
258  }
259 
262  void coreAllocate(size_t _ndim, int _zdim, int _ydim, int _xdim)
263  {
264  if (_ndim <= 0 || _zdim <= 0 || _ydim<=0 || _xdim<=0)
265  {
266  clear();
267  return;
268  }
269  if(data!=NULL)
270  REPORT_ERROR(ERR_MEM_NOTDEALLOC, "do not allocate space for an image if you have not deallocate it first");
271 
272  ndim=_ndim;
273  zdim=_zdim;
274  ydim=_ydim;
275  xdim=_xdim;
276  yxdim=(size_t)ydim*xdim;
277  zyxdim=yxdim*zdim;
279 
280  coreAllocate();
281  }
282 
290  {
291  if(data!=NULL)
292  REPORT_ERROR(ERR_MEM_NOTDEALLOC, "do not allocate space for an image if you have not deallocate it first");
293 
294  if (mmapOn)
295  mFd = mmapFile(data, nzyxdim);
296  else
297  {
298  try
299  {
300  data = new T [nzyxdim];
301  if (data == NULL)
302  {
303  setMmap(true);
304  mFd = mmapFile(data, nzyxdim);
305  }
306  }
307  catch (std::bad_alloc &)
308  {
309  setMmap(true);
310  mFd = mmapFile(data, nzyxdim);
311  }
312  }
313  memset(data,0,nzyxdim*sizeof(T));
315  }
316 
324  {
325  if(data != NULL && nzyxdim <= nzyxdimAlloc)
326  return;
327  else if (nzyxdim > nzyxdimAlloc)
328  coreDeallocate();
329 
330  if (mmapOn)
331  mFd = mmapFile(data, nzyxdim);
332  else
333  {
334  data = new T [nzyxdim];
335  if (data == NULL)
336  REPORT_ERROR(ERR_MEM_NOTENOUGH, "Allocate: No space left");
337  }
338  memset(data,0,nzyxdim*sizeof(T));
340  }
341 
342  /* Create a temporary file to mmap the data.
343  */
344  FILE* mmapFile(T* &_data, size_t nzyxDim) const;
345 
349  void coreDeallocate() noexcept
350  {
351  if (data != NULL && destroyData)
352  {
353  if (mmapOn)
354  {
355 #ifdef XMIPP_MMAP
356  munmap(data,nzyxdimAlloc*sizeof(T));
357  fclose(mFd);
358 #else
359 
360  REPORT_ERROR(ERR_MMAP,"Mapping not supported in Windows");
361 #endif
362 
363  }
364  else
365  delete[] data;
366  }
367  data = NULL;
368  destroyData = true;
369  nzyxdimAlloc = 0;
370  }
371 
379  void alias(const MultidimArray<T> &m)
380  {
381  coreDeallocate();
382  copyShape(m);
383  this->data=m.data;
384  this->nzyxdimAlloc = this->nzyxdim;
385  this->destroyData = false;
386  }
387 
396  void aliasRow(const MultidimArray<T> &m, size_t select_row)
397  {
398  if (select_row >= YSIZE(m))
399  REPORT_ERROR(ERR_MULTIDIM_SIZE, "aliasRow: Selected row cannot be higher than Y size.");
400 
401  coreDeallocate();
402  setDimensions(XSIZE(m),1, 1, 1);
403  this->data = m.data + XSIZE(m)*select_row;
404  this->nzyxdimAlloc = this->nzyxdim;
405  this->destroyData = false;
406  }
407 
416  void aliasSlice(const MultidimArray<T> &m, size_t select_slice)
417  {
418  if (select_slice >= ZSIZE(m))
419  REPORT_ERROR(ERR_MULTIDIM_SIZE, "aliasSlice: Selected slice cannot be higher than Z size.");
420 
421  coreDeallocate();
422  setDimensions(XSIZE(m), YSIZE(m), 1, 1);
423  this->data = m.data + XSIZE(m)*YSIZE(m)*(select_slice);
424  this->nzyxdimAlloc = this->nzyxdim;
425  this->destroyData = false;
426  }
427 
436  void aliasImageInStack(const MultidimArray<T> &m, size_t select_image)
437  {
438  if (select_image >= NSIZE(m))
439  REPORT_ERROR(ERR_MULTIDIM_SIZE, "aliasImageInStack: Selected image cannot be higher than N size.");
440  if (ZSIZE(m)!=1)
441  REPORT_ERROR(ERR_MULTIDIM_SIZE, "aliasImageInStack: This function is not meant for volumes");
442 
443  coreDeallocate();
444  setDimensions(XSIZE(m), YSIZE(m), 1, 1);
445  this->data = m.data + XSIZE(m)*YSIZE(m)*(select_image);
446  this->nzyxdimAlloc = this->nzyxdim;
447  this->destroyData = false;
448  }
449 
450 
451 
453 
455 
456 
457  /* These "using" declarations must be done due to c++ cannot overload methods that have been
458  * declared in base class.
459  */
463 
475  void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true);
476 
489  template<typename T1>
490  void resize(const MultidimArray<T1> &v, bool copy = true)
491  {
492  if (NSIZE(*this) != NSIZE(v) || XSIZE(*this) != XSIZE(v) ||
493  YSIZE(*this) != YSIZE(v) || ZSIZE(*this) != ZSIZE(v) || data==NULL)
494  resize(NSIZE(v), ZSIZE(v), YSIZE(v), XSIZE(v), copy);
495 
496  STARTINGX(*this) = STARTINGX(v);
497  STARTINGY(*this) = STARTINGY(v);
498  STARTINGZ(*this) = STARTINGZ(v);
499  }
500 
503  template<typename T1>
505  {
506  if (NSIZE(*this) != NSIZE(v) || XSIZE(*this) != XSIZE(v) ||
507  YSIZE(*this) != YSIZE(v) || ZSIZE(*this) != ZSIZE(v) || data==NULL)
508  resize(NSIZE(v), ZSIZE(v), YSIZE(v), XSIZE(v), false);
509 
510  STARTINGX(*this) = STARTINGX(v);
511  STARTINGY(*this) = STARTINGY(v);
512  STARTINGZ(*this) = STARTINGZ(v);
513  }
514 
520 #define checkDimension(dim) checkDimensionWithDebug(dim,__FILE__,__LINE__)
521  void checkDimensionWithDebug(int dim, const char *file, int line) const
522  {
523  if (getDim() != dim)
524  {
525  std::cerr<<" Check for dimension: " << dim <<std::endl;
526  std::cerr << "MultidimArray shape: ";
527  printShape(std::cerr);
528  std::cerr << std::endl;
529  std::cerr << "Check called from file "<<file<<" line "<<line<<std::endl;
530  exit(1);
531  }
532  }
533 
538  void selfWindow(int n0,int z0, int y0, int x0,
539  int nF,int zF, int yF, int xF,
540  T init_value = 0)
541  {
542  if (this->ndim >1)
543  REPORT_ERROR(ERR_MULTIDIM_DIM,"stack windowing not implemented");
544  if (this->zdim >1)
545  {//call 3Dwindow
546  selfWindow( z0, y0, x0,
547  zF, yF, xF,
548  init_value);
549  }
550  else if (this->ydim >1)
551  {//call 2Dwindow
552  selfWindow( y0, x0,
553  yF, xF,
554  init_value);
555 
556  }
557  else if (this->xdim >1)
558  {//call 1Dwindow
559  selfWindow( x0, xF, init_value);
560  }
561  }
562 
563  template <class T1>
564  void window(MultidimArray<T1> &result, int n0,int z0, int y0, int x0,
565  int nF,int zF, int yF, int xF,
566  T1 init_value = 0) const
567  {
568  if (this->ndim >1)
569  REPORT_ERROR(ERR_MULTIDIM_DIM,"stack windowing not implemented");
570  if (this->zdim >1)
571  {//call 3Dwindow
572  window(result, z0, y0, x0,
573  zF, yF, xF,
574  init_value);
575  }
576  else if (this->ydim >1)
577  {//call 2Dwindow
578  window(result, y0, x0,
579  yF, xF,
580  init_value);
581  }
582  else if (this->xdim >1)
583  {//call 1Dwindow
584  window(result, x0, xF, init_value);
585  }
586  }
587 
614  template <class T1>
615  void window(MultidimArray<T1> &result, int z0, int y0, int x0, int zF, int yF, int xF,
616  T1 init_value = 0) const
617  {
618  result.resizeNoCopy(zF - z0 + 1, yF - y0 + 1, xF - x0 + 1);
619  STARTINGZ(result) = z0;
620  STARTINGY(result) = y0;
621  STARTINGX(result) = x0;
622 
624  if ((k >= STARTINGZ(*this) && k <= FINISHINGZ(*this)) &&
625  (i >= STARTINGY(*this) && i <= FINISHINGY(*this)) &&
626  (j >= STARTINGX(*this) && j <= FINISHINGX(*this)))
627  A3D_ELEM(result, k, i, j) = (T1) A3D_ELEM(*this, k, i, j);
628  else
629  A3D_ELEM(result, k, i, j) = init_value;
630  }
631 
633  void selfWindow(int z0, int y0, int x0, int zF, int yF, int xF,
634  T init_value = 0)
635  {
636  if (z0 == STARTINGZ(*this) && zF == FINISHINGZ(*this) &&
637  y0 == STARTINGY(*this) && yF == FINISHINGY(*this) &&
638  x0 == STARTINGX(*this) && xF == FINISHINGX(*this))
639  return;
640 
641  MultidimArray<T> result;
642  window(result,z0,y0,x0,zF,yF,xF,init_value);
643  *this=result;
644  }
645 
665  template <class T1>
666  void window(MultidimArray<T1> &result, int y0, int x0, int yF, int xF,
667  T1 init_value = 0) const
668  {
669  result.resizeNoCopy(yF - y0 + 1, xF - x0 + 1);
670  STARTINGY(result) = y0;
671  STARTINGX(result) = x0;
672 
674  if (j >= STARTINGX(*this) && j <= FINISHINGX(*this) &&
675  i >= STARTINGY(*this) && i <= FINISHINGY(*this))
676  A2D_ELEM(result, i, j) = A2D_ELEM(*this, i, j);
677  else
678  A2D_ELEM(result, i, j) = init_value;
679  }
680 
682  void selfWindow(int y0, int x0, int yF, int xF,
683  T init_value = 0)
684  {
685  MultidimArray<T> result;
686  window(result,y0,x0,yF,xF,init_value);
687  *this=result;
688  }
689 
704  template <class T1>
705  void window(MultidimArray<T1> &result, int x0, int xF, T1 init_value = 0) const
706  {
707  result.resizeNoCopy(xF - x0 + 1);
708  STARTINGX(result) = x0;
709 
711  if (i >= STARTINGX(*this) && i <= FINISHINGX(*this))
712  A1D_ELEM(result, i) = A1D_ELEM(*this, i);
713  else
714  A1D_ELEM(result, i) = init_value;
715  }
716 
718  void selfWindow(int x0, int xF,
719  T init_value = 0)
720  {
721  MultidimArray<T> result;
722  window(result,x0,xF,init_value);
723  *this=result;
724  }
725 
727  void patch(MultidimArray<T> patchArray, int x, int y)
728  {
729  int n = XSIZE(patchArray)*sizeof(T);
730 
731  for (size_t i=0; i < YSIZE(patchArray); ++i)
732  memcpy(&dAij(*this, y+i, x), &dAij(patchArray, i, 0), n);
733  }
734 
736 
738 
739 
755  T& operator()(const Matrix1D< double >& v) const
756  {
757  switch (VEC_XSIZE(v))
758  {
759  case 1:
760  return A1D_ELEM((*this), ROUND(XX(v)));
761  case 2:
762  return A2D_ELEM((*this), ROUND(YY(v)), ROUND(XX(v)));
763  case 3:
764  return A3D_ELEM((*this), ROUND(ZZ(v)), ROUND(YY(v)), ROUND(XX(v)));
765  default:
766  REPORT_ERROR(ERR_ARG_INCORRECT,"Cannot handle indexes with dimension larger than 3");
767  }
768  }
769 
772  T& operator()(const Matrix1D< int >& v) const
773  {
774  switch (VEC_XSIZE(v))
775  {
776  case 1:
777  return A1D_ELEM((*this), XX(v));
778  case 2:
779  return A2D_ELEM((*this), YY(v), XX(v));
780  case 3:
781  return A3D_ELEM((*this), ZZ(v), YY(v), XX(v));
782  default:
783  REPORT_ERROR(ERR_ARG_INCORRECT,"Cannot handle indexes with dimension larger than 3");
784  }
785  }
786 
799  inline T& operator()(size_t n, int k, int i, int j) const
800  {
801  return NZYX_ELEM(*this, n, k, i, j);
802  }
803 
816  inline T& operator()(int k, int i, int j) const
817  {
818  return A3D_ELEM(*this, k, i, j);
819  }
820 
834  inline T& operator()(int i, int j) const
835  {
836  return A2D_ELEM(*this, i, j);
837  }
838 
851  inline T& operator()(int i) const
852  {
853  return A1D_ELEM(*this, i);
854  }
855 
856  inline T& operator[](size_t i) const
857  {
858  return data[i];
859  }
860 
861 
864  void* getArrayPointer() const
865  {
866  return (void*) data;
867 
868  }
869 
877  void getImage(size_t n, MultidimArray<T>& M, size_t n2 = 0) const
878  {
879  if (XSIZE(*this) == 0)
880  {
881  M.clear();
882  return;
883  }
884 
885  if (n > NSIZE(*this))
886  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS," Multidimarray getImage: n larger than NSIZE");
887 
888  if (ZSIZE(*this) != ZSIZE(M) || YSIZE(*this) != YSIZE(M) || XSIZE(*this) != XSIZE(M))
889  {
890  if (n2 == 0)
891  M.resizeNoCopy(*this);
892  else
893  REPORT_ERROR(ERR_MULTIDIM_SIZE, "MultidimArray::getImage: Target dimensions do not match source dimensions.");
894  }
895 
896  if (n2 > NSIZE(M))
897  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS," Multidimarray getImage: n larger than MultidimArray target NSIZE");
898 
899 
901  DIRECT_NZYX_ELEM(M, n2, k, i, j) = DIRECT_NZYX_ELEM(*this, n, k, i, j);
902 
903  STARTINGX(M) = STARTINGX(*this);
904  STARTINGY(M) = STARTINGY(*this);
905  STARTINGZ(M) = STARTINGZ(*this);
906  }
907 
920  template <typename T1>
921  void getSlice(int k, MultidimArray<T1>& M, char axis = 'Z', bool reverse = false, size_t n = 0) const
922  {
923  if (XSIZE(*this) == 0)
924  {
925  M.clear();
926  return;
927  }
928 
929  T* ptr=NULL;
930  switch (axis)
931  {
932  case 'Z':
933  if (k < STARTINGZ(*this) || k > FINISHINGZ(*this))
935  "Slice: Multidim subscript (k) out of range");
936 
937  M.resize(1, 1, YSIZE(*this), XSIZE(*this),false);
938  k = k - STARTINGZ(*this);
939 
940  if (reverse)
941  {
942  int zEnd = ZSIZE(*this) - 1;
944  DIRECT_A2D_ELEM(M, i, j) = (T1) DIRECT_NZYX_ELEM(*this, n, k, zEnd-i, j);
945  }
946  else
947  {
948  ptr=&(DIRECT_NZYX_ELEM(*this, n, k, 0, 0));
950  DIRECT_MULTIDIM_ELEM(M, n) = (T1) *(ptr++);
951  }
952 
953  STARTINGX(M) = STARTINGX(*this);
954  STARTINGY(M) = STARTINGY(*this);
955  break;
956  case 'Y':
957  if (k < STARTINGY(*this) || k > FINISHINGY(*this))
959  "Slice: Multidim subscript (i) out of range");
960 
961  k = k - STARTINGY(*this);
962  M.resizeNoCopy(ZSIZE(*this), XSIZE(*this));
963 
964  if (reverse)
965  {
966  int zEnd = ZSIZE(*this) - 1;
968  DIRECT_A2D_ELEM(M, i, j) = (T1) DIRECT_NZYX_ELEM(*this, n, zEnd-i, k, j);
969  }
970  else
971  {
973  DIRECT_A2D_ELEM(M, i, j) = (T1) DIRECT_NZYX_ELEM(*this, n, i, k, j);
974  }
975 
976  STARTINGX(M) = STARTINGX(*this);
977  STARTINGY(M) = STARTINGZ(*this);
978  break;
979  case 'X':
980  if (k < STARTINGX(*this) || k > FINISHINGX(*this))
982  "Slice: Multidim subscript (j) out of range");
983 
984  k = k - STARTINGX(*this);
985  M.resizeNoCopy(YSIZE(*this), ZSIZE(*this));
986 
987  if (reverse)
988  {
989  int zEnd = ZSIZE(*this) - 1;
991  DIRECT_A2D_ELEM(M, i, j) = (T1) DIRECT_NZYX_ELEM(*this, n, zEnd-j, i, k);
992  }
993  else
994  {
996  DIRECT_A2D_ELEM(M, i, j) = (T1) DIRECT_NZYX_ELEM(*this, n, j, i, k);
997  }
998 
999  STARTINGX(M) = STARTINGY(*this);
1000  STARTINGY(M) = STARTINGZ(*this);
1001  break;
1002  default:
1004  formatString("Slice: not supported axis %c", axis));
1005  }
1006  }
1007 
1009  void getSliceAsMatrix(size_t k, Matrix2D<T> &m) const;
1010 
1011 
1015  {
1016  m.vdim = NZYXSIZE(*this);
1017  m.destroyData = false;
1018  m.row = true;
1019  m.vdata = data;
1020  }
1021 
1032  template <typename T1>
1033  void setSlice(int k, const MultidimArray<T1>& v, size_t n=0)
1034  {
1035  if (xdim == 0)
1036  return;
1037 
1038  if (k < STARTINGZ(*this) || k > FINISHINGZ(*this))
1040  "setSlice: MultidimArray subscript (k=%d) out of range [%d, %d]",
1041  k,STARTINGZ(*this),FINISHINGZ(*this)));
1042 
1043  if (v.rowNumber() != YSIZE(*this) || v.colNumber() != XSIZE(*this))
1045  "setSlice: MultidimArray dimensions different from the matrix ones");
1046 
1047  k-=STARTINGZ(*this);
1048  T *ptr=&(DIRECT_NZYX_ELEM(*this, n, k, 0, 0));
1050  *(ptr++) = (T) DIRECT_MULTIDIM_ELEM(v, n);
1051  }
1052 
1061  template <typename T1>
1062  void reslice(MultidimArray<T1>& out, AxisView face, bool flip = false, size_t n = 0) const
1063  {
1064  ArrayDim aDim, aDimOut;
1065  getDimensions(aDim);
1066 
1067  char axis='Z';
1068  bool reverse=false;
1069 
1070  aDimOut = aDim;
1071 
1072  if (face == VIEW_Y_NEG || face == VIEW_Y_POS)
1073  {
1074  axis = 'Y';
1075  aDimOut.ydim = aDim.zdim;
1076  aDimOut.zdim = aDim.ydim;
1077  reverse = (face == VIEW_Y_NEG);
1078  }
1079  else if (face == VIEW_X_NEG || face == VIEW_X_POS)
1080  {
1081  axis = 'X';
1082  aDimOut.xdim = aDim.zdim;
1083  aDimOut.zdim = aDim.xdim;
1084  reverse = (face == VIEW_X_NEG);
1085  }
1086 
1087  flip = flip^reverse;
1088 
1089  out.resize(aDimOut, false);
1090 
1091  MultidimArray<T1> imTemp;
1092 
1093  int index;
1094 
1095  for (size_t k = 0; k < aDimOut.zdim; k++)
1096  {
1097  imTemp.aliasSlice(out, k);
1098  index = k + (aDimOut.zdim - 1 - 2*k) * (int)flip;
1099  this->getSlice(index, imTemp, axis, !reverse);
1100  }
1101  }
1102 
1109  void reslice(AxisView face, bool flip = false, size_t n = 0)
1110  {
1111  MultidimArray<T> mTemp;
1112  reslice(mTemp, face, flip, n);
1113  *this = mTemp;
1114  }
1115 
1126  void getCol(size_t j, MultidimArray<T>& v) const
1127  {
1128  if (xdim == 0 || ydim == 0)
1129  {
1130  v.clear();
1131  return;
1132  }
1133 
1134  if (j >= xdim)
1135  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS,"getCol: Matrix subscript (j) greater than matrix dimension");
1136 
1137  v.resizeNoCopy(ydim);
1138  for (size_t i = 0; i < ydim; i++)
1139  DIRECT_A1D_ELEM(v,i) = DIRECT_A2D_ELEM(*this,i, j);
1140  }
1141 
1151  void setCol(size_t j, const MultidimArray<T>& v)
1152  {
1153  if (xdim == 0 || ydim == 0)
1154  REPORT_ERROR(ERR_MULTIDIM_EMPTY, "setCol: Target matrix is empty");
1155 
1156  if (j>= xdim)
1157  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, "setCol: Matrix subscript (j) out of range");
1158 
1159  if (v.xdim != ydim)
1161  "setCol: Vector dimension different from matrix one");
1162 
1163  for (size_t i = 0; i < ydim; i++)
1164  DIRECT_A2D_ELEM(*this,i, j) = DIRECT_A1D_ELEM(v,i);
1165  }
1166 
1178  void getRow(size_t i, MultidimArray<T>& v) const
1179  {
1180  if (xdim == 0 || ydim == 0)
1181  {
1182  v.clear();
1183  return;
1184  }
1185 
1186  if (i >= ydim)
1187  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, "getRow: Matrix subscript (i) greater than matrix dimension");
1188 
1189  v.resizeNoCopy(xdim);
1190  memcpy(&A1D_ELEM(v,0),&A2D_ELEM(*this,i,0),xdim*sizeof(T));
1191  }
1192 
1201  void setRow(int i, const MultidimArray<T>& v)
1202  {
1203  if (xdim == 0 || ydim == 0)
1204  REPORT_ERROR(ERR_MULTIDIM_EMPTY, "setRow: Target matrix is empty");
1205 
1206  if (i < 0 || i >= ydim)
1207  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, "setRow: Matrix subscript (i) out of range");
1208 
1209  if (v.xdim != xdim)
1211  "setRow: Vector dimension different from matrix one");
1212 
1213  memcpy(&A2D_ELEM(*this,i,0),&A1D_ELEM(v,0),xdim*sizeof(T));
1214  }
1215 
1216  void getReal(MultidimArray< double > & realImg) const
1217  {
1218  REPORT_ERROR(ERR_TYPE_INCORRECT, "MultidimArray: Non complex datatype.");
1219  }
1220 
1221  void getImag(MultidimArray< double > & imagImg) const
1222  {
1223  REPORT_ERROR(ERR_TYPE_INCORRECT, "MultidimArray: Non complex datatype.");
1224  }
1225 
1226 
1235  void toPhysical(int k_log, int i_log, int j_log,
1236  int& k_phys, int& i_phys, int& j_phys) const
1237  {
1238  k_phys = k_log - STARTINGZ(*this);
1239  i_phys = i_log - STARTINGY(*this);
1240  j_phys = j_log - STARTINGX(*this);
1241  }
1242 
1251  void toLogical(int k_phys, int i_phys, int j_phys,
1252  int& k_log, int& i_log, int& j_log) const
1253  {
1254  k_log = k_phys + STARTINGZ(*this);
1255  i_log = i_phys + STARTINGY(*this);
1256  j_log = j_phys + STARTINGX(*this);
1257  }
1258 
1267  void toPhysical(int i_log, int j_log, int& i_phys, int& j_phys) const
1268  {
1269  i_phys = i_log - STARTINGY(*this);
1270  j_phys = j_log - STARTINGX(*this);
1271  }
1272 
1281  void toLogical(int i_phys, int j_phys, int &i_log, int& j_log) const
1282  {
1283  i_log = i_phys + STARTINGY(*this);
1284  j_log = j_phys + STARTINGX(*this);
1285  }
1286 
1295  void toPhysical(int i_log, int& i_phys) const
1296  {
1297  i_phys = i_log - STARTINGX(*this);
1298  }
1299 
1308  void toLogical(int i_phys, int& i_log) const
1309  {
1310  i_log = i_phys + STARTINGX(*this);
1311  }
1312 
1317  T interpolatedElement3D(double x, double y, double z, T outside_value = (T) 0) const
1318  {
1319  int x0 = FLOOR(x);
1320  double fx = x - x0;
1321  int x1 = x0 + 1;
1322 
1323  int y0 = FLOOR(y);
1324  double fy = y - y0;
1325  int y1 = y0 + 1;
1326 
1327  int z0 = FLOOR(z);
1328  double fz = z - z0;
1329  int z1 = z0 + 1;
1330 
1331  double doutside_value=outside_value;
1332  double d000 = (OUTSIDE3D(z0, y0, x0)) ? doutside_value : A3D_ELEM(*this, z0, y0, x0);
1333  double d001 = (OUTSIDE3D(z0, y0, x1)) ? doutside_value : A3D_ELEM(*this, z0, y0, x1);
1334  double d010 = (OUTSIDE3D(z0, y1, x0)) ? doutside_value : A3D_ELEM(*this, z0, y1, x0);
1335  double d011 = (OUTSIDE3D(z0, y1, x1)) ? doutside_value : A3D_ELEM(*this, z0, y1, x1);
1336  double d100 = (OUTSIDE3D(z1, y0, x0)) ? doutside_value : A3D_ELEM(*this, z1, y0, x0);
1337  double d101 = (OUTSIDE3D(z1, y0, x1)) ? doutside_value : A3D_ELEM(*this, z1, y0, x1);
1338  double d110 = (OUTSIDE3D(z1, y1, x0)) ? doutside_value : A3D_ELEM(*this, z1, y1, x0);
1339  double d111 = (OUTSIDE3D(z1, y1, x1)) ? doutside_value : A3D_ELEM(*this, z1, y1, x1);
1340 
1341  double dx00 = LIN_INTERP(fx, d000, d001);
1342  double dx01 = LIN_INTERP(fx, d100, d101);
1343  double dx10 = LIN_INTERP(fx, d010, d011);
1344  double dx11 = LIN_INTERP(fx, d110, d111);
1345  double dxy0 = LIN_INTERP(fy, dx00, dx10);
1346  double dxy1 = LIN_INTERP(fy, dx01, dx11);
1347 
1348  return (T) LIN_INTERP(fz, dxy0, dxy1);
1349  }
1350 
1355  T interpolatedElement2D(double x, double y, T outside_value = (T) 0) const
1356  {
1357  int x0 = floor(x);
1358  double fx = x - x0;
1359  int x1 = x0 + 1;
1360  int y0 = floor(y);
1361  double fy = y - y0;
1362  int y1 = y0 + 1;
1363 
1364  int i0=STARTINGY(*this);
1365  int j0=STARTINGX(*this);
1366  int iF=FINISHINGY(*this);
1367  int jF=FINISHINGX(*this);
1368 
1369 #define ASSIGNVAL2D(d,i,j) \
1370  if ((j) < j0 || (j) > jF || (i) < i0 || (i) > iF) \
1371  d=outside_value;\
1372  else \
1373  d=A2D_ELEM(*this, i, j);
1374 
1375  double d00, d10, d11, d01;
1376  ASSIGNVAL2D(d00,y0,x0);
1377  ASSIGNVAL2D(d01,y0,x1);
1378  ASSIGNVAL2D(d10,y1,x0);
1379  ASSIGNVAL2D(d11,y1,x1);
1380 
1381  double d0 = LIN_INTERP(fx, d00, d01);
1382  double d1 = LIN_INTERP(fx, d10, d11);
1383  return (T) LIN_INTERP(fy, d0, d1);
1384  }
1385 
1391  T interpolatedElement2DOutsideZero(double x, double y) const
1392  {
1393  int x0 = floor(x);
1394  double fx = x - x0;
1395  int x1 = x0 + 1;
1396  int y0 = floor(y);
1397  double fy = y - y0;
1398  int y1 = y0 + 1;
1399 
1400  int i0=STARTINGY(*this);
1401  int j0=STARTINGX(*this);
1402  int iF=FINISHINGY(*this);
1403  int jF=FINISHINGX(*this);
1404 
1405  int b;
1406 #define ASSIGNVAL2DNODIV(d,i,j) \
1407  b = ((j) < j0 || (j) > jF || (i) < i0 || (i) > iF); \
1408  b ? d=0 : d=A2D_ELEM(*this, i, j);
1409 
1410  double d00, d10, d11, d01;
1411  ASSIGNVAL2DNODIV(d00,y0,x0);
1412  ASSIGNVAL2DNODIV(d01,y0,x1);
1413  ASSIGNVAL2DNODIV(d10,y1,x0);
1414  ASSIGNVAL2DNODIV(d11,y1,x1);
1415 
1416  double d0 = LIN_INTERP(fx, d00, d01);
1417  double d1 = LIN_INTERP(fx, d10, d11);
1418  return (T) LIN_INTERP(fy, d0, d1);
1419  }
1420 
1425  T interpolatedElement1D(double x, T outside_value = (T) 0) const
1426  {
1427  int x0 = floor(x);
1428  double fx = x - x0;
1429  int x1 = x0 + 1;
1430 
1431  int j0=STARTINGX(*this);
1432  int jF=FINISHINGX(*this);
1433 
1434 #define ASSIGNVAL1D(d,j) \
1435  if ((j) < j0 || (j) > jF) \
1436  d=outside_value;\
1437  else \
1438  d=A1D_ELEM(*this, j);
1439 
1440  double d0, d1;
1441  ASSIGNVAL1D(d0,x0);
1442  ASSIGNVAL1D(d1,x1);
1443 
1444  return (T) LIN_INTERP(fx, d0, d1);
1445  }
1446 
1452  T interpolatedElementBSpline3D(double x, double y, double z,
1453  int SplineDegree = 3) const;
1454 
1471  T interpolatedElementBSpline2D(double x, double y, int SplineDegree = 3) const;
1472 
1473  T interpolatedElementBSpline2D_Degree3(double x, double y) const;
1474 
1490  T interpolatedElementBSpline1D(double x, int SplineDegree = 3) const;
1492 
1494 
1495 
1507  void printStats(std::ostream& out = std::cout) const
1508  {
1509  T minval, maxval;
1510  double avgval, devval;
1511 
1512  computeStats(avgval, devval, minval, maxval);
1513 
1514  out.setf(std::ios::showpoint);
1515  int old_prec = out.precision(7);
1516 
1517  out << " min= ";
1518  out.width(9);
1519  out << minval;
1520  out << " max= ";
1521  out.width(9);
1522  out << maxval;
1523  out << " avg= ";
1524  out.width(9);
1525  out << avgval;
1526  out << " dev= ";
1527  out.width(9);
1528  out << devval;
1529 
1530  out.precision(old_prec);
1531  }
1532 
1537  T computeMax() const
1538  {
1539  if (NZYXSIZE(*this) <= 0)
1540  return static_cast< T >(0);
1541 
1542  T maxval = data[0];
1543 
1544  T* ptr=NULL;
1545  size_t n;
1547  if (*ptr > maxval)
1548  maxval = *ptr;
1549 
1550  return maxval;
1551  }
1552 
1557  void maxIndex(int& jmax) const
1558  {
1559  size_t zeroLong=0;
1560  int zeroInt=0;
1561  maxIndex(zeroLong,zeroInt,zeroInt,jmax);
1562  }
1563 
1568  T computeMin() const
1569  {
1570  if (NZYXSIZE(*this) <= 0)
1571  return static_cast< T >(0);
1572 
1573  T minval = data[0];
1574 
1575  T* ptr=NULL;
1576  size_t n;
1578  if (*ptr < minval)
1579  minval = *ptr;
1580 
1581  return minval;
1582  }
1583 
1589  void minIndex(int &lmin, int& kmin, int& imin, int& jmin) const
1590  {
1591  if (XSIZE(*this) == 0)
1592  {
1593  lmin = kmin = imin = jmin = -1;
1594  return;
1595  }
1596 
1597  kmin = STARTINGZ(*this);
1598  imin = STARTINGY(*this);
1599  jmin = STARTINGX(*this);
1600  lmin = 0;
1601  size_t n=0;
1602  T minval = DIRECT_MULTIDIM_ELEM(*this, n);
1603 
1605  {
1606  T val=DIRECT_MULTIDIM_ELEM(*this,n);
1607  if (val > minval)
1608  {
1609  minval = val;
1610  lmin = l;
1611  kmin = k;
1612  imin = i;
1613  jmin = j;
1614  }
1615  ++n;
1616  }
1617  }
1618 
1623  void minIndex(int& kmin, int& imin, int& jmin) const
1624  {
1625  int zeroInt=0;
1626  minIndex(zeroInt,kmin,imin,jmin);
1627  }
1628 
1633  void minIndex(int& imin, int& jmin) const
1634  {
1635  int zeroInt=0;
1636  minIndex(zeroInt,zeroInt,imin,jmin);
1637  }
1638 
1643  void minIndex(int& jmin) const
1644  {
1645  int zeroInt=0;
1646  minIndex(zeroInt,zeroInt,zeroInt,jmin);
1647  }
1648 
1654  void maxIndex(size_t &lmax, int& kmax, int& imax, int& jmax) const
1655  {
1656  if (XSIZE(*this) == 0)
1657  {
1658  lmax = kmax = imax = jmax = -1;
1659  return;
1660  }
1661 
1662  kmax = STARTINGZ(*this);
1663  imax = STARTINGY(*this);
1664  jmax = STARTINGX(*this);
1665  lmax = 0;
1666  size_t n=0;
1667  T maxval = DIRECT_MULTIDIM_ELEM(*this, n);
1668 
1670  {
1671  T val=DIRECT_MULTIDIM_ELEM(*this, n);
1672  if (val > maxval)
1673  {
1674  maxval = val;
1675  lmax = l;
1676  kmax = k;
1677  imax = i;
1678  jmax = j;
1679  }
1680  ++n;
1681  }
1682  }
1683 
1688  void computeDoubleMinMax(double& minval, double& maxval) const
1689  {
1690  if (NZYXSIZE(*this) <= 0)
1691  return;
1692 
1693  T* ptr=NULL;
1694  size_t n;
1695  T Tmin=DIRECT_MULTIDIM_ELEM(*this,0);
1696  T Tmax=Tmin;
1698  {
1699  T val=*ptr;
1700  if (val < Tmin)
1701  Tmin = val;
1702  else if (val > Tmax)
1703  Tmax = val;
1704  }
1705  minval = static_cast< double >(Tmin);
1706  maxval = static_cast< double >(Tmax);
1707  }
1708 
1713  void computeDoubleMinMaxRange(double& minval, double& maxval,size_t offset, size_t size) const
1714  {
1715  if (NZYXSIZE(*this) <= 0)
1716  return;
1717 
1718  minval = maxval = static_cast< double >(data[offset]);
1719 
1720  T* ptr=NULL;
1721  T val;
1722  size_t n;
1723 
1724  for (n=offset,ptr=data+offset; n<size; ++n, ++ptr)
1725  {
1726  val = *ptr;
1727  if (val < minval)
1728  minval = static_cast< double >(val);
1729  else if (val > maxval)
1730  maxval = static_cast< double >(val);
1731  }
1732  }
1733 
1739  double computeAvg() const
1740  {
1741  if (NZYXSIZE(*this) <= 0)
1742  return 0;
1743 
1744  double sum = 0;
1745 
1746  T* ptr=NULL;
1747  size_t n;
1749  sum += static_cast< double >(*ptr);
1750 
1751  return sum / NZYXSIZE(*this);
1752  }
1753 
1760  double computeStddev() const
1761  {
1762  if (NZYXSIZE(*this) <= 1)
1763  return 0;
1764 
1765  double avg = 0, stddev = 0;
1766 
1767  T* ptr=NULL;
1768  size_t n;
1770  {
1771  double val=static_cast< double >(*ptr);
1772  avg += val;
1773  stddev += val * val;
1774  }
1775 
1776  avg /= NZYXSIZE(*this);
1777  stddev = stddev / NZYXSIZE(*this) - avg * avg;
1778  stddev *= NZYXSIZE(*this) / (NZYXSIZE(*this) - 1);
1779 
1780  // Foreseeing numerical instabilities
1781  stddev = sqrt(static_cast<double>((ABS(stddev))));
1782 
1783  return stddev;
1784  }
1785 
1791  void computeStats(double& avg, double& stddev, T& minval, T& maxval) const
1792  {
1793  if (NZYXSIZE(*this) <= 0)
1794  return;
1795 
1796  avg = 0;
1797  stddev = 0;
1798 
1799  minval = maxval = data[0];
1800 
1801  T* ptr=NULL;
1802  size_t n;
1804  {
1805  T Tval=*ptr;
1806  double val=Tval;
1807  avg += val;
1808  stddev += val * val;
1809 
1810  if (Tval > maxval)
1811  maxval = Tval;
1812  else if (Tval < minval)
1813  minval = Tval;
1814  }
1815 
1816  avg /= NZYXSIZE(*this);
1817 
1818  if (NZYXSIZE(*this) > 1)
1819  {
1820  stddev = stddev / NZYXSIZE(*this) - avg * avg;
1821  stddev *= NZYXSIZE(*this) / (NZYXSIZE(*this) - 1);
1822 
1823  // Foreseeing numerical instabilities
1824  stddev = sqrt(static_cast< double >(ABS(stddev)));
1825  }
1826  else
1827  stddev = 0;
1828  }
1829 
1835  template<typename U>
1836  void computeAvgStdev(U& avg, U& stddev) const
1837  {
1838  static_assert(
1839  std::is_same<double, U>::value || std::is_same<float, U>::value,
1840  "U must be a floating presiont type");
1841  if (NZYXSIZE(*this) <= 0)
1842  return;
1843 
1844  avg = 0;
1845  stddev = 0;
1846  const size_t nMax = nzyxdim;
1847  for (size_t n = 0; n < nMax; ++n)
1848  {
1849  U v = (U)data[n];
1850  avg += v;
1851  stddev += v * v;
1852  }
1853 
1854  avg /= NZYXSIZE(*this);
1855 
1856  if (NZYXSIZE(*this) > 1)
1857  {
1858  stddev = stddev / NZYXSIZE(*this) - avg * avg;
1859  stddev *= NZYXSIZE(*this) / (NZYXSIZE(*this) - 1);
1860 
1861  // Foreseeing numerical instabilities
1862  stddev = sqrt(fabs(stddev));
1863  }
1864  else
1865  stddev = 0;
1866  }
1867 
1874  double& avg, double& stddev) const
1875  {
1876  double sum1 = 0;
1877  double sum2 = 0;
1878  double N = 0;
1879 
1881  {
1882  if (DIRECT_MULTIDIM_ELEM(mask, n) != 0)
1883  {
1884  ++N;
1885  double aux=DIRECT_MULTIDIM_ELEM(*this, n);
1886  sum1 += aux;
1887  sum2 += aux*aux;
1888  }
1889  }
1890 
1891  // average and standard deviation
1892  avg = sum1 / N;
1893  if (N > 1)
1894  stddev = sqrt(fabs(sum2 / N - avg * avg) * N / (N - 1));
1895  else
1896  stddev = 0;
1897  }
1898 
1899  void computeMedian_within_binary_mask(const MultidimArray< int >& mask, double& median) const;
1900 
1906  void computeStats(double& avg,
1907  double& stddev,
1908  T& min_val,
1909  T& max_val,
1910  Matrix1D< int >& corner1,
1911  Matrix1D< int >& corner2,
1912  size_t n = 0)
1913  {
1914  (*this).checkDimension(2);
1915  min_val = max_val = NZYX_ELEM((*this), n, 0, YY(corner1), XX(corner1));
1916 
1917  Matrix1D< double > r(3);
1918  double N = 0, sum = 0, sum2 = 0;
1919 
1920  FOR_ALL_ELEMENTS_IN_ARRAY2D_BETWEEN(corner1, corner2)
1921  {
1922  sum += (*this)(r);
1923  sum2 += (*this)(r) * (*this)(r);
1924  N++;
1925 
1926  if ((*this)(r) < min_val)
1927  min_val = (*this)(r);
1928  else if ((*this)(r) > max_val)
1929  max_val = (*this)(r);
1930  }
1931 
1932  if (N != 0)
1933  {
1934  avg = sum / N;
1935  stddev = sqrt(sum2 / N - avg * avg);
1936  }
1937  else
1938  {
1939  avg = stddev = 0;
1940  }
1941  }
1942 
1951  double computeMedian() const
1952  {
1953  if (XSIZE(*this) == 0)
1954  return 0;
1955 
1956  if (XSIZE(*this) == 1)
1957  return DIRECT_MULTIDIM_ELEM(*this,0);
1958 
1959  // Initialise data
1960  MultidimArray<T> temp;
1961  this->sort(temp);
1962 
1963  // Get median
1964  if (NZYXSIZE(*this)%2==0)
1965  return 0.5*(DIRECT_MULTIDIM_ELEM(temp,NZYXSIZE(*this)/2-1)+
1966  DIRECT_MULTIDIM_ELEM(temp,NZYXSIZE(*this)/2 ));
1967  else
1968  return DIRECT_MULTIDIM_ELEM(temp,NZYXSIZE(*this)/2);
1969  }
1970 
1982  void rangeAdjust(T minF, T maxF)
1983  {
1984  if (NZYXSIZE(*this) <= 0)
1985  return;
1986 
1987  double min0=0., max0=0.;
1988  computeDoubleMinMax(min0, max0);
1989 
1990  // If max0==min0, it means that the vector is a constant one, so the
1991  // only possible transformation is to a fixed minF
1992  double slope;
1993  if (max0 != min0)
1994  slope = static_cast< double >(maxF - minF) /
1995  static_cast< double >(max0 - min0);
1996  else
1997  slope = 0;
1998 
1999  T* ptr=NULL;
2000  size_t n;
2002  *ptr = minF + static_cast< T >(slope *
2003  static_cast< double >(*ptr - min0));
2004  }
2005 
2018  // This function must be explicitly implemented outside
2019  void rangeAdjust(T minF, T maxF, MultidimArray<int> &mask)
2020  {
2021  if (MULTIDIM_SIZE(*this) <= 0)
2022  return;
2023 
2024  double min0=0., max0=0.;
2025  bool first=true;
2026  T* ptr=NULL;
2027  size_t n;
2028  int * ptrMask=MULTIDIM_ARRAY(mask);
2030  {
2031  if (*ptrMask)
2032  {
2033  T val= *ptr;
2034  if (first)
2035  {
2036  min0=max0=(double)val;
2037  first=false;
2038  }
2039  else
2040  {
2041  min0=XMIPP_MIN(min0,val);
2042  max0=XMIPP_MAX(max0,val);
2043  }
2044  }
2045  ptrMask++;
2046  }
2047 
2048  // If max0==min0, it means that the vector is a constant one, so the
2049  // only possible transformation is to a fixed minF
2050  double slope;
2051  if (max0 != min0)
2052  slope = static_cast< double >(maxF - minF) /
2053  static_cast< double >(max0 - min0);
2054  else
2055  slope = 0;
2056 
2058  *ptr = minF + static_cast< T >(slope *
2059  static_cast< double >(*ptr - min0));
2060  }
2061 
2070  //As written this will only work for T=double
2071  //nevertheless since this is used is better
2072  //to use T than double or will create problem for int multidim arrays
2073  void rangeAdjust(const MultidimArray<T> &example,
2074  const MultidimArray<int> *mask=NULL)
2075  {
2076  if (NZYXSIZE(*this) <= 0)
2077  return;
2078 
2079  double avgExample=0., stddevExample=0., avgThis, stddevThis;
2080  if (mask!=NULL)
2081  {
2082  example.computeAvgStdev_within_binary_mask(*mask,avgExample,stddevExample);
2083  computeAvgStdev_within_binary_mask(*mask,avgThis,stddevThis);
2084  }
2085  else
2086  {
2087  computeAvgStdev(avgThis,stddevThis);
2088  example.computeAvgStdev(avgExample,stddevExample);
2089  }
2090 
2091  // y=a+bx
2092  double b=stddevThis>0? stddevExample/stddevThis:0;
2093  double a=avgExample-avgThis*b;
2094 
2095  size_t n;
2096  T *ptr=NULL;
2098  *ptr = static_cast< T >(a+b * static_cast< double > (*ptr));
2099  }
2100 
2112  // This function must be explicitly implemented outside.
2113  template<typename U>
2114  void statisticsAdjust(U avgF, U stddevF)
2115  {
2116  static_assert(
2117  std::is_same<double, U>::value || std::is_same<float, U>::value,
2118  "U must be a floating presiont type");
2119  U avg0 = 0;
2120  U stddev0 = 0;
2121 
2122  if (NZYXSIZE(*this) == 0)
2123  return;
2124 
2125  computeAvgStdev(avg0, stddev0);
2126 
2127  U a = (stddev0 != 0) ? (stddevF / stddev0) : 0;
2128  U b = avgF - a * avg0;
2129 
2130  T* ptr=&DIRECT_MULTIDIM_ELEM(*this,0);
2131  size_t nmax=(nzyxdim/4)*4;
2132  for (size_t n=0; n<nmax; n+=4, ptr+=4)
2133  {
2134  *(ptr )= static_cast< T >(a * (*(ptr )) + b);
2135  *(ptr+1)= static_cast< T >(a * (*(ptr+1)) + b);
2136  *(ptr+2)= static_cast< T >(a * (*(ptr+2)) + b);
2137  *(ptr+3)= static_cast< T >(a * (*(ptr+3)) + b);
2138  }
2139  for (size_t n=nmax; n<nzyxdim; ++n, ptr+=1)
2140  *(ptr )= static_cast< T >(a * (*(ptr )) + b);
2141  }
2143 
2158 
2163  inline friend void coreArrayByArray(const MultidimArray<T>& op1,
2164  const MultidimArray<T>& op2, MultidimArray<T>& result,
2165  char operation)
2166  {
2167  T* ptrResult=NULL;
2168  T* ptrOp1=NULL;
2169  T* ptrOp2=NULL;
2170  size_t n;
2171  // Loop unrolling
2172  const size_t unroll=4;
2173  size_t nmax=unroll*(op1.nzyxdim/unroll);
2174  switch (operation)
2175  {
2176  case '+':
2177  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data;
2178  n<nmax; n+=unroll, ptrResult+=unroll, ptrOp1+=unroll, ptrOp2+=unroll)
2179  {
2180  *ptrResult = *ptrOp1 + *ptrOp2;
2181  *(ptrResult+1) = *(ptrOp1+1) + *(ptrOp2+1);
2182  *(ptrResult+2) = *(ptrOp1+2) + *(ptrOp2+2);
2183  *(ptrResult+3) = *(ptrOp1+3) + *(ptrOp2+3);
2184  }
2185  for (n=nmax, ptrResult=result.data+nmax, ptrOp1=op1.data+nmax, ptrOp2=op2.data+nmax;
2186  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1, ++ptrOp2)
2187  *ptrResult = *ptrOp1 + *ptrOp2;
2188  break;
2189  case '-':
2190  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data;
2191  n<nmax; n+=unroll, ptrResult+=unroll, ptrOp1+=unroll, ptrOp2+=unroll)
2192  {
2193  *ptrResult = *ptrOp1 - *ptrOp2;
2194  *(ptrResult+1) = *(ptrOp1+1) - *(ptrOp2+1);
2195  *(ptrResult+2) = *(ptrOp1+2) - *(ptrOp2+2);
2196  *(ptrResult+3) = *(ptrOp1+3) - *(ptrOp2+3);
2197  }
2198  for (n=nmax, ptrResult=result.data+nmax, ptrOp1=op1.data+nmax, ptrOp2=op2.data+nmax;
2199  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1, ++ptrOp2)
2200  *ptrResult = *ptrOp1 - *ptrOp2;
2201  break;
2202  case '*':
2203  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data;
2204  n<nmax; n+=unroll, ptrResult+=unroll, ptrOp1+=unroll, ptrOp2+=unroll)
2205  {
2206  *ptrResult = *ptrOp1 * *ptrOp2;
2207  *(ptrResult+1) = *(ptrOp1+1) * *(ptrOp2+1);
2208  *(ptrResult+2) = *(ptrOp1+2) * *(ptrOp2+2);
2209  *(ptrResult+3) = *(ptrOp1+3) * *(ptrOp2+3);
2210  }
2211  for (n=nmax, ptrResult=result.data+nmax, ptrOp1=op1.data+nmax, ptrOp2=op2.data+nmax;
2212  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1, ++ptrOp2)
2213  *ptrResult = *ptrOp1 * *ptrOp2;
2214  break;
2215  case '/':
2216  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data;
2217  n<nmax; n+=unroll, ptrResult+=unroll, ptrOp1+=unroll, ptrOp2+=unroll)
2218  {
2219  *ptrResult = *ptrOp1 / *ptrOp2;
2220  *(ptrResult+1) = *(ptrOp1+1) / *(ptrOp2+1);
2221  *(ptrResult+2) = *(ptrOp1+2) / *(ptrOp2+2);
2222  *(ptrResult+3) = *(ptrOp1+3) / *(ptrOp2+3);
2223  }
2224  for (n=nmax, ptrResult=result.data+nmax, ptrOp1=op1.data+nmax, ptrOp2=op2.data+nmax;
2225  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1, ++ptrOp2)
2226  *ptrResult = *ptrOp1 / *ptrOp2;
2227  break;
2228  }
2229  }
2230 
2235  inline friend void selfCoreArrayByArrayMask(const MultidimArray<T>& op1,
2236  const MultidimArray<T>& op2, MultidimArray<T>& result,
2237  char operation, const MultidimArray<T>* mask)
2238  {
2239  T* ptrResult=NULL;
2240  T* ptrOp1=NULL;
2241  T* ptrOp2=NULL;
2242  T* ptrMask=NULL;
2243  T zero;
2244  zero = T(0);
2245  size_t n;
2246  switch (operation)
2247  {
2248  case '+':
2249  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data,
2250  ptrMask=mask->data;
2251  n<op1.nzyxdim; n++, ptrResult++,
2252  ptrOp1++, ptrOp2++, ptrMask++)
2253  {
2254  if ((*ptrMask)==zero)
2255  *ptrResult += (*ptrOp1);
2256  else
2257  *ptrResult += (*ptrOp2);//(*ptrOp2) * (*ptrMask);
2258  }
2259  break;
2260  case '-':
2261  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data,
2262  ptrMask=mask->data;
2263  n<op1.nzyxdim; n++, ptrResult++,
2264  ptrOp1++, ptrOp2++, ptrMask++)
2265  {
2266  if ((*ptrMask)==zero)
2267  *ptrResult -= (*ptrOp1);
2268  else
2269  *ptrResult -= (*ptrOp2) * (*ptrMask);
2270  }
2271  break;
2272  //NOTE: not clear if this should be the default case for * and / operators
2273  case '*':
2274  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data,
2275  ptrMask=mask->data;
2276  n<op1.nzyxdim; n++, ptrResult++,
2277  ptrOp1++, ptrOp2++, ptrMask++)
2278  {
2279  if ((*ptrMask)==zero)
2280  *ptrResult *= (*ptrOp1);
2281  else
2282  *ptrResult *= (*ptrOp2) * (*ptrMask);
2283  }
2284  break;
2285  case '/':
2286  for (n=0, ptrResult=result.data, ptrOp1=op1.data,ptrOp2=op2.data,
2287  ptrMask=mask->data;
2288  n<op1.nzyxdim; n++, ptrResult++,
2289  ptrOp1++, ptrOp2++, ptrMask++)
2290  {
2291  if ((*ptrMask)==zero)
2292  *ptrResult /= (*ptrOp1);
2293  else
2294  *ptrResult /= (*ptrOp2) * (*ptrMask);
2295  }
2296  break;
2297  }
2298  }
2299 
2300 
2310  inline friend void arrayByArray(const MultidimArray<T>& op1,
2311  const MultidimArray<T>& op2,
2312  MultidimArray<T>& result,
2313  char operation)
2314  {
2315  if (!op1.sameShape(op2))
2317  formatString("Array_by_array: different shapes (%c)", operation));
2318  if (result.data == NULL || !result.sameShape(op1))
2319  result.resizeNoCopy(op1);
2320  coreArrayByArray(op1, op2, result, operation);
2321  }
2329  inline friend void selfArrayByArrayMask(const MultidimArray<T>& op1,
2330  const MultidimArray<T>& op2,
2331  MultidimArray<T>& result,
2332  char operation, const MultidimArray<T> *mask=NULL)
2333  {
2334  if (!op1.sameShape(op2) || !result.sameShape(op1))
2336  formatString("Array_by_array: different shapes (%c)", operation));
2337  selfCoreArrayByArrayMask(op1, op2, result, operation, mask);
2338  }
2339 
2343  {
2344  MultidimArray<T> tmp;
2345  arrayByArray(*this, op1, tmp, '+');
2346  return tmp;
2347  }
2348 
2352  {
2353  MultidimArray<T> tmp;
2354  arrayByArray(*this, op1, tmp, '-');
2355  return tmp;
2356  }
2357 
2361  {
2362  MultidimArray<T> tmp;
2363  arrayByArray(*this, op1, tmp, '*');
2364  return tmp;
2365  }
2366 
2370  {
2371  MultidimArray<T> tmp;
2372  arrayByArray(*this, op1, tmp, '/');
2373  return tmp;
2374  }
2375 
2378  void operator+=(const MultidimArray<T>& op1)
2379  {
2380  arrayByArray(*this, op1, *this, '+');
2381  }
2382 
2385  void operator-=(const MultidimArray<T>& op1)
2386  {
2387  arrayByArray(*this, op1, *this, '-');
2388  }
2389 
2392  void operator*=(const MultidimArray<T>& op1)
2393  {
2394  arrayByArray(*this, op1, *this, '*');
2395  }
2396 
2399  void operator/=(const MultidimArray<T>& op1)
2400  {
2401  arrayByArray(*this, op1, *this, '/');
2402  }
2403 
2405  double dotProduct(const MultidimArray<T>& op1)
2406  {
2407  if (!sameShape(op1))
2408  REPORT_ERROR(ERR_MULTIDIM_SIZE,"The two arrays for dot product are not of the same shape");
2409  double dot=0;
2410  size_t n;
2411  T* ptrOp1=NULL;
2412  T* ptrOp2=NULL;
2413  const size_t unroll=4;
2414  size_t nmax=unroll*(MULTIDIM_SIZE(*this)/unroll);
2415  for (n=0, ptrOp1=data,ptrOp2=op1.data;
2416  n<nmax; n+=unroll, ptrOp1+=unroll, ptrOp2+=unroll)
2417  {
2418  dot += *ptrOp1 * *ptrOp2;
2419  dot += *(ptrOp1+1) * *(ptrOp2+1);
2420  dot += *(ptrOp1+2) * *(ptrOp2+2);
2421  dot += *(ptrOp1+3) * *(ptrOp2+3);
2422  }
2423  for (n=nmax, ptrOp1=data+nmax, ptrOp2=op1.data+nmax;
2424  n<MULTIDIM_SIZE(*this); ++n, ++ptrOp1, ++ptrOp2)
2425  dot += *ptrOp1 * *ptrOp2;
2426  return dot;
2427  }
2429 
2441 
2448  inline friend void coreArrayByScalar(const MultidimArray<T>& op1,
2449  const T& op2,
2450  MultidimArray<T>& result,
2451  char operation)
2452  {
2453  T* ptrResult=NULL;
2454  T* ptrOp1=NULL;
2455  size_t n;
2456  switch (operation)
2457  {
2458  case '+':
2459  for (n=0, ptrResult=result.data, ptrOp1=op1.data;
2460  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1)
2461  *ptrResult = *ptrOp1 + op2;
2462  break;
2463  case '-':
2464  for (n=0, ptrResult=result.data, ptrOp1=op1.data;
2465  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1)
2466  *ptrResult = *ptrOp1 - op2;
2467  break;
2468  case '*':
2469  for (n=0, ptrResult=result.data, ptrOp1=op1.data;
2470  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1)
2471  *ptrResult = *ptrOp1 * op2;
2472  break;
2473  case '/':
2474  for (n=0, ptrResult=result.data, ptrOp1=op1.data;
2475  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1)
2476  *ptrResult = *ptrOp1 / op2;
2477  break;
2478  case '=':
2479  for (n=0, ptrResult=result.data, ptrOp1=op1.data;
2480  n<op1.zyxdim; ++n, ++ptrResult, ++ptrOp1)
2481  *ptrResult = *ptrOp1 == op2;
2482  break;
2483  }
2484  }
2485 
2496  inline friend void arrayByScalar(const MultidimArray<T>& op1,
2497  T op2,
2498  MultidimArray<T>& result,
2499  char operation)
2500  {
2501  if (result.data == NULL || !result.sameShape(op1))
2502  result.resizeNoCopy(op1);
2503  coreArrayByScalar(op1, op2, result, operation);
2504  }
2505 
2509  {
2510  MultidimArray<T> tmp;
2511  arrayByScalar(*this, op1, tmp, '+');
2512  return tmp;
2513  }
2514 
2518  {
2519  MultidimArray<T> tmp;
2520  arrayByScalar(*this, op1, tmp, '-');
2521  return tmp;
2522  }
2523 
2527  {
2528  MultidimArray<T> tmp;
2529  arrayByScalar(*this, op1, tmp, '*');
2530  return tmp;
2531  }
2532 
2536  {
2537  MultidimArray<T> tmp;
2538  arrayByScalar(*this, op1, tmp, '/');
2539  return tmp;
2540  }
2541 
2542 
2545  void equal(T op1, MultidimArray<char> &result) const
2546  {
2547  result.resizeNoCopy(*this);
2549  DIRECT_MULTIDIM_ELEM(result,n) = DIRECT_MULTIDIM_ELEM(*this,n) == op1;
2550  }
2551 
2556  void operator+=(const T& op1)
2557  {
2558  arrayByScalar(*this, op1, *this, '+');
2559  }
2560 
2565  void operator-=(const T& op1)
2566  {
2567  arrayByScalar(*this, op1, *this, '-');
2568  }
2569 
2574  void operator*=(const T& op1)
2575  {
2576  arrayByScalar(*this, op1, *this, '*');
2577  }
2578 
2583  void operator/=(const T& op1)
2584  {
2585  arrayByScalar(*this, op1, *this, '/');
2586  }
2588 
2601 
2608  inline friend void coreScalarByArray(const T& op1,
2609  const MultidimArray<T>& op2,
2610  MultidimArray<T>& result,
2611  char operation)
2612  {
2613  T* ptrResult=NULL;
2614  T* ptrOp2=NULL;
2615  size_t n;
2616  for (n=0, ptrResult=result.data, ptrOp2=op2.data;
2617  n<op2.zyxdim; ++n, ++ptrResult, ++ptrOp2)
2618  switch (operation)
2619  {
2620  case '+':
2621  *ptrResult = op1 + *ptrOp2;
2622  break;
2623  case '-':
2624  *ptrResult = op1 - *ptrOp2;
2625  break;
2626  case '*':
2627  *ptrResult = op1 * *ptrOp2;
2628  break;
2629  case '/':
2630  *ptrResult = op1 / *ptrOp2;
2631  break;
2632  }
2633  }
2634 
2645  inline friend void scalarByArray(T op1,
2646  const MultidimArray<T>& op2,
2647  MultidimArray<T>& result,
2648  char operation)
2649  {
2650  if (result.data == NULL || !result.sameShape(op2))
2651  result.resizeNoCopy(op2);
2652  coreScalarByArray(op1, op2, result, operation);
2653  }
2654 
2657  friend MultidimArray<T> operator+(T op1, const MultidimArray<T>& op2)
2658  {
2659  MultidimArray<T> tmp;
2660  scalarByArray(op1, op2, tmp, '+');
2661  return tmp;
2662  }
2663 
2666  friend MultidimArray<T> operator-(T op1, const MultidimArray<T>& op2)
2667  {
2668  MultidimArray<T> tmp;
2669  scalarByArray(op1, op2, tmp, '-');
2670  return tmp;
2671  }
2672 
2675  friend MultidimArray<T> operator*(T op1, const MultidimArray<T>& op2)
2676  {
2677  MultidimArray<T> tmp;
2678  scalarByArray(op1, op2, tmp, '*');
2679  return tmp;
2680  }
2681 
2684  friend MultidimArray<T> operator/(T op1, const MultidimArray<T>& op2)
2685  {
2686  MultidimArray<T> tmp;
2687  scalarByArray(op1, op2, tmp, '/');
2688  return tmp;
2689  }
2691 
2694 
2705  void initConstant(T val)
2706  {
2707  T* ptr=NULL;
2708  size_t n;
2710  *ptr = val;
2711  }
2712 
2722  template <typename T1>
2724  {
2725  if (data == NULL || !sameShape(op))
2726  resizeNoCopy(op);
2727  memset(data,0,nzyxdim*sizeof(T));
2728  }
2729 
2739  inline void initZeros()
2740  {
2741  memset(data,0,nzyxdim*sizeof(T));
2742  }
2743 
2746  inline void initZeros(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim)
2747  {
2748  if (xdim!=Xdim || ydim!=Ydim || zdim!=Zdim || ndim!=Ndim)
2749  resize(Ndim, Zdim,Ydim,Xdim,false);
2750  memset(data,0,nzyxdim*sizeof(T));
2751  }
2752 
2755  void initZeros(int Xdim)
2756  {
2757  initZeros(1, 1, 1, Xdim);
2758  }
2759 
2762  void initZeros(int Ydim, int Xdim)
2763  {
2764  initZeros(1, 1, Ydim, Xdim);
2765  }
2766 
2769  void initZeros(int Zdim, int Ydim, int Xdim)
2770  {
2771  initZeros(1, Zdim, Ydim, Xdim);
2772  }
2773 
2797  void initLinear(T minF, T maxF, int n = 1, const String& mode = "incr")
2798  {
2799  double slope;
2800  int steps;
2801 
2802  if (mode == "incr")
2803  {
2804  steps = 1 + (int) FLOOR((double) ABS((maxF - minF)) / ((double) n));
2805  slope = n * SGN(maxF - minF);
2806  }
2807  else if (mode == "steps")
2808  {
2809  steps = n;
2810  slope = (maxF - minF) / (steps - 1);
2811  }
2812  else
2813  REPORT_ERROR(ERR_VALUE_INCORRECT, "Init_linear: Mode not supported (" + mode +
2814  ")");
2815 
2816  if (steps == 0)
2817  clear();
2818  else
2819  {
2820  resizeNoCopy(steps);
2821  for (int i = 0; i < steps; i++)
2822  A1D_ELEM(*this, i) = (T)((double) minF + slope * i);
2823  }
2824  }
2825 
2847  void initRandom(double op1, double op2, RandomMode mode = RND_UNIFORM);
2848 
2875  void addNoise(double op1,
2876  double op2,
2877  const String& mode = "uniform",
2878  double df = 3.) const;
2880 
2887 
2894  T*** adaptForNumericalRecipes3D(size_t n = 0) const
2895  {
2896  T*** m = NULL;
2897  ask_Tvolume(m, 1, ZSIZE(*this), 1, YSIZE(*this), 1, XSIZE(*this));
2898 
2900  m[k+1][i+1][j+1] = DIRECT_NZYX_ELEM(*this, n, k, i, j);
2901 
2902  return m;
2903  }
2904 
2908  {
2909  free_Tvolume(m, 1, ZSIZE(*this), 1, YSIZE(*this), 1, XSIZE(*this));
2910  }
2911 
2918  T** adaptForNumericalRecipes2D(size_t n = 0) const
2919  {
2920  T** m = NULL;
2921  ask_Tmatrix(m, 1, YSIZE(*this), 1, XSIZE(*this));
2922 
2924  m[i+1][j+1] = DIRECT_NZYX_ELEM(*this, n, 0, i, j);
2925 
2926  return m;
2927  }
2928 
2936  {
2937  return MULTIDIM_ARRAY(*this) - 1 - XSIZE(*this);
2938  }
2939 
2942  void loadFromNumericalRecipes2D(T** m, int Ydim, int Xdim)
2943  {
2944  resizeNoCopy(Ydim, Xdim);
2945 
2946  for (int i = 1; i <= Ydim; i++)
2947  for (int j = 1; j <= Xdim; j++)
2948  DIRECT_A2D_ELEM(*this,i - 1, j - 1) = m[i][j];
2949  }
2950 
2956  {
2957  free_Tmatrix(m, 1, YSIZE(*this), 1, XSIZE(*this));
2958  }
2959 
2965  {}
2966 
2977  {
2978  return MULTIDIM_ARRAY(*this) - 1;
2979  }
2980 
2988  {}
2989 
2992  void centerOfMass(Matrix1D< double >& center, void * mask=NULL, size_t n = 0)
2993  {
2994  center.initZeros(3);
2995  double mass = 0;
2996  MultidimArray< int >* imask = (MultidimArray< int >*) mask;
2997 
2999  {
3000  if ((imask == NULL || NZYX_ELEM(*imask, n, k, i, j)) &&
3001  A3D_ELEM(*this, k, i, j) > 0)
3002  {
3003  XX(center) += j * NZYX_ELEM(*this, n, k, i, j);
3004  YY(center) += i * NZYX_ELEM(*this, n, k, i, j);
3005  ZZ(center) += k * NZYX_ELEM(*this, n, k, i, j);
3006 
3007  mass += NZYX_ELEM(*this, n, k, i, j);
3008  }
3009  }
3010 
3011  if (mass != 0)
3012  center /= mass;
3013  }
3014 
3024  void sort(MultidimArray<T> &result) const;
3025 
3038  void indexSort(MultidimArray< int > &indx) const;
3039 
3043  {
3044  MultidimArray<int> indx;
3045  indexSort(indx);
3046  cdf.resizeNoCopy(*this);
3047  double iSize=1.0/XSIZE(indx);
3049  {
3050  int ii=A1D_ELEM(indx,i)-1;
3051  A1D_ELEM(cdf,ii)=(i+1)*iSize;
3052  }
3053  }
3054 
3089  void threshold(const String& type,
3090  T a,
3091  T b=0,
3092  MultidimArray<int> * mask = NULL )
3093  {
3094  int mode;
3095 
3096  if (type == "abs_above")
3097  mode = 1;
3098  else if (type == "abs_below")
3099  mode = 2;
3100  else if (type == "above")
3101  mode = 3;
3102  else if (type == "below")
3103  mode = 4;
3104  else if (type == "range")
3105  mode = 5;
3106  else if (type == "soft")
3107  mode = 6;
3108  else
3110  formatString("Threshold: mode not supported (%s)", type.c_str() ));
3111 
3112  T* ptr=NULL;
3113  size_t n;
3114  T ma=-a;
3116  {
3117  if (mask == NULL || DIRECT_MULTIDIM_ELEM(*mask,n) > 0 )
3118  {
3119  switch (mode)
3120  {
3121  case 1:
3122  if (ABS(*ptr) > a)
3123  *ptr = SGN(*ptr) * b;
3124  break;
3125  case 2:
3126  if (ABS(*ptr) < a)
3127  *ptr = SGN(*ptr) * b;
3128  break;
3129  case 3:
3130  if (*ptr > a)
3131  *ptr = b;
3132  break;
3133  case 4:
3134  if (*ptr < a)
3135  *ptr = b;
3136  break;
3137  case 5:
3138  if (*ptr < a)
3139  *ptr = a;
3140  else if (*ptr > b)
3141  *ptr = b;
3142  break;
3143  case 6:
3144  if (*ptr<ma)
3145  *ptr+=a;
3146  else if (*ptr>a)
3147  *ptr-=a;
3148  else
3149  *ptr=0;
3150  }
3151  }
3152  }
3153  }
3154 
3160  size_t countThreshold(const String& type,
3161  T a,
3162  T b,
3163  MultidimArray<int> * mask = NULL )
3164  {
3165  int mode;
3166 
3167  if (type == "abs_above")
3168  mode = 1;
3169  else if (type == "abs_below")
3170  mode = 2;
3171  else if (type == "above")
3172  mode = 3;
3173  else if (type == "below")
3174  mode = 4;
3175  else if (type == "range")
3176  mode = 5;
3177  else
3179  formatString("CountThreshold: mode not supported (%s)", type.c_str()));
3180 
3181  size_t ret = 0;
3182 
3183  T* ptr=NULL;
3184  size_t n;
3186  if (mask == NULL || DIRECT_MULTIDIM_ELEM(*mask,n) > 0 )
3187  {
3188  switch (mode)
3189  {
3190  case 1:
3191  if (ABS(*ptr) > a)
3192  ret++;
3193  break;
3194  case 2:
3195  if (ABS(*ptr) < a)
3196  ret++;
3197  break;
3198  case 3:
3199  if (*ptr > a)
3200  ret++;
3201  break;
3202  case 4:
3203  if (*ptr < a)
3204  ret++;
3205  break;
3206  case 5:
3207  if (*ptr >= a && *ptr <= b)
3208  ret++;
3209  break;
3210  }
3211  }
3212  return ret;
3213  }
3214 
3221  void substitute(T oldv,
3222  T newv,
3223  double accuracy = XMIPP_EQUAL_ACCURACY,
3224  MultidimArray<int> * mask = NULL )
3225  {
3226  T* ptr=NULL;
3227  size_t n;
3229  if (mask == NULL || DIRECT_MULTIDIM_ELEM(*mask,n) > 0 )
3230  if (ABS(*ptr - oldv) <= accuracy)
3231  *ptr = newv;
3232  }
3233 
3240  void randomSubstitute(T oldv,
3241  T avgv,
3242  T sigv,
3243  double accuracy = XMIPP_EQUAL_ACCURACY,
3244  MultidimArray<int> * mask = NULL );
3245 
3252  void binarize(double val = 0,
3253  double accuracy = XMIPP_EQUAL_ACCURACY,
3254  MultidimArray<int> * mask = NULL )
3255  {
3256  T* ptr=NULL;
3257  size_t n;
3259  if (mask == NULL || DIRECT_MULTIDIM_ELEM(*mask,n) > 0 )
3260  {
3261  if (*ptr <= val + accuracy)
3262  *ptr = 0;
3263  else
3264  *ptr = 1;
3265  }
3266  }
3267 
3273  void binarizeRange(double valMin = 0, double valMax = 255,
3274  MultidimArray<int> * mask = NULL )
3275  {
3276  T* ptr=NULL;
3277  size_t n;
3279  if (mask == NULL || DIRECT_MULTIDIM_ELEM(*mask,n) > 0 )
3280  {
3281  if ( (*ptr < valMax) && (*ptr > valMin) )
3282  *ptr = 1;
3283  else
3284  *ptr = 0;
3285  }
3286  }
3287 
3292  void selfROUND()
3293  {
3294  T* ptr=NULL;
3295  size_t n;
3297  *ptr = ROUND(*ptr);
3298  }
3299 
3305  void selfCEIL()
3306  {
3307  T* ptr=NULL;
3308  size_t n;
3310  *ptr = CEIL(*ptr);
3311  }
3312 
3318  void selfFLOOR()
3319  {
3320  T* ptr=NULL;
3321  size_t n;
3323  *ptr = FLOOR(*ptr);
3324  }
3325 
3330  void selfABS()
3331  {
3332  T* ptr=NULL;
3333  size_t n;
3335  *ptr = ABS(*ptr);
3336  }
3337 
3344  void selfNormalizeInterval(double minPerc=0.25, double maxPerc=0.75, int Npix=1000);
3345 
3352  friend void MultidimArrayMax(const MultidimArray<T>& v1, const MultidimArray<T>& v2,
3353  MultidimArray<T>& result)
3354  {
3355  if (!v1.sameShape(v2))
3356  REPORT_ERROR(ERR_MULTIDIM_SIZE, "MAX: arrays of different shape");
3357 
3358  result.resizeNoCopy(v1);
3360  DIRECT_MULTIDIM_ELEM(result,n) = XMIPP_MAX(
3361  DIRECT_MULTIDIM_ELEM(v1,n),
3362  DIRECT_MULTIDIM_ELEM(v2,n));
3363  }
3364 
3371  friend void MultidimArrayMIN(const MultidimArray<T>& v1, const MultidimArray<T>& v2,
3372  MultidimArray<T>& result)
3373  {
3374  if (!v1.sameShape(v2))
3375  REPORT_ERROR(ERR_MULTIDIM_SIZE, "MIN: arrays of different shape");
3376 
3377  result.resizeNoCopy(v1);
3379  DIRECT_MULTIDIM_ELEM(result,n) = XMIPP_MIN(
3380  DIRECT_MULTIDIM_ELEM(v1,n),
3381  DIRECT_MULTIDIM_ELEM(v2,n));
3382  }
3383 
3389  void selfSQRT()
3390  {
3391  T* ptr=NULL;
3392  size_t n;
3394  *ptr = static_cast< T >(sqrt(static_cast< double >(*ptr)));
3395  }
3396 
3405  double sum() const
3406  {
3407  double sum = 0;
3408  T* ptr=NULL;
3409  size_t n;
3411  sum += *ptr;
3412  return sum;
3413  }
3414 
3424  double sum2() const
3425  {
3426  double sum = 0;
3427 
3428  // Unroll the loop
3429  const size_t unroll=4;
3430  size_t nmax=(NZYXSIZE(*this)/unroll)*unroll;
3431  T* ptr = MULTIDIM_ARRAY(*this);
3432  for (size_t n=0; n<nmax; n+=unroll, ptr+=unroll)
3433  {
3434  sum+= (*ptr)*(*ptr);
3435  T* ptr1=ptr+1;
3436  sum+= (*ptr1)*(*ptr1);
3437  T* ptr2=ptr+2;
3438  sum+= (*ptr2)*(*ptr2);
3439  T* ptr3=ptr+3;
3440  sum+= (*ptr3)*(*ptr3);
3441  }
3442  // Do the remaining elements
3443  for (size_t n=nmax; n<NZYXSIZE(*this); ++n, ++ptr)
3444  sum+=(*ptr)*(*ptr);
3445  return sum;
3446  }
3447 
3452  void selfLog10()
3453  {
3454  T* ptr=NULL;
3455  size_t n;
3457  *ptr = static_cast< T >(log10(static_cast< double >(*ptr)));
3458  }
3459 
3464  void selfLog()
3465  {
3466  T* ptr=NULL;
3467  size_t n;
3469  *ptr = static_cast< T >(log(static_cast< double >(*ptr)));
3470  }
3471 
3502  {
3503  size_t xsize=XSIZE(*this);
3504  size_t halfSizeX = (xsize-2)/2;
3505  size_t xsize_1=xsize-1;
3506  for (size_t k = 0; k < ZSIZE(*this); k++)
3507  for (size_t i = 0; i < YSIZE(*this); i++)
3508  for (size_t j = 0; j <=halfSizeX; j++)
3509  {
3510  T aux;
3511  T& d1=DIRECT_ZYX_ELEM(*this, k, i, j);
3512  T& d2=DIRECT_ZYX_ELEM(*this, k, i, xsize_1 - j);
3513  SWAP(d1,d2,aux);
3514  }
3515  STARTINGX(*this) = -FINISHINGX(*this);
3516  }
3517 
3532  {
3533  size_t ysize=YSIZE(*this);
3534  size_t halfSizeY = (ysize-2)/2;
3535  size_t ysize_1=ysize-1;
3536  for (size_t k = 0; k < ZSIZE(*this); k++)
3537  for (size_t i = 0; i <= halfSizeY; i++)
3538  for (size_t j = 0; j < XSIZE(*this); j++)
3539  {
3540  T aux;
3541  T& d1=DIRECT_ZYX_ELEM(*this, k, i, j);
3542  T& d2=DIRECT_ZYX_ELEM(*this, k, ysize_1 - i, j);
3543  SWAP(d1,d2,aux);
3544  }
3545  STARTINGY(*this) = -FINISHINGY(*this);
3546  }
3547 
3554  {
3555  size_t zsize=ZSIZE(*this);
3556  size_t halfSizeZ = (zsize-2)/2;
3557  size_t zsize_1=zsize-1;
3558  for (size_t k = 0; k <= halfSizeZ; k++)
3559  for (size_t i = 0; i <YSIZE(*this); i++)
3560  for (size_t j = 0; j < XSIZE(*this); j++)
3561  {
3562  T aux;
3563  T& d1=DIRECT_ZYX_ELEM(*this, k, i, j);
3564  T& d2=DIRECT_ZYX_ELEM(*this, zsize_1- k, i, j);
3565  SWAP(d1,d2,aux);
3566  }
3567  STARTINGZ(*this) = -FINISHINGZ(*this);
3568  }
3569 
3576  void profile(int x0, int y0, int xF, int yF, int N,
3578  {
3579  checkDimension(2);
3580  profile.initZeros(N);
3581  double tx_step = (double)(xF - x0) / (N - 1);
3582  double ty_step = (double)(yF - y0) / (N - 1);
3583  double tx = x0, ty = y0;
3584 
3585  for (int i = 0; i < N; i++)
3586  {
3587  profile(i) = interpolatedElement2D(tx, ty);
3588  tx += tx_step;
3589  ty += ty_step;
3590  }
3591  }
3592 
3598  void showWithGnuPlot(const String& xlabel, const String& title);
3599 
3606  void edit();
3607 
3610  void write(const FileName& fn) const;
3612 
3615 
3629  {
3630  if (&op1 != this)
3631  {
3632  if (data == NULL || !sameShape(op1))
3633  resizeNoCopy(op1);
3634  memcpy(data,op1.data,MULTIDIM_SIZE(op1)*sizeof(T));
3635  }
3636  return *this;
3637  }
3638 
3650  {
3651  if (&other != this)
3652  {
3653  coreDeallocate();
3654  coreInit();
3655  swap(other);
3656  }
3657  return *this;
3658  }
3659 
3672  MultidimArray<T>& operator=(const Matrix2D<T>& op1);
3673 
3685  {
3686  MultidimArray<T> tmp(*this);
3687  T* ptr;
3688  size_t n;
3690  *ptr = -(*ptr);
3691  return tmp;
3692  }
3693 
3706  {
3707  T* ptr;
3708  size_t n;
3710  in >> *ptr;
3711  return in;
3712  }
3713 
3714  void copy(Matrix2D<T>& op1) const;
3715 
3721  bool equal(const MultidimArray<T>& op,
3722  double accuracy = XMIPP_EQUAL_ACCURACY) const
3723  {
3724  if (!sameShape(op) || data==NULL || op.data == NULL)
3725  return false;
3727  {
3728  if (fabs(DIRECT_MULTIDIM_ELEM(*this,n) -
3729  DIRECT_MULTIDIM_ELEM(op,n)) > accuracy)
3730  return false;
3731  }
3732  return true;
3733  }
3735 };
3736 
3737 
3738 
3741 
3748 template<typename T1, typename T2>
3750 {
3751  if (NZYXSIZE(v1) == 0)
3752  {
3753  v2.clear();
3754  return;
3755  }
3756 
3757  v2.resizeNoCopy(v1);
3758  T1* ptr1 = MULTIDIM_ARRAY(v1);
3759 
3760  // Unroll the loop
3761  const size_t unroll=4;
3762  size_t nmax=(NZYXSIZE(v1)/unroll)*unroll;
3763  for (size_t n=0; n<nmax; n+=unroll, ptr1+=unroll)
3764  {
3765  DIRECT_MULTIDIM_ELEM(v2,n) = static_cast< T2 >(*ptr1);
3766  DIRECT_MULTIDIM_ELEM(v2,n+1) = static_cast< T2 >(*(ptr1+1));
3767  DIRECT_MULTIDIM_ELEM(v2,n+2) = static_cast< T2 >(*(ptr1+2));
3768  DIRECT_MULTIDIM_ELEM(v2,n+3) = static_cast< T2 >(*(ptr1+3));
3769  }
3770  // Do the remaining elements
3771  for (size_t n=nmax; n<NZYXSIZE(v1); ++n, ++ptr1)
3772  DIRECT_MULTIDIM_ELEM(v2,n) = static_cast< T2 >(*ptr1);
3773 }
3774 
3775 template<typename T1>
3776 void typeCastComplex(const MultidimArray<T1>& v1, MultidimArray<std::complex<double> >& v2)
3777 {
3778  if (NZYXSIZE(v1) == 0)
3779  {
3780  v2.clear();
3781  return;
3782  }
3783 
3784  v2.resizeNoCopy(v1);
3785  T1* ptr1 = MULTIDIM_ARRAY(v1);
3786  double * ptr2 = (double*) MULTIDIM_ARRAY(v2);
3787 
3788  // Unroll the loop
3789  const size_t unroll=4;
3790  size_t nmax=(NZYXSIZE(v1)/unroll)*unroll;
3791  for (size_t n=0; n<nmax; n+=unroll, ptr1+=unroll)
3792  {
3793  *(ptr2++) = static_cast<double>(*ptr1);
3794  *(ptr2++) = 0;
3795  *(ptr2++) = static_cast< double >(*(ptr1+1));
3796  *(ptr2++) = 0;
3797  *(ptr2++) = static_cast< double >(*(ptr1+2));
3798  *(ptr2++) = 0;
3799  *(ptr2++) = static_cast< double >(*(ptr1+3));
3800  *(ptr2++) = 0;
3801  }
3802  // Do the remaining elements
3803  for (size_t n=nmax; n<NZYXSIZE(v1); ++n, ++ptr1)
3804  {
3805  *(ptr2++) = static_cast< double >(*ptr1);
3806  *(ptr2++) = 0;
3807  }
3808 }
3809 
3813 template<typename T1>
3815 {
3816  v2=v1;
3817 }
3818 
3821 template<typename T>
3823 {
3824  v2.resizeNoCopy(XSIZE(v1));
3825  memcpy(&VEC_ELEM(v2,0),&DIRECT_A1D_ELEM(v1,0),MULTIDIM_SIZE(v1)*sizeof(T));
3826  v2.row=false;
3827 }
3828 
3829 
3831 template<typename T>
3832 bool operator==(const MultidimArray<T>& op1, const MultidimArray<T>& op2)
3833 {
3834  return op1.equal(op2);
3835 }
3836 
3838 template<typename T>
3839 bool operator!=(const MultidimArray<T>& op1, const MultidimArray<T>& op2)
3840 {
3841  return !(op1==op2);
3842 }
3843 
3865 template<typename T>
3867 {
3868  int z0 = XMIPP_MAX(STARTINGZ(V1), STARTINGZ(V2));
3869  int zF = XMIPP_MIN(FINISHINGZ(V1), FINISHINGZ(V2));
3870  int y0 = XMIPP_MAX(STARTINGY(V1), STARTINGY(V2));
3871  int yF = XMIPP_MIN(FINISHINGY(V1), FINISHINGY(V2));
3872  int x0 = XMIPP_MAX(STARTINGX(V1), STARTINGX(V2));
3873  int xF = XMIPP_MIN(FINISHINGX(V1), FINISHINGX(V2));
3874 
3875  V1.window(z0, y0, x0, zF, yF, xF);
3876  V2.window(z0, y0, x0, zF, yF, xF);
3877 }
3878 
3879 
3883 
3887  double &p0, double &p1, double &p2);
3888 
3889 /*
3890  mod Modulus after division.
3891  mod(x,y) is x - n.*y where n = floor(x./y) if y ~= 0. If y is not an
3892  integer and the quotient x./y is within roundoff error of an integer,
3893  then n is that integer. The inputs x and y must be real arrays of the
3894  same size, or real scalars.
3895 
3896  By convention:
3897  MOD(x, m, 0) is m = x.
3898  MOD(x,m,x) is m = 0.
3899  MOD(x,m,y), for x~=y and y~=0, m has the same sign as y.
3900  */
3901 template <typename T>
3902 void mod(const MultidimArray<T> &x, MultidimArray<T> &m, double y)
3903 {
3904  m.resizeNoCopy(x);
3905  double *ptr=NULL;
3906  double *ptrm=MULTIDIM_ARRAY(m);
3907  size_t n;
3909  *(ptrm++) = (*ptr) - std::floor((*ptr)/(y))*(y);
3910 }
3911 
3915 template <typename T>
3916 std::ostream& operator<< (std::ostream& ostrm, const MultidimArray<T>& v)
3917 {
3918  if (v.xdim == 0)
3919  ostrm << "NULL Array\n";
3920  else
3921  ostrm << std::endl;
3922 
3923  double max_val = ABS(DIRECT_A3D_ELEM(v , 0, 0, 0));
3924 
3925  T* ptr;
3926  size_t n;
3928  max_val = XMIPP_MAX(max_val, ABS(*ptr));
3929 
3930  int prec = bestPrecision(max_val, 10);
3931 
3932  if (YSIZE(v)==1 && ZSIZE(v)==1)
3933  {
3934  for (int j = STARTINGX(v); j <= FINISHINGX(v); j++)
3935  ostrm << floatToString((double) A3D_ELEM(v, 0, 0, j), 10, prec)
3936  << std::endl;
3937  }
3938  else
3939  {
3940  for (size_t l = 0; l < NSIZE(v); l++)
3941  {
3942  if (NSIZE(v)>1)
3943  ostrm << "Image No. " << l << std::endl;
3944  for (int k = STARTINGZ(v); k <= FINISHINGZ(v); k++)
3945  {
3946  if (ZSIZE(v)>1)
3947  ostrm << "Slice No. " << k << std::endl;
3948  for (int i = STARTINGY(v); i <= FINISHINGY(v); i++)
3949  {
3950  for (int j = STARTINGX(v); j <= FINISHINGX(v); j++)
3951  {
3952  ostrm << floatToString((double) A3D_ELEM(v, k, i, j), 10, prec) << ' ';
3953  }
3954  ostrm << std::endl;
3955  }
3956  }
3957  }
3958  }
3959 
3960  return ostrm;
3961 }
3962 
3966 template<typename T>
3967 void window2D(const MultidimArray<T> &Ibig, MultidimArray<T> &Ismall,
3968  size_t y0, size_t x0, size_t yF, size_t xF);
3969 
3973 template <typename T>
3975  const MultidimArray< T >& y,
3976  const MultidimArray< int >* mask = NULL,
3977  MultidimArray< double >* Contributions = NULL)
3978 {
3980 
3981  double retval = 0, aux;
3982  double mean_x, mean_y;
3983  double stddev_x, stddev_y;
3984 
3985  long N = 0;
3986 
3987  if (mask == NULL)
3988  {
3989  x.computeAvgStdev(mean_x, stddev_x);
3990  y.computeAvgStdev(mean_y, stddev_y);
3991  }
3992  else
3993  {
3994  x.computeAvgStdev_within_binary_mask(*mask, mean_x,stddev_x);
3995  y.computeAvgStdev_within_binary_mask(*mask, mean_y,stddev_y);
3996  }
3997  if (ABS(stddev_x)<XMIPP_EQUAL_ACCURACY ||
3998  ABS(stddev_y)<XMIPP_EQUAL_ACCURACY)
3999  return 0;
4000 
4001  // If contributions are desired. Please, be careful interpreting individual
4002  // contributions to the covariance! One pixel value afect others.
4003  if (Contributions != NULL)
4004  {
4006  {
4007  if (mask != NULL)
4008  if (!A3D_ELEM(*mask,k, i, j))
4009  continue;
4010 
4011  aux = (A3D_ELEM(x, k, i, j) - mean_x) * (A3D_ELEM(y, k, i, j) -
4012  mean_y);
4013  A3D_ELEM(*Contributions, k, i, j) = aux;
4014  retval += aux;
4015  ++N;
4016  }
4017 
4018  FOR_ALL_ELEMENTS_IN_ARRAY3D(*Contributions)
4019  A3D_ELEM(*Contributions, k, i, j) /= ((stddev_x * stddev_y) * N);
4020  }
4021  else
4022  {
4023  if (mask==NULL && x.sameShape(y))
4024  {
4026  retval += DIRECT_MULTIDIM_ELEM(x, n)*DIRECT_MULTIDIM_ELEM(y, n);
4027  N=MULTIDIM_SIZE(x);
4028  retval-=N*mean_x*mean_y;
4029  }
4030  else
4031  {
4033  {
4034  if (mask != NULL)
4035  if (!A3D_ELEM(*mask,k, i, j))
4036  continue;
4037 
4038  retval += (A3D_ELEM(x, k, i, j) - mean_x) *
4039  (A3D_ELEM(y, k, i, j) - mean_y);
4040  ++N;
4041  }
4042  }
4043  }
4044 
4045  if (N != 0)
4046  return retval / ((stddev_x * stddev_y) * N);
4047  else
4048  return 0;
4049 }
4051 
4052 // Specializations cases for complex numbers
4053 template<>
4054 std::ostream& operator<<(std::ostream& ostrm, const MultidimArray< std::complex<double> >& v);
4055 template<>
4056 void MultidimArray< std::complex< double > >::computeDoubleMinMax(double& minval, double& maxval) const;
4057 template<>
4058 void MultidimArray< std::complex< double > >::computeDoubleMinMaxRange(double& minval, double& maxval, size_t pos, size_t size) const;
4059 template<>
4060 void MultidimArray< std::complex< double > >::rangeAdjust(std::complex< double > minF, std::complex< double > maxF);
4061 template<>
4063 template<>
4064 void MultidimArray< std::complex< double > >::maxIndex(size_t &lmax, int& kmax, int& imax, int& jmax) const;
4065 template<>
4066 bool operator==(const MultidimArray< std::complex< double > >& op1,
4067  const MultidimArray< std::complex< double > >& op2);
4068 template<>
4069 double MultidimArray<double>::interpolatedElement2D(double x, double y, double outside_value) const;
4070 template<>
4072 template<>
4074 
4076 #endif
#define ASSIGNVAL1D(d, j)
void typeCastComplex(const MultidimArray< T1 > &v1, MultidimArray< std::complex< double > > &v2)
Index out of bounds.
Definition: xmipp_error.h:132
void reslice(AxisView face, bool flip=false, size_t n=0)
#define NSIZE(v)
void substitute(T oldv, T newv, double accuracy=XMIPP_EQUAL_ACCURACY, MultidimArray< int > *mask=NULL)
void patch(MultidimArray< T > patchArray, int x, int y)
void planeFit(const MultidimArray< double > &z, const MultidimArray< double > &x, const MultidimArray< double > &y, double &p0, double &p1, double &p2)
void operator*=(const MultidimArray< T > &op1)
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
void binarizeRange(double valMin=0, double valMax=255, MultidimArray< int > *mask=NULL)
T interpolatedElementBSpline1D(double x, int SplineDegree=3) const
MultidimArray< T > operator-() const
void killAdaptationForNumericalRecipes22D(T **m) const
int * nmax
MultidimArray(int Xdim)
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
void minIndex(int &jmin) const
void coreDeallocate() noexcept
friend MultidimArray< T > operator/(T op1, const MultidimArray< T > &op2)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
MultidimArray(int Ydim, int Xdim)
void window(MultidimArray< T1 > &result, int y0, int x0, int yF, int xF, T1 init_value=0) const
size_t xdim
void cumlativeDensityFunction(MultidimArray< double > &cdf)
void free_Tvolume(T ***&m, int nsl, int nsh, int nrl, int nrh, int ncl, int nch)
Definition: xmipp_memory.h:106
friend void MultidimArrayMIN(const MultidimArray< T > &v1, const MultidimArray< T > &v2, MultidimArray< T > &result)
void threshold(const String &type, T a, T b=0, MultidimArray< int > *mask=NULL)
void coreAllocate(size_t _ndim, int _zdim, int _ydim, int _xdim)
MultidimArray< T > operator-(T op1) const
__host__ __device__ float2 floor(const float2 v)
#define DIRECT_NZYX_ELEM(v, l, k, i, j)
#define OUTSIDE3D(k, i, j)
MultidimArray is empty.
Definition: xmipp_error.h:175
void getSlice(int k, MultidimArray< T1 > &M, char axis='Z', bool reverse=false, size_t n=0) const
#define FINISHINGX(v)
void minIndex(int &lmin, int &kmin, int &imin, int &jmin) const
void coreScalarByArray(const T &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
void printShape(std::ostream &out=std::cout) const
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void computeStats(double &avg, double &stddev, T &min_val, T &max_val, Matrix1D< int > &corner1, Matrix1D< int > &corner2, size_t n=0)
void operator+=(const MultidimArray< T > &op1)
size_t size() const
Definition: matrix1d.h:508
T interpolatedElementBSpline2D_Degree3(double x, double y) const
void sort(MultidimArray< T > &result) const
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
void initRandom(double op1, double op2, RandomMode mode=RND_UNIFORM)
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
doublereal * c
#define MULTIDIM_SIZE(v)
friend void scalarByArray(T op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
Global mmap error.
Definition: xmipp_error.h:170
void resizeNoCopy(const MultidimArray< T1 > &v)
#define dAij(M, i, j)
FILE * mmapFile(T *&_data, size_t nzyxDim) const
void minIndex(int &imin, int &jmin) const
void sqrt(Image< double > &op)
void aliasImageInStack(const MultidimArray< T > &m, size_t select_image)
double dotProduct(const MultidimArray< T > &op1)
ArrayDim getDimensions() const
friend void arrayByArray(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
void computeStats(double &avg, double &stddev, T &minval, T &maxval) const
friend MultidimArray< T > operator*(T op1, const MultidimArray< T > &op2)
static double * y
MultidimArray(size_t Ndim, int Zdim, int Ydim, int Xdim)
friend MultidimArray< T > operator-(T op1, const MultidimArray< T > &op2)
There is not enough memory for allocation.
Definition: xmipp_error.h:166
T interpolatedElementBSpline3D(double x, double y, double z, int SplineDegree=3) const
#define DIRECT_A2D_ELEM(v, i, j)
double correlationIndex(const MultidimArray< T > &x, const MultidimArray< T > &y, const MultidimArray< int > *mask=NULL, MultidimArray< double > *Contributions=NULL)
void maxIndex(size_t &lmax, int &kmax, int &imax, int &jmax) const
#define A1D_ELEM(v, i)
void computeAvgStdev(U &avg, U &stddev) const
void maxIndex(int &jmax) const
#define MULTIDIM_ARRAY(v)
void rangeAdjust(T minF, T maxF)
void operator/=(const T &op1)
void initConstant(T val)
int bestPrecision(float F, int _width)
#define zF
RandomMode
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY_ptr(v, n, ptr)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(V)
void swap(MultidimArray< T > &other) noexcept
#define z0
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
void getCol(size_t j, MultidimArray< T > &v) const
#define FINISHINGZ(v)
Memory has not been deallocated.
Definition: xmipp_error.h:167
String floatToString(float F, int _width, int _prec)
void initZeros(int Xdim)
MultidimArray< T > operator/(const MultidimArray< T > &op1) const
void free_Tmatrix(T **&m, int nrl, int nrh, int ncl, int nch)
Definition: xmipp_memory.h:61
friend void coreScalarByArray(const T &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
void resize(const MultidimArray< T1 > &v, bool copy=true)
void coreInit() noexcept
#define STARTINGX(v)
friend void coreArrayByArray(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
void computeAvgStdev_within_binary_mask(const MultidimArray< int > &mask, double &avg, double &stddev) const
doublereal * x
#define i
T *** adaptForNumericalRecipes3D(size_t n=0) const
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void median(MultidimArray< T > &x, MultidimArray< T > &y, T &m)
Definition: filters.h:1055
void initLinear(T minF, T maxF, int n=1, const String &mode="incr")
void aliasSlice(const MultidimArray< T > &m, size_t select_slice)
void typeCast(const MultidimArray< T1 > &v1, MultidimArray< T2 > &v2)
void centerOfMass(Matrix1D< double > &center, void *mask=NULL, size_t n=0)
T interpolatedElement2D(double x, double y, T outside_value=(T) 0) const
#define STARTINGY(v)
void initZeros(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim)
MultidimArray< T > operator/(T op1) const
#define A3D_ELEM(V, k, i, j)
void selfWindow(int x0, int xF, T init_value=0)
void cutToCommonSize(MultidimArray< T > &V1, MultidimArray< T > &V2)
Definition: mask.h:36
T * adaptForNumericalRecipes22D() const
glob_log first
MultidimArray(const std::vector< T > &vector)
void toPhysical(int i_log, int j_log, int &i_phys, int &j_phys) const
T & operator()(int i) const
#define DIRECT_A1D_ELEM(v, i)
AxisView
Definition: axis_view.h:32
#define checkDimension(dim)
void toPhysical(int k_log, int i_log, int j_log, int &k_phys, int &i_phys, int &j_phys) const
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
void rangeAdjust(T minF, T maxF, MultidimArray< int > &mask)
doublereal * b
void addNoise(double op1, double op2, const String &mode="uniform", double df=3.) const
double v1
#define FLOOR(x)
Definition: xmipp_macros.h:240
void log(Image< double > &op)
T computeMin() const
void window(MultidimArray< T1 > &result, int x0, int xF, T1 init_value=0) const
void window(MultidimArray< T1 > &result, int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T1 init_value=0) const
void computeMedian_within_binary_mask(const MultidimArray< int > &mask, double &median) const
#define y0
char axis
void minIndex(int &kmin, int &imin, int &jmin) const
#define x0
#define XX(v)
Definition: matrix1d.h:85
MultidimArray< T > operator-(const MultidimArray< T > &op1) const
bool equal(const MultidimArray< T > &op, double accuracy=XMIPP_EQUAL_ACCURACY) const
size_t zdim
void initZeros(int Ydim, int Xdim)
void getSliceAsMatrix(size_t k, Matrix2D< T > &m) const
void binarize(double val=0, double accuracy=XMIPP_EQUAL_ACCURACY, MultidimArray< int > *mask=NULL)
void operator-=(const T &op1)
viol index
viol type
void rangeAdjust(const MultidimArray< T > &example, const MultidimArray< int > *mask=NULL)
#define CEIL(x)
Definition: xmipp_macros.h:225
void getAliasAsRowVector(Matrix1D< T > &m) const
void killAdaptationForNumericalRecipes2D(T **m) const
int in
bool operator!=(const MultidimArray< T > &op1, const MultidimArray< T > &op2)
void profile(int x0, int y0, int xF, int yF, int N, MultidimArray< double > &profile) const
MultidimArray< T > operator*(T op1) const
Incorrect argument received.
Definition: xmipp_error.h:113
void setSlice(int k, const MultidimArray< T1 > &v, size_t n=0)
void setMmap(bool mmap)
MultidimArray(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, T *data)
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
void setCol(size_t j, const MultidimArray< T > &v)
bool sameShape(const MultidimArrayBase &op) const
T & operator()(const Matrix1D< int > &v) const
MultidimArray(const MultidimArray< T > &V)
MultidimArray< T > & operator=(MultidimArray< T > &&other) noexcept
#define XSIZE(v)
friend void coreArrayByScalar(const MultidimArray< T > &op1, const T &op2, MultidimArray< T > &result, char operation)
void operator*=(const T &op1)
void write(const FileName &fn) const
T * adaptForNumericalRecipes1D() const
virtual ~MultidimArray()
void computeDoubleMinMax(double &minval, double &maxval) const
MultidimArray< T > & operator=(const MultidimArray< T > &op1)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
void killAdaptationForNumericalRecipes3D(T ***m) const
void sincos(const MultidimArray< double > &x, MultidimArray< double > &s, MultidimArray< double > &c)
void initZeros(int Zdim, int Ydim, int Xdim)
MultidimArray< T > operator*(const MultidimArray< T > &op1) const
void equal(T op1, MultidimArray< char > &result) const
#define ABS(x)
Definition: xmipp_macros.h:142
void checkDimensionWithDebug(int dim, const char *file, int line) const
void showWithGnuPlot(const String &xlabel, const String &title)
#define ZSIZE(v)
bool row
<0=column vector (default), 1=row vector
Definition: matrix1d.h:267
double z
#define DIRECT_MULTIDIM_ELEM(v, n)
void operator/=(const MultidimArray< T > &op1)
T interpolatedElement3D(double x, double y, double z, T outside_value=(T) 0) const
#define ROUND(x)
Definition: xmipp_macros.h:210
void toPhysical(int i_log, int &i_phys) const
#define NZYXSIZE(v)
void randomSubstitute(T oldv, T avgv, T sigv, double accuracy=XMIPP_EQUAL_ACCURACY, MultidimArray< int > *mask=NULL)
#define ASSIGNVAL2D(d, i, j)
void log10(Image< double > &op)
void window2D(const MultidimArray< T > &Ibig, MultidimArray< T > &Ismall, size_t y0, size_t x0, size_t yF, size_t xF)
MultidimArray(int Zdim, int Ydim, int Xdim)
void mode
T & operator()(int k, int i, int j) const
void coreAllocateReuse()
void alias(const MultidimArray< T > &m)
double computeMedian() const
basic_istream< char, std::char_traits< char > > istream
Definition: utilities.cpp:815
#define xF
void initZeros()
Definition: matrix1d.h:592
void toLogical(int i_phys, int &i_log) const
T & operator[](size_t i) const
void mod(const MultidimArray< T > &x, MultidimArray< T > &m, double y)
void printStats(std::ostream &out=std::cout) const
#define NZYX_ELEM(v, l, k, i, j)
#define DIRECT_A3D_ELEM(v, k, i, j)
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
bool operator==(const MultidimArray< T > &op1, const MultidimArray< T > &op2)
void setDimensions(int Xdim, int Ydim, int Zdim, size_t Ndim)
T interpolatedElementBSpline2D(double x, double y, int SplineDegree=3) const
double * d0
#define j
size_t colNumber() const
void getRow(size_t i, MultidimArray< T > &v) const
virtual void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)=0
void operator-=(const MultidimArray< T > &op1)
double steps
#define YY(v)
Definition: matrix1d.h:93
int m
void copyShape(const MultidimArrayBase &m)
void loadFromNumericalRecipes2D(T **m, int Ydim, int Xdim)
T ** adaptForNumericalRecipes2D(size_t n=0) const
size_t countThreshold(const String &type, T a, T b, MultidimArray< int > *mask=NULL)
void operator+=(const T &op1)
friend void MultidimArrayMax(const MultidimArray< T > &v1, const MultidimArray< T > &v2, MultidimArray< T > &result)
double sum2() const
#define FINISHINGY(v)
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
void selfWindow(int z0, int y0, int x0, int zF, int yF, int xF, T init_value=0)
void getReal(MultidimArray< double > &realImg) const
void toLogical(int k_phys, int i_phys, int j_phys, int &k_log, int &i_log, int &j_log) const
Definition: ctf.h:38
void window(MultidimArray< T1 > &result, int z0, int y0, int x0, int zF, int yF, int xF, T1 init_value=0) const
friend MultidimArray< T > operator+(T op1, const MultidimArray< T > &op2)
std::string String
Definition: xmipp_strings.h:34
void reslice(MultidimArray< T1 > &out, AxisView face, bool flip=false, size_t n=0) const
#define DIRECT_ZYX_ELEM(v, k, i, j)
void ask_Tvolume(T ***&m, int nsl, int nsh, int nrl, int nrh, int ncl, int nch)
Definition: xmipp_memory.h:78
String formatString(const char *format,...)
void selfWindow(int y0, int x0, int yF, int xF, T init_value=0)
void killAdaptationForNumericalRecipes1D(T *m) const
T & operator()(int i, int j) const
void selfNormalizeInterval(double minPerc=0.25, double maxPerc=0.75, int Npix=1000)
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
MultidimArray< T > operator+(T op1) const
void copy(Matrix2D< T > &op1) const
#define SWAP(a, b, tmp)
Definition: xmipp_macros.h:428
void aliasRow(const MultidimArray< T > &m, size_t select_row)
friend void arrayByScalar(const MultidimArray< T > &op1, T op2, MultidimArray< T > &result, char operation)
T interpolatedElement2DOutsideZero(double x, double y) const
size_t ydim
void ask_Tmatrix(T **&m, int nrl, int nrh, int ncl, int nch)
Definition: xmipp_memory.h:40
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
#define SPEED_UP_tempsInt
Definition: xmipp_macros.h:408
T * vdata
The array itself.
Definition: matrix1d.h:258
void computeDoubleMinMaxRange(double &minval, double &maxval, size_t offset, size_t size) const
#define FOR_ALL_ELEMENTS_IN_ARRAY2D_BETWEEN(corner1, corner2)
#define ASSIGNVAL2DNODIV(d, i, j)
double computeStddev() const
void initZeros(const MultidimArray< T1 > &op)
double computeAvg() const
void getImag(MultidimArray< double > &imagImg) const
Incorrect type received.
Definition: xmipp_error.h:190
MultidimArray< T > operator+(const MultidimArray< T > &op1) const
#define FOR_ALL_ELEMENTS_IN_COMMON_IN_ARRAY3D(V1, V2)
#define LIN_INTERP(a, l, h)
Definition: xmipp_macros.h:381
void selfCoreArrayByArrayMask(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation, const MultidimArray< T > *mask)
virtual void maxIndex(size_t &lmax, int &kmax, int &imax, int &jmax) const =0
T interpolatedElement1D(double x, T outside_value=(T) 0) const
Incorrect value received.
Definition: xmipp_error.h:195
#define SGN(x)
Definition: xmipp_macros.h:155
#define yF
bool destroyData
Destroy data.
Definition: matrix1d.h:261
#define STARTINGZ(v)
friend void selfCoreArrayByArrayMask(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation, const MultidimArray< T > *mask)
T & operator()(size_t n, int k, int i, int j) const
int * n
#define ZZ(v)
Definition: matrix1d.h:101
#define FOR_ALL_NZYX_ELEMENTS_IN_MULTIDIMARRAY(V)
doublereal * a
double sum() const
friend std::istream & operator>>(std::istream &in, MultidimArray< T > &v)
friend void selfArrayByArrayMask(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation, const MultidimArray< T > *mask=NULL)
void resizeNoCopy(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim)
void coreArrayByArray(const MultidimArray< T > &op1, const MultidimArray< T > &op2, MultidimArray< T > &result, char operation)
void setRow(int i, const MultidimArray< T > &v)
size_t rowNumber() const
void indexSort(MultidimArray< int > &indx) const
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
void statisticsAdjust(U avgF, U stddevF)
void * getArrayPointer() const
void getImage(size_t n, MultidimArray< T > &M, size_t n2=0) const
void coreArrayByScalar(const MultidimArray< T > &op1, const T &op2, MultidimArray< T > &result, char operation)
MultidimArray(MultidimArray< T > &&V) noexcept
T computeMax() const
void toLogical(int i_phys, int j_phys, int &i_log, int &j_log) const
size_t vdim
Number of elements.
Definition: matrix1d.h:264
__host__ __device__ float dot(float2 a, float2 b)
T & operator()(const Matrix1D< double > &v) const
MultidimArray(const Matrix1D< T > &V)