Xmipp  v3.23.11-Nereus
xmipp_image.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors H.W. Scheres (scheres@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * Part of this module has been developed by Lorenzo Zampighi and Nelson Tang
8  * Dept. Physiology of the David Geffen School of Medicine
9  * Univ. of California, Los Angeles.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24  * 02111-1307 USA
25  *
26  * All comments concerning this program package may be sent to the
27  * e-mail address 'xmipp@cnb.csic.es'
28  ***************************************************************************/
29 
30 #include "xmipp_image.h"
31 #include "xmipp_image_generic.h"
32 #include "matrix2d.h"
33 #include "transformations.h"
34 #include <sys/stat.h>
35 #include "metadata_static.h"
36 
37 template<typename T>
38 int Image<T>::readPreview(const FileName &name, size_t Xdim, size_t Ydim,
39  int select_slice, size_t select_img) // FIXME this should be moved to image_generic.*
40 {
41  // Zdim is used to choose the slices: -1 = CENTRAL_SLICE, 0 = ALL_SLICES, else This Slice
42 
43  ImageGeneric im;
44  size_t imXdim, imYdim, imZdim, Zdim;
45  int err;
46  err = im.readMapped(name, select_img);
47  im.getDimensions(imXdim, imYdim, imZdim);
48  ImageInfo imgInfo;
49  im.getInfo(imgInfo);
50 
51  //Set information from image file
52  setName(name);
53  setDatatype(imgInfo.datatype);
54  aDimFile = imgInfo.adim;
55 
56  im().setXmippOrigin();
57 
58  double scale;
59 
60  // If only Xdim is passed, it is the higher allowable size, for any dimension
61  if (Ydim == 0 && imXdim < imYdim)
62  {
63  Ydim = Xdim;
64  scale = ((double) Ydim) / ((double) imYdim);
65  Xdim = (int) (scale * imXdim);
66  }
67  else
68  {
69  scale = ((double) Xdim) / ((double) imXdim);
70  if (Ydim == 0)
71  Ydim = (int) (scale * imYdim);
72  }
73 
74  int mode = (scale <= 1) ? xmipp_transformation::NEAREST : xmipp_transformation::LINEAR; // If scale factor is higher than 1, LINEAR mode is used to avoid artifacts
75 
76  if (select_slice > ALL_SLICES) // In this case a specific slice number has been chosen (Not central slice)
77  {
78  MultidimArrayGeneric array(im(), select_slice - 1);
79  array.setXmippOrigin();
80 
81  scaleToSize(mode, IMGMATRIX(*this), array, Xdim, Ydim);
82  }
83  else // Otherwise, All slices or Central slice is selected
84  {
85  Zdim = (select_slice == ALL_SLICES) ? imZdim : 1;
86  scaleToSize(mode, IMGMATRIX(*this), im(), Xdim, Ydim, Zdim);
87  }
88 
89  IMGMATRIX(*this).resetOrigin();
90  return err;
91 }
92 
93 template<typename T>
94 void Image<T>::mmapFile()
95  {
96 #ifdef XMIPP_MMAP
97  if (this->hFile->mode == WRITE_READONLY)
98  mFd = open(dataFName.c_str(), O_RDONLY, S_IREAD);
99  else
100  mFd = open(dataFName.c_str(), O_RDWR, S_IREAD | S_IWRITE);
101 
102  if (mFd == -1)
103  {
104  if (errno == EACCES)
106  formatString(
107  "Image Class::mmapFile: permission denied when opening %s",
108  dataFName.c_str()));
109  else
111  "Image Class::mmapFile: Error opening the image file to be mapped.");
112  }
113  char * map;
114  const size_t pagesize = sysconf(_SC_PAGESIZE);
115  size_t offsetPages = (mappedOffset / pagesize) * pagesize;
116  mappedOffset -= offsetPages;
117  mappedSize -= offsetPages;
118 
119  if (this->hFile->mode == WRITE_READONLY)
120  map = (char*) mmap(0, mappedSize, PROT_READ, MAP_SHARED, mFd,
121  offsetPages);
122  else
123  map = (char*) mmap(0, mappedSize, PROT_READ | PROT_WRITE, MAP_SHARED,
124  mFd, offsetPages);
125 
126  if (map == MAP_FAILED)
128  formatString("Image Class::mmapFile: mmap of image file failed. Error: %s", strerror(errno)));
129  data.data = reinterpret_cast<T*>(map + mappedOffset);
130  data.nzyxdimAlloc = XSIZE(data) * YSIZE(data) * ZSIZE(data) * NSIZE(data);
131 #else
132 
133  REPORT_ERROR(ERR_MMAP,"Mapping not supported in Windows");
134 #endif
135 
136  }
137 
138 
139 // Special cases for complex numbers
140 template<>
141 void Image< std::complex< double > >::castPage2T(char * page,
142  std::complex<double> * ptrDest,
143  DataType datatype,
144  size_t pageSize)
145 {
146 
147  switch (datatype)
148  {
149  case DT_CShort:
150  {
151  std::complex<short> * ptr = (std::complex<short> *) page;
152  for(size_t i=0; i<pageSize;i++)
153  ptrDest[i]= std::complex<double> (real(ptr[i]),imag(ptr[i]));
154  }
155  break;
156  case DT_CInt:
157  {
158  std::complex<int> * ptr = (std::complex<int> *) page;
159  for(size_t i=0; i<pageSize;i++)
160  ptrDest[i]= std::complex<double> (real(ptr[i]),imag(ptr[i]));
161  }
162  break;
163  case DT_CFloat:
164  {
165  std::complex<float> * ptr = (std::complex<float> *) page;
166  for(size_t i=0; i<pageSize;i++)
167  ptrDest[i]= std::complex<double> (real(ptr[i]),imag(ptr[i]));
168  }
169  break;
170  case DT_CDouble:
171  memcpy(ptrDest, page, pageSize*sizeof(std::complex<double>));
172  break;
173  default:
174  std::cerr<<"Datatype= "<<datatype<<std::endl;
175  REPORT_ERROR(ERR_TYPE_INCORRECT," ERROR: cannot cast datatype to std::complex<double>");
176  break;
177  }
178 }
179 
180 template<>
181 void Image< std::complex< double > >::castPage2Datatype(std::complex<double> * srcPtr,
182  char * page,
183  DataType datatype,
184  size_t pageSize) const
185 {
186  switch (datatype)
187  {
188  case DT_CShort:
189  {
190  short * ptr = (short *) page;
191  double * srcPtrd = (double *)srcPtr;
192  for(size_t i=0; i<pageSize;i++)
193  {
194  *ptr=(short) *srcPtrd; ptr++; srcPtrd++;
195  *ptr=(short) *srcPtrd; ptr++; srcPtrd++;
196  }
197  }
198  break;
199  case DT_CInt:
200  {
201  int * ptr = (int *) page;
202  double * srcPtrd = (double *)srcPtr;
203  for(size_t i=0; i<pageSize;i++)
204  {
205  *ptr=(int) *srcPtrd; ptr++; srcPtrd++;
206  *ptr=(int) *srcPtrd; ptr++; srcPtrd++;
207  }
208  }
209  break;
210  case DT_CFloat:
211  {
212  std::complex<float> * ptr = (std::complex<float> *) page;
213  for(size_t i=0; i<pageSize;i++)
214  ptr[i] = (std::complex<float>)srcPtr[i];
215  }
216  break;
217  case DT_CDouble:
218  memcpy(page, srcPtr, pageSize*sizeof(std::complex<double>));
219  break;
220  default:
221  REPORT_ERROR(ERR_TYPE_INCORRECT,formatString("ERROR: cannot cast type number %d to complex<double>",datatype));
222  break;
223  }
224 }
225 
226 template<>
227 void Image< std::complex< double > >::castConvertPage2Datatype(std::complex< double > * srcPtr,
228  char * page, DataType datatype, size_t pageSize,double min0,double max0,CastWriteMode castMode) const
229 {
230 
231  switch (datatype)
232  {
233  case DT_CFloat:
234  {
235  std::complex<float> * ptr = (std::complex<float> *) page;
236  for(size_t i=0; i<pageSize;i++)
237  ptr[i] = (std::complex<float>)srcPtr[i];
238  }
239  break;
240  default:
241  REPORT_ERROR(ERR_TYPE_INCORRECT,formatString("ERROR: cannot cast&convert type number %d to complex<double>",datatype));
242  break;
243  }
244 }
245 
246 template<typename T>
247 void Image<T>::selfApplyGeometry(int SplineDegree, bool wrap,
248  bool only_apply_shifts)
249 {
250  //apply geo has not been defined for volumes
251  //and only make sense when reading data
252  if (data.getDim() < 3 && dataMode >= DATA)
253  {
255  getTransformationMatrix(A, only_apply_shifts);
256  if (!A.isIdentity())
257  {
258  MultidimArray<T> tmp = MULTIDIM_ARRAY(*this);
259  applyGeometry(SplineDegree, MULTIDIM_ARRAY(*this), tmp, A, xmipp_transformation::IS_NOT_INV,
260  wrap);
261  }
262  }
263 }
264 
265 template<typename T>
266 void Image<T>::getTransformationMatrix(Matrix2D<double> &A, bool only_apply_shifts,
267  const size_t n)
268 {
269  // This has only been implemented for 2D images...
270  MULTIDIM_ARRAY(*this).checkDimension(2);
271  A.resizeNoCopy(3, 3);
272  geo2TransformationMatrix(*MD[n], A, only_apply_shifts);
273 }
274 
275 template<typename T>
276 void Image<T>::getPreview(ImageBase *imgBOut, size_t Xdim, size_t Ydim,
277  int select_slice, size_t select_img)
278 {
279  // Zdim is used to choose the slices: -1 = CENTRAL_SLICE, 0 = ALL_SLICES, else This Slice
280 
281  size_t Zdim;
282  ArrayDim imAdim;
283  MULTIDIM_ARRAY(*this).getDimensions(imAdim);
284  MULTIDIM_ARRAY(*this).setXmippOrigin();
285 
286  double scale;
287 
288  // If only Xdim is passed, it is the higher allowable size, for any dimension
289  if (Ydim == 0 && imAdim.xdim < imAdim.ydim)
290  {
291  Ydim = Xdim;
292  scale = ((double) Ydim) / ((double) imAdim.ydim);
293  Xdim = (int) (scale * imAdim.xdim);
294  }
295  else
296  {
297  scale = ((double) Xdim) / ((double) imAdim.xdim);
298  if (Ydim == 0)
299  Ydim = (int) (scale * imAdim.ydim);
300  }
301 
302  Image<T> &imgOut = *((Image<T>*) imgBOut);
303 
304  int mode = (scale <= 1) ? xmipp_transformation::NEAREST : xmipp_transformation::LINEAR; // If scale factor is higher than 1, LINEAR mode is used to avoid artifacts
305 
306  if (select_slice > ALL_SLICES) // In this case a specific slice number has been chosen (Not central slice)
307  {
308  movePointerTo(select_slice, select_img);
309  scaleToSize(mode, IMGMATRIX(imgOut), IMGMATRIX(*this), Xdim, Ydim);
310  }
311  else // Otherwise, All slices or Central slice is selected
312  {
313  movePointerTo(ALL_SLICES, select_img);
314  Zdim = (select_slice == ALL_SLICES) ? imAdim.zdim : 1;
315  scaleToSize(mode, IMGMATRIX(imgOut), IMGMATRIX(*this), Xdim, Ydim,
316  Zdim);
317  }
318 
319  movePointerTo();
320  IMGMATRIX(*this).resetOrigin();
321 
322  // We set the actual dimesions of th MDA to the imageOut as if it were read from file.
323  imgOut.setADimFile(IMGMATRIX(imgOut).getDimensions());
324 }
325 
326 template<typename T>
327 void Image<T>::applyGeo(const MDRow &row, bool only_apply_shifts, bool wrap) {
328  //This implementation does not handle stacks,
329  //read in a block
330  if (data.ndim != 1)
332  "Geometric transformation cannot be applied to stacks!!!");
333 
334  if (MD.size() == 0)
335  MD.push_back(std::unique_ptr<MDRowVec>(new MDRowVec(MDL::emptyHeaderVec())));
336  MDRow &rowAux = *MD[0];
337 
339  {
340  double aux;
341  //origins
342  if (row.getValue(MDL_ORIGIN_X, aux))
343  rowAux.setValue(MDL_ORIGIN_X, aux);
344  if (row.getValue(MDL_ORIGIN_Y, aux))
345  rowAux.setValue(MDL_ORIGIN_Y, aux);
346  if (row.getValue(MDL_ORIGIN_Z, aux))
347  rowAux.setValue(MDL_ORIGIN_Z, aux);
348  //shifts
349  if (row.getValue(MDL_SHIFT_X, aux))
350  rowAux.setValue(MDL_SHIFT_X, aux);
351  if (row.getValue(MDL_SHIFT_Y, aux))
352  rowAux.setValue(MDL_SHIFT_Y, aux);
353  if (row.getValue(MDL_SHIFT_Z, aux))
354  rowAux.setValue(MDL_SHIFT_Z, aux);
355  //rotations
356  if (row.getValue(MDL_ANGLE_ROT, aux))
357  rowAux.setValue(MDL_ANGLE_ROT, aux);
358  if (row.getValue(MDL_ANGLE_TILT, aux))
359  rowAux.setValue(MDL_ANGLE_TILT, aux);
360  if (row.getValue(MDL_ANGLE_PSI, aux))
361  rowAux.setValue(MDL_ANGLE_PSI, aux);
362  //scale
363  if (row.getValue(MDL_SCALE, aux))
364  rowAux.setValue(MDL_SCALE, aux);
365  //weight
366  if (row.getValue(MDL_WEIGHT, aux))
367  rowAux.setValue(MDL_WEIGHT, aux);
368  bool auxBool;
369  if (row.getValue(MDL_FLIP, auxBool))
370  rowAux.setValue(MDL_FLIP, auxBool);
371  }
372 
373  //apply geo has not been defined for volumes
374  //and only make sense when reading data
375  if (data.getDim() < 3 && dataMode >= DATA)
376  {
379  getTransformationMatrix(A, only_apply_shifts);
380  else
381  {
382  String matrixStr;
383  row.getValue(MDL_TRANSFORM_MATRIX, matrixStr);
384  string2TransformationMatrix(matrixStr, A, 3);
385  }
386 
387  if (!A.isIdentity())
388  {
389  MultidimArray<T> tmp = MULTIDIM_ARRAY(*this);
390  applyGeometry(xmipp_transformation::BSPLINE3, MULTIDIM_ARRAY(*this), tmp, A, xmipp_transformation::IS_NOT_INV,
391  wrap);
392  }
393  }
394 }
395 
396 //template int Image<std::complex<double> >::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
397 //template int Image<bool>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
398 //template int Image<int>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
399 //template int Image<short>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
400 //template int Image<float>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
401 //template int Image<unsigned int>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
402 //template int Image<double>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
403 //template int Image<char>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
404 //template int Image<unsigned short>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
405 //template int Image<unsigned char>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
406 //template int Image<unsigned long>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
407 //template int Image<long>::readPreview(FileName const&, unsigned long, unsigned long, int, unsigned long);
408 template class Image<std::complex<double> >;
409 template class Image<bool>;
410 template class Image<int>;
411 template class Image<short>;
412 template class Image<float>;
413 template class Image<unsigned int>;
414 template class Image<double>;
415 template class Image<char>;
416 template class Image<unsigned short>;
417 template class Image<unsigned char>;
418 template class Image<unsigned long>;
419 template class Image<long>;
420 template class Image<half_float::half>;
#define NSIZE(v)
bool isIdentity() const
Definition: matrix2d.cpp:1323
Rotation angle of an image (double,degrees)
#define YSIZE(v)
size_t xdim
void string2TransformationMatrix(const String &matrixStr, Matrix2D< double > &matrix, size_t dim)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void geo2TransformationMatrix(const MDRow &imageGeo, Matrix2D< double > &A, bool only_apply_shifts)
Global mmap error.
Definition: xmipp_error.h:170
Tilting angle of an image (double,degrees)
Shift for the image in the X axis (double)
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)
#define MULTIDIM_ARRAY(v)
Special label to be used when gathering MDs in MpiMetadataPrograms.
auxiliary label to be used as an index (long)
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
#define IMGMATRIX(I)
#define i
void resizeNoCopy(int Ydim, int Xdim)
Definition: matrix2d.h:534
void getPreview(ImageBase *imgBOut, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
Map addressing of file has failed.
Definition: xmipp_error.h:171
void setADimFile(ArrayDim aDim)
T & getValue(MDLabel label)
size_t zdim
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
Origin for the image in the Y axis (double)
Flip the image? (bool)
void getInfo(ImageInfo &imgInfo) const
#define XSIZE(v)
int readPreview(const FileName &name, size_t Xdim, size_t Ydim=0, int select_slice=CENTRAL_SLICE, size_t select_img=FIRST_IMAGE)
Definition: xmipp_image.cpp:38
#define ZSIZE(v)
static MDRowVec emptyHeaderVec()
DataType
scaling factor for an image or volume (double)
ArrayDim adim
void mode
Image base class.
void scaleToSize(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
File cannot be open.
Definition: xmipp_error.h:137
void setValue(MDLabel label, const T &d, bool addLabel=true)
virtual bool containsLabel(MDLabel label) const =0
std::string String
Definition: xmipp_strings.h:34
void selfApplyGeometry(int SplineDegree, bool wrap=xmipp_transformation::WRAP, bool only_apply_shifts=false)
transformation matrix in numpy string format or space separated (std::string)
String formatString(const char *format,...)
Shift for the image in the Z axis (double)
void applyGeo(const MDRow &row, bool only_apply_shifts=false, bool wrap=xmipp_transformation::WRAP) override
size_t ydim
void getTransformationMatrix(Matrix2D< double > &A, bool only_apply_shifts=false, const size_t n=0)
Origin for the image in the Z axis (double)
DataType datatype
CastWriteMode
Shift for the image in the Y axis (double)
Incorrect type received.
Definition: xmipp_error.h:190
Insufficient permissions to perform operation.
Definition: xmipp_error.h:138
#define ALL_SLICES
int readMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
int * n
< Score 4 for volumes