Xmipp  v3.23.11-Nereus
metadata_extension.cpp
Go to the documentation of this file.
1 /*
2  * metadata_extension.h
3  *
4  * Created on: May 12, 2010
5  * Author: roberto
6  */
7 #include "metadata_extension.h"
9 #include "xmipp_fftw.h"
10 #include "xmipp_image_generic.h"
11 #include "matrix2d.h"
12 #include "metadata_sql.h"
13 
14 #ifndef __linux__
15 #define MAXDOUBLE __DBL_MAX__
16 #endif
17 
18 
19 /*---------- Statistics --------------------------------------- */
20 void getStatistics(const MetaData &md, Image<double> & _ave, Image<double> & _sd, bool apply_geo, bool wrap, MDLabel image_label)
21 {
22  bool first = true;
23  int n = 0;
24 
25  // Calculate Mean
26  if (md.isEmpty())
27  REPORT_ERROR(ERR_MD_OBJECTNUMBER, "There is no selected images in Metadata.");
28 
29  Image<double> image, tmpImg;
30  FileName fnImg;
31  ApplyGeoParams params;
32  params.wrap = wrap;
33  for (size_t id : md.ids())
34  {
35  int enabled;
36  md.getValueOrDefault(MDL_ENABLED, enabled, id, 1); // default = enabled
37  if (enabled < 1)
38  continue;
39 
40  md.getValue(image_label, fnImg, id);
41  if (apply_geo)
42  image.readApplyGeo(fnImg, md, id, params);
43  else
44  image.read(fnImg);
45  if (first)
46  {
47  _ave = image;
48  first = false;
49  }
50  else
51  _ave() += image();
52  n++;
53  }
54 
55  if (n > 0)
56  _ave() /= n;
57  _sd = _ave;
58  _sd().initZeros();
59  // Calculate SD
60  for (size_t id : md.ids())
61  {
62  int enabled;
63  md.getValueOrDefault(MDL_ENABLED, enabled, id, 1); // default = enabled
64  if (enabled < 1)
65  continue;
66 
67  md.getValue(image_label, fnImg, id);
68  if (apply_geo)
69  image.readApplyGeo(fnImg, md, id, params);
70  else
71  image.read(fnImg);
72  tmpImg() = ((image() - _ave()));
73  tmpImg() *= tmpImg();
74  _sd() += tmpImg();
75  }
76  _sd() /= (n - 1);
77  _sd().selfSQRT();
78 }
79 
80 /* Write all images in a MetaData to a binary stack (usually .stk or .mrcs) */
81 
82 void writeMdToStack(const MetaData &md, const FileName &fnStack, bool apply_geo, bool wrap, MDLabel image_label)
83 {
84  size_t i = 0;
85 
86  if (md.isEmpty())
87  REPORT_ERROR(ERR_MD_OBJECTNUMBER, "writeMdToStack: input MetaData is empty!!!");
88 
89  ImageGeneric image;
90  FileName fnImg;
91  ApplyGeoParams params;
92  params.wrap = wrap;
93  int enabled;
94  bool containsEnabled = md.containsLabel(MDL_ENABLED);
95 
96  int mode = WRITE_OVERWRITE;
97 
98  for (size_t id : md.ids())
99  {
100  if (containsEnabled)
101  md.getValue(MDL_ENABLED, enabled, id);
102  else
103  enabled = 1;
104 
105  if (enabled == 1)
106  {
107  i++;
108 
109  md.getValue(image_label, fnImg, id);
110 
111  if (apply_geo)
112  image.readApplyGeo(fnImg, md, id, params);
113  else
114  image.read(fnImg);
115  image.write(fnStack, i, false, mode);
116  mode = WRITE_APPEND;
117  }
118  }
119 } /* function writeMdToStack */
120 
121 
122 /*---------- Statistics --------------------------------------- */
123 
125 {
126  // Parse the string values as floats
127  std::stringstream ss(matrix);
128  double values[16];
129  for (int i = 0; i < 16; i++)
130  ss >> values[i];
131 
132  //build the matrix from the parsed values
133 
134 
135  Matrix2D<double> transformM(3, 3);
136  dMij(transformM, 0, 2) = 0;
137  dMij(transformM, 1, 2) = 0;
138  dMij(transformM, 2, 0) = 0;
139  dMij(transformM, 2, 1) = 0;
140  dMij(transformM, 2, 2) = 1;
141  dMij(transformM, 0, 0) = values[0]; // cosine
142  dMij(transformM, 0, 1) = values[1]; // sine
143  dMij(transformM, 1, 0) = values[4]; // -sine
144  dMij(transformM, 1, 1) = values[5]; // cosine
145  dMij(transformM, 0, 2) = values[3]; // shiftx;
146  dMij(transformM, 1, 2) = values[7]; // shifty;
147  return transformM;
148 }
149 
150 void getAverageApplyGeo(const MetaData &md, MultidimArray<double> & _ave, MDLabel image_label)
151 {
152  bool first = true;
153  int n = 0;
154 
155  // Calculate Mean
156  if (md.isEmpty())
157  return;
158 
159  Image<double> image;
160  FileName fnImg;
161 
162  for (size_t id : md.ids())
163  {
164  int enabled;
165  md.getValueOrDefault(MDL_ENABLED, enabled, id, 1); // default = enabled
166  if (enabled < 1)
167  continue;
168 
169  md.getValue(image_label, fnImg, id);
170  image.readApplyGeo(fnImg, md, id);
171 
172  if (first)
173  {
174  _ave = image();
175  first = false;
176  }
177  _ave += image();
178  n++;
179  }
180 
181  if (n > 0)
182  _ave /= n;
183 }
184 
185 /*---------- Statistics --------------------------------------- */
186 void getStatistics(const MetaData &md, double& _ave, double& _sd, double& _min,
187  double& _max, bool apply_geo, MDLabel image_label)
188 {
189  _min = MAXDOUBLE;
190  _max = -MAXDOUBLE;
191  _ave = _sd = 0;
192  int n = 0;
193 
194  // Calculate Mean
195  if (md.isEmpty())
196  REPORT_ERROR(ERR_MD_OBJECTNUMBER, "There is no selected images in Metadata.");
197 
198  ImageGeneric image;
199  double min, max, avg, stddev;
200  FileName fnImg;
201  for (size_t id : md.ids())
202  {
203  int enabled;
204  md.getValueOrDefault(MDL_ENABLED, enabled, id, 1); // default = enabled
205  if (enabled < 1)
206  continue;
207 
208  md.getValue(image_label, fnImg, id);
209  if (apply_geo)
210  image.readApplyGeo(fnImg, md, id);
211  else
212  image.read(fnImg, DATA, ALL_IMAGES, true);
213  image().computeStats(avg, stddev, min, max);
214 
215  if (min < _min)
216  _min = min;
217  if (max > _max)
218  _max = max;
219 
220  _ave += avg;
221  _sd += stddev;
222 
223  n++;
224  }
225 
226  _ave /= n;
227  _sd /= n;
228 }
229 
230 /* Get Fourier statistics ------------------------------------------------- */
231 void getFourierStatistics(MetaDataDb &MDin, double sam, MetaData &MDout,
232  bool do_dpr, double max_sam, MDLabel image_label)
233 {
234  MetaDataDb MDaux;
235  std::vector<MetaDataDb> vMD;
236  MDaux.randomize(MDin);
237  MDaux.split(2,vMD,image_label);
238  MetaDataDb &MD1 = vMD.at(0);
239  MetaDataDb &MD2 = vMD.at(1);
240 
241  Image<double> I1, I2, Id;
242  getStatistics(MD1,I1,Id,true, image_label);
243  getStatistics(MD2,I2,Id,true, image_label);
244  I1().setXmippOrigin();
245  I2().setXmippOrigin();
246 
247  MultidimArray<double> freq, frc, dpr, frc_noise, ssnr, error_l2;
248  frc_dpr(I1(), I2(), sam, freq, frc, frc_noise, dpr,error_l2,do_dpr);
249 
250  MDout.clear();
252  {
253  if (i>0)
254  {
255  size_t id=MDout.addObject();
256  if(max_sam >=0 && ((1./dAi(freq, i))<max_sam) )
257  {
258  if(do_dpr)
259  dAi(dpr, i)=0.;
260  dAi(frc, i)=0.;
261  }
262  MDout.setValue(MDL_RESOLUTION_FREQ,dAi(freq, i),id);
263  MDout.setValue(MDL_RESOLUTION_FRC,dAi(frc, i),id);
264  if(do_dpr)
265  MDout.setValue(MDL_RESOLUTION_DPR,dAi(dpr, i),id);
266  MDout.setValue(MDL_RESOLUTION_ERRORL2,dAi(error_l2, i),id);
267  MDout.setValue(MDL_RESOLUTION_FRCRANDOMNOISE,dAi(frc_noise, i),id);
268  MDout.setValue(MDL_RESOLUTION_FREQREAL,1./dAi(freq, i),id);
269  }
270  }
271 }
272 
273 void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
274 {
275  if (!md.isEmpty())
276  {
277  FileName fn_img;
278  md.getValue(image_label, fn_img, md.firstRowId());
279  getImageSize(fn_img, Xdim, Ydim, Zdim, Ndim);
280 
281  }
282  else
283  REPORT_ERROR(ERR_MD_NOOBJ, "Can not read image size from empty metadata");
284 }
285 
286 void getImageInfo(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, DataType &datatype, MDLabel image_label)
287 {
288  if (!md.isEmpty())
289  {
290  FileName fn_img;
291  md.getValue(image_label, fn_img, md.firstRowId());
292  getImageInfo(fn_img, Xdim, Ydim, Zdim, Ndim, datatype);
293 
294  }
295  else
296  REPORT_ERROR(ERR_MD_NOOBJ, "Can not read image size from empty metadata");
297 }
298 
299 void getImageInfo(const MetaData &md, ImageInfo &imgInfo, MDLabel image_label)
300 {
301  if (!md.isEmpty())
302  {
303  FileName fn_img;
304  md.getValue(image_label, fn_img, md.firstRowId());
305  getImageInfo(fn_img, imgInfo);
306  }
307  else
308  REPORT_ERROR(ERR_MD_NOOBJ, "Can not read image size from empty metadata");
309 }
310 
311 void getImageSizeFromFilename(const FileName &filename, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
312 {
313  if (filename.hasImageExtension())
314  getImageSize(filename, Xdim, Ydim, Zdim, Ndim);
315  else
316  {
317  MetaDataVec mdi;
318  mdi.setMaxRows(1);
319  mdi.read(filename);
320  getImageSize(mdi, Xdim, Ydim, Zdim, Ndim, image_label);
321  }
322 }
323 
324 bool compareImage(const FileName &filename1, const FileName &filename2)
325 {
326  ImageGeneric Im1,Im2;
327  Im1.read(filename1);
328  Im2.read(filename2);
329  bool result = *(Im1.data) == *(Im2.data);
330  return( result);
331 }
332 
333 bool compareImageSize(const FileName &filename1, const FileName &filename2)
334 {
335  size_t x,y,z, X, Y, Z, n, N;
336  getImageSizeFromFilename(filename1,x,y,z,n);
337  getImageSizeFromFilename(filename2,X,Y,Z,N);
338  return (x==X && y == Y && z == Z && n == N);
339 }
340 
341 bool compareTwoMetadataFiles(const FileName &fn1, const FileName &fn2)
342 {
343  StringVector blockList;
344  getBlocksInMetaDataFile(fn1,blockList);
345  FileName fn_1aux, fn_2aux;
346  MetaDataVec md1, md2;
347 
348  for (StringVector::iterator it= blockList.begin();
349  it!=blockList.end(); it++)
350  {
351  fn_1aux.compose(*it, fn1);
352  fn_2aux.compose(*it, fn2);
353  md1.read(fn_1aux);
354  md2.read(fn_2aux);
355  if (!(md1 == md2))
356  return false;
357  }
358 
359  return true;
360 }
361 
362 
363 
364 
365 
366 int maxFileNameLength(const MetaData &md, MDLabel image_label)
367 {
368  int maxLength = 0;
369  for (size_t id : md.ids())
370  {
371  FileName fnImg;
372  md.getValue(image_label, fnImg, id);
373  int length = fnImg.length();
374  maxLength = XMIPP_MAX(length, maxLength);
375  }
376  return maxLength;
377 }
378 
379 void mpiSelectPart(MetaDataDb &md, int rank, int size, int &num_img_tot)
380 {
381  num_img_tot = md.size();
382  MetaDataDb aux(md);
383  md.selectSplitPart(aux, size, rank);
384 }
385 
387 {
388  if (fn.isStar1(true))
389  md.read(fn);
390  else
391  {
392  // Try to read a one or two column file
393  std::ifstream fhIn;
394  fhIn.open(fn.c_str());
395  if (!fhIn)
397  md.clear();
398  String line;
399  size_t id;
400  while (!fhIn.eof())
401  {
402  getline(fhIn,line);
403  std::vector<std::string> tokens;
404  tokenize(line, tokens, " \t");
405  switch (tokens.size())
406  {
407  case 0:
408  break;
409  case 1:
410  id = md.addObject();
411  md.setValue(MDL_IMAGE,tokens[0], id);
412  break;
413  case 2:
414  id = md.addObject();
415  md.setValue(MDL_IMAGE,tokens[0], id);
416  md.setValue(MDL_IMAGE1,tokens[1], id);
417  break;
418  default:
420  (String)"Invalid number of objects in line:"+line);
421  }
422  }
423  fhIn.close();
424  }
425 }
426 
427 /* Substitute ------------------------------------------------------------- */
428 void substituteOriginalImages(const FileName &fn, const FileName &fnOrig, const FileName &fnOut,
429  MDLabel label, bool skipFirstBlock)
430 {
431  // Read the original files
432  MetaDataVec mdorig(fnOrig);
433  if (mdorig.containsLabel(MDL_ENABLED))
434  mdorig.removeObjects(MDValueEQ(MDL_ENABLED, -1));
435  StringVector filesOrig;
436  mdorig.getColumnValues(MDL_IMAGE, filesOrig);
437  mdorig.clear(); // Save memory
438  FileName auxFn;
439 
440  // Read the blocks available
441  StringVector blocks;
442  getBlocksInMetaDataFile(fn, blocks);
443 
444  // Delete the output file if it exists
445  fnOut.deleteFile();
446 
447  // Process each block
448  for (size_t b=0; b<blocks.size(); b++)
449  {
450  MetaDataVec md;
451  md.read(blocks[b]+"@"+fn);
452  if (md.containsLabel(label) && (!skipFirstBlock || b!=0))
453  {
454  FileName fnImg;
455  size_t stkNo;
456  String stkName;
457  for (size_t id : md.ids())
458  {
459  md.getValue(label, fnImg, id);
460  fnImg.decompose(stkNo,stkName);
461  md.setValue(label, filesOrig[stkNo], id);
462  }
463  }
464  auxFn.compose(blocks[b],fnOut);
465  md.write(auxFn, MD_APPEND);
466  //md._write(fnOut,blocks[b],MD_APPEND);
467  }
468 }
469 
470 void bsoftRemoveLoopBlock(const FileName &_inFile, const FileName &_outFile)
471 {
472  std::ifstream in(_inFile.c_str());
473  std::ofstream out(_outFile.c_str());
474 
475  if (!in)
476  REPORT_ERROR(ERR_IO_NOTEXIST,"can not open file: " + _inFile);
477 
478  if (!out)
479  REPORT_ERROR(ERR_IO_NOTEXIST,"can not open file: " + _outFile);
480 
481  std::string line;
482  size_t len = 5;
483  bool newData = false;
484  size_t pos;
485  std::string _data;
486  int counter=1;
487  bool comment=true;
488 
489  while (getline(in, line))
490  {
491  //remove comments xmipp cannot handle them outside header
492  pos = line.substr(0,1).find("#",0,1);
493  if (pos != std::string::npos)
494  {
495  if(comment)
496  out << line << '\n';
497  continue;
498  }
499  //make sure that data block does not start with a number xmipp cannot handle them
500  pos = line.substr(0,5).find("data_",0,5);
501  if (pos != std::string::npos)
502  {
503  if(('0' <= line[5]) && (line[5]<='9'))
504  line.replace(pos, len, "data_A");
505  newData = true;
506  comment=false;
507  out << line << '\n';
508  continue;
509  }
510  pos = line.substr(0,5).find("loop_",0,5);
511  if (pos != std::string::npos)
512  {
513  std::stringstream ss;
514  ss << "data_loop_" << counter++;
515  if (!newData)
516  {
517  line.replace(pos, len, ss.str());
518  out << line << "\nloop_\n";
519  }
520  else
521  out << line << '\n';
522  newData = false;
523  continue;
524  }
525  //line no data no comment no loop
526  pos = line.substr(0,2).find("_",0,1);
527  if (pos != std::string::npos)
528  {
529  newData = false;
530  out << line << '\n';
531  continue;
532  }
533  out << line << '\n';
534  }
535 }
536 
537 void bsoftRestoreLoopBlock(const FileName &_inFile, const FileName &_outFile)
538 {
539  std::ifstream in(_inFile.c_str());
540  std::ofstream out(_outFile.c_str());
541 
542  if (!in)
543  REPORT_ERROR(ERR_IO_NOTEXIST,"can not open file: " + _inFile);
544 
545  if (!out)
546  REPORT_ERROR(ERR_IO_NOTEXIST,"can not open file: " + _outFile);
547 
548  std::string line;
549  size_t len = 10;
550  size_t pos;
551 
552  while (getline(in, line))
553  {
554  pos = line.substr(0,10).find("data_loop_",0,len);
555  if (pos != std::string::npos)
556  continue;
557  out << line << '\n';
558  }
559 }
560 
561 MDRowVec firstRow(const FileName &fnMetadata) {
562  MetaDataVec md;
563  md.setMaxRows(1);
564  md.read(fnMetadata);
565  MDRowVec row;
566  md.getRow(row, md.firstRowId());
567  return row;
568 }
void bsoftRemoveLoopBlock(const FileName &_inFile, const FileName &_outFile)
virtual void setMaxRows(size_t maxRows=0)
void removeObjects(const std::vector< size_t > &toRemove) override
#define dAi(v, i)
void getImageSizeFromFilename(const FileName &filename, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
void min(Image< double > &op1, const Image< double > &op2)
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
virtual size_t addObject()=0
void selectSplitPart(const MetaData &mdIn, size_t n, size_t part, const MDLabel sortLabel=MDL_OBJID)
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
virtual void clear()
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
No exist requested object.
Definition: xmipp_error.h:156
virtual bool containsLabel(const MDLabel label) const =0
static double * y
virtual size_t firstRowId() const =0
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
void compose(const String &str, const size_t no, const String &ext="")
void substituteOriginalImages(const FileName &fn, const FileName &fnOrig, const FileName &fnOut, MDLabel label, bool skipFirstBlock)
void frc_dpr(MultidimArray< double > &m1, MultidimArray< double > &m2, double sampling_rate, MultidimArray< double > &freq, MultidimArray< double > &frc, MultidimArray< double > &frc_noise, MultidimArray< double > &dpr, MultidimArray< double > &error_l2, bool dodpr, bool doRfactor, double minFreq, double maxFreq, double *rFactor)
Definition: xmipp_fftw.cpp:491
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
bool hasImageExtension() const
void decompose(size_t &no, String &str) const
virtual IdIteratorProxy< false > ids()
std::unique_ptr< MDRow > getRow(size_t id) override
void getStatistics(const MetaData &md, Image< double > &_ave, Image< double > &_sd, bool apply_geo, bool wrap, MDLabel image_label)
void getFourierStatistics(MetaDataDb &MDin, double sam, MetaData &MDout, bool do_dpr, double max_sam, MDLabel image_label)
void getBlocksInMetaDataFile(const FileName &inFile, StringVector &blockList)
std::vector< String > StringVector
Definition: xmipp_strings.h:35
virtual bool getValue(MDObject &mdValueOut, size_t id) const =0
doublereal * x
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
#define i
Is this image enabled? (int [-1 or 1])
differential phase residual (double)
Incorrect number of objects in Metadata.
Definition: xmipp_error.h:160
void writeMdToStack(const MetaData &md, const FileName &fnStack, bool apply_geo, bool wrap, MDLabel image_label)
Matrix2D< double > getMatrix(char *matrix)
void clear() override
glob_log first
void getImageInfo(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, DataType &datatype, MDLabel image_label)
doublereal * b
bool compareImage(const FileName &filename1, const FileName &filename2)
compare two image files
void randomize(const MetaDataDb &MDin)
virtual bool isEmpty() const
bool setValue(const MDObject &mdValueIn, size_t id)
int in
Frequency in A (double)
size_t firstRowId() const override
#define dMij(m, i, j)
Definition: matrix2d.h:139
FileName fnOut
#define MAXDOUBLE
void bsoftRestoreLoopBlock(const FileName &_inFile, const FileName &_outFile)
void max(Image< double > &op1, const Image< double > &op2)
void tokenize(const String &str, StringVector &tokens, const String &delimiters)
bool isStar1(bool failIfNotExists) const
double z
void readMetaDataWithTwoPossibleImages(const FileName &fn, MetaData &md)
__host__ __device__ float length(float2 v)
File or directory does not exist.
Definition: xmipp_error.h:136
Image associated to this object (std::string)
DataType
void mode
bool compareImageSize(const FileName &filename1, const FileName &filename2)
compare if same dimensions
size_t size() const override
Frequency in 1/A (double)
void deleteFile() const
const T getValueOrDefault(const MDLabel label, size_t id, const T &_default) const
bool getValue(MDObject &mdValueOut, size_t id) const override
bool setValue(const MDLabel label, const T &valueIn, size_t id)
#define len
void getColumnValues(const MDLabel label, std::vector< MDObject > &valuesOut) const override
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
int maxFileNameLength(const MetaData &md, MDLabel image_label)
Error in l2 (double)
std::string String
Definition: xmipp_strings.h:34
Fourier shell correlation noise (double)
#define ALL_IMAGES
void getAverageApplyGeo(const MetaData &md, MultidimArray< double > &_ave, MDLabel image_label)
void mpiSelectPart(MetaDataDb &md, int rank, int size, int &num_img_tot)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
MDRowVec firstRow(const FileName &fnMetadata)
bool containsLabel(const MDLabel label) const override
bool compareTwoMetadataFiles(const FileName &fn1, const FileName &fn2)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false)
MultidimArrayGeneric * data
int * n
Name of an image (std::string)
MDLabel
virtual void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true)=0
Fourier shell correlation (double)
void split(size_t n, std::vector< MetaDataDb > &results, const MDLabel sortLabel=MDL_OBJID)