Xmipp  v3.23.11-Nereus
micrograph.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar (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 #include "micrograph.h"
27 #include <core/args.h>
28 #include <data/mask.h>
29 #include <core/geometry.h>
30 
31 #include <fstream>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 //#ifdef LINUX
38 //#include <unistd.h>
39 //#endif
40 
42 {
43  single_particle.clear();
44  coords.clear();
45  fn_coords = fn_micrograph = "";
46  X_window_size = Y_window_size = -1;
47  fh_micrograph = -1;
48  Xdim = Ydim = -1;
49  datatype = -1;
50  compute_transmitance = false;
51  compute_inverse = false;
52  IUChar.clear();
53  IShort.clear();
54  IUShort.clear();
55  IInt.clear();
56  IUInt.clear();
57  IFloat.clear();
58 }
59 
60 /* Open micrograph --------------------------------------------------------- */
61 void Micrograph::open_micrograph(const FileName &_fn_micrograph)
62 {
63  clear();
64  // Micrograph name
65  fn_micrograph = _fn_micrograph;
66  // Look for micrograph dimensions
67  Image<char> auxI = {};
68  auxI.read(fn_micrograph, HEADER);
69 
70  auxI.getDimensions(Xdim, Ydim, Zdim, Ndim);
71  if ((Zdim > 1) || (Ndim > 1))
74  "Micrograph::open_micrograph: Only files with a single micrograph may be processed. Error reading " + fn_micrograph);
75  auxI.MDMainHeader.getValue(MDL_DATATYPE, datatype);
76  __offset = 0;
77  auxI.clear();
78  //#define DEBUG
79 #ifdef DEBUG
80 
81  std::cerr << "x,y,z,n, datatype : "
82  << Xdim << " "
83  << Ydim << " "
84  << Zdim << " "
85  << Ndim << " "
86  << datatype << " "
87  <<std::endl;
88 #endif
89 #undef DEBUG
90  //3,4,6
91  // Open micrograph and map
92  int result;
93  switch (datatype)
94  {
95  case DT_UHalfByte:
96  case DT_UChar:
97  result = IUChar.readMapped(fn_micrograph, FIRST_IMAGE);
98  pixelDesvFilter(IUChar.data, stdevFilter);
99  break;
100  case DT_UShort:
101  result = IUShort.readMapped(fn_micrograph, FIRST_IMAGE);
102  pixelDesvFilter(IUShort.data, stdevFilter);
103  break;
104  case DT_Short:
105  result = IShort.readMapped(fn_micrograph, FIRST_IMAGE);
106  pixelDesvFilter(IShort.data, stdevFilter);
107  break;
108  case DT_Int:
109  result = IInt.readMapped(fn_micrograph, FIRST_IMAGE);
110  pixelDesvFilter(IInt.data, stdevFilter);
111  break;
112  case DT_UInt:
113  result = IUInt.readMapped(fn_micrograph, FIRST_IMAGE);
114  pixelDesvFilter(IUChar.data, stdevFilter);
115  break;
116  case DT_Float:
117  result = IFloat.readMapped(fn_micrograph, FIRST_IMAGE);
118  pixelDesvFilter(IFloat.data, stdevFilter);
119  break;
120  case DT_HalfFloat:
121  datatype = DT_Float; // Converting
122  result = IFloat.read(fn_micrograph, DATA, FIRST_IMAGE);
123  pixelDesvFilter(IFloat.data, stdevFilter);
124  break;
125  default:
126  std::cerr << "Micrograph::open_micrograph: Unknown datatype "
127  << datatype << std::endl;
129  break;
130  }
131  //fh_micrograph = open(fn_micrograph.c_str(), O_RDWR, S_IREAD | S_IWRITE);
132  if (result < 0)
133  REPORT_ERROR(
135  (std::string)"Micrograph::open_micrograph: There is a "
136  "problem opening " + fn_micrograph + "\nCheck that the file has write permission");
137 }
138 
139 /* Close micrograph -------------------------------------------------------- */
141 {
142  switch (datatype)
143  {
144  case DT_UHalfByte:
145  case DT_UChar:
146  IUChar.clear();
147  break;
148  case DT_UShort:
149  IUShort.clear();
150  break;
151  case DT_Short:
152  IShort.clear();
153  break;
154  case DT_Int:
155  IInt.clear();
156  break;
157  case DT_UInt:
158  IUInt.clear();
159  break;
160  case DT_Float:
161  IFloat.clear();
162  break;
163  default:
164  std::cerr << "Micrograph::close_micrograph: Unknown datatype "
165  << datatype << std::endl;
167  break;
168  }
169 }
170 /* Get datatype detph -------------------------------------------------------- */
172 {
173  switch (datatype)
174  {
175  case DT_UHalfByte:
176  case DT_UChar:
177  return (8 * sizeof(unsigned char));
178  case DT_UShort:
179  return (8 * sizeof(unsigned short));
180  case DT_Short:
181  return (8 * sizeof(short));
182  case DT_UInt:
183  return (8 * sizeof(unsigned int));
184  case DT_Int:
185  return (8 * sizeof(int));
186  case DT_Float:
187  return (8 * sizeof(float));
188  default:
189  std::cerr << "Micrograph::getDatatypeDetph: Unknown datatype "
190  << datatype << std::endl;
192  break;
193  }
194 }
195 
196 /* Save coordinates to disk ------------------------------------------------ */
197 void Micrograph::write_coordinates(int label, double minCost,
198  const FileName &_fn_coords)
199 {
200  std::ofstream fh;
201  if (_fn_coords != "")
202  fn_coords = _fn_coords;
203 
204  MetaDataVec MD;
205  MD.setComment((std::string) "Selected Coordinates for file " + fn_coords);
206  int imax = coords.size();
207  for (int i = 0; i < imax; i++)
208  {
209  if (coords[i].valid && coords[i].cost > minCost
210  && coords[i].label == label)
211  {
212  size_t id = MD.addObject();
213  MD.setValue(MDL_XCOOR, coords[i].X, id);
214  MD.setValue(MDL_YCOOR, coords[i].Y, id);
215  }
216  }
217  MD.write(fn_coords);
218 }
219 
220 /* Read coordinates from disk ---------------------------------------------- */
221 void Micrograph::read_coordinates(int label, const FileName &_fn_coords)
222 {
223  std::ifstream fh;
224  int line_no = 0;
225  std::string line;
226 
227  fn_coords = _fn_coords;
228 
229  MetaDataVec MD;
230  MD.read(fn_coords);
231  line_no = MD.size();
232 
233  // Resize coordinate list and read
234  coords.reserve(line_no);
235  struct Particle_coords aux;
236  aux.valid = true;
237  aux.label = label;
238  aux.cost = 1;
239  aux.scoreVar = -1;
240  aux.scoreGini = -1;
241 
242  for (size_t objId : MD.ids())
243  {
244  MD.getValue(MDL_XCOOR, aux.X, objId); //aux.X=x;
245  MD.getValue(MDL_YCOOR, aux.Y, objId); //aux.Y=y;
247  {
248  MD.getValue(MDL_SCORE_BY_VAR, aux.scoreVar, objId);
249  MD.getValue(MDL_SCORE_BY_GINI, aux.scoreGini, objId);
250  }
251  coords.push_back(aux);
252  }
253 }
254 
255 /* Transform all coordinates ---------------------------------------------- */
257 {
258  Matrix1D<double> m(3);
260 
261  int imax = coords.size();
262  for (int i = 0; i < imax; i++)
263  {
264  if (coords[i].valid)
265  {
266  VECTOR_R3(m, coords[i].X, coords[i].Y, 1);
267  M3x3_BY_V3x1(m, M, m);
268  coords[i].X = (int) XX(m);
269  coords[i].Y = (int) YY(m);
270  }
271  }
272 }
273 
274 /* Multiply coordinates by a constant -------------------------------------- */
275 void Micrograph::scale_coordinates(const double &c)
276 {
277  int imax = coords.size();
278  for (int i = 0; i < imax; i++)
279  {
280  if (coords[i].valid)
281  {
282  coords[i].X = (int) (coords[i].X * c);
283  coords[i].Y = (int) (coords[i].Y * c);
284  }
285  }
286 
287 }
288 
289 /* Scissor ----------------------------------------------------------------- */
291  double Dmin, double Dmax, double scaleX, double scaleY,
292  bool only_check, bool fillBorders)
293 {
294  if (X_window_size == -1 || Y_window_size == -1)
296  "Micrograph::scissor: window size not set");
297  if (datatype == DT_UChar || datatype == DT_UHalfByte)
298  return templateScissor(IUChar, P, result, Dmin, Dmax, scaleX, scaleY,
299  only_check, fillBorders);
300  else if (datatype == DT_UShort)
301  return templateScissor(IUShort, P, result, Dmin, Dmax, scaleX, scaleY,
302  only_check, fillBorders);
303  else if (datatype == DT_Short)
304  return templateScissor(IShort, P, result, Dmin, Dmax, scaleX, scaleY,
305  only_check, fillBorders);
306  else if (datatype == DT_UInt)
307  return templateScissor(IUInt, P, result, Dmin, Dmax, scaleX, scaleY,
308  only_check, fillBorders);
309  else if (datatype == DT_Int)
310  return templateScissor(IInt, P, result, Dmin, Dmax, scaleX, scaleY,
311  only_check, fillBorders);
312  else if (datatype == DT_Float)
313  return templateScissor(IFloat, P, result, Dmin, Dmax, scaleX, scaleY,
314  only_check, fillBorders);
315  else
317  "Micrograph::scissor: unknown datatype");
318 
319 }
320 
321 /* Produce all images ------------------------------------------------------ */
322 void Micrograph::produce_all_images(int label, double minCost,
323  const FileName &fn_rootIn, const FileName &fn_image, double ang,
324  bool rmStack, bool fillBorders,
325  bool extractNoise, int Nnoise)
326 {
327  MetaDataVec SF;
328  Image<double> I;
329  Micrograph *M;
330 
331  // Set Source image
332  if (fn_image == "")
333  M = this;
334  else
335  {
336  M = new Micrograph;
337  M->open_micrograph(fn_image/*, swapbyte*/);
338  M->set_window_size(X_window_size, Y_window_size);
339  M->set_transmitance_flag(compute_transmitance);
340  M->set_inverse_flag(compute_inverse);
341  }
342 
343  // Set scale for particles
344  int MXdim;
345  int MYdim;
346  int thisXdim;
347  int thisYdim;
348  M->size(MXdim, MYdim);
349  this->size(thisXdim, thisYdim);
350  double scaleX = (double) MXdim / thisXdim;
351  double scaleY = (double) MYdim / thisYdim;
352 
353  // Compute max and minimum if compute_transmitance
354  // or compute_inverse flags are ON
355  double Dmax=0.;
356  double Dmin=0.;
357  if (compute_transmitance || compute_inverse)
358  {
359  (*this).computeDoubleMinMax(Dmin, Dmax);
360 
361  if (compute_transmitance)
362  {
363  if (Dmin > 1)
364  Dmin = log10(Dmin);
365  if (Dmax > 1)
366  Dmax = log10(Dmax);
367  }
368  }
369  // Scissor all particles
370  if (ang != 0)
371  std::cout << "Angle from Y axis to tilt axis " << ang << std::endl
372  << " applying appropriate rotation\n";
373  int nmax = ParticleNo();
374  int nparticles = nmax;
375  if (extractNoise && Nnoise>0)
376  nmax=Nnoise;
377  FileName fn_aux;
378  FileName _ext = fn_rootIn.getFileFormat();
379  FileName fn_out;
380  FileName fn_root = fn_rootIn.removeFileFormat().removeLastExtension();
381  if (fn_rootIn.hasStackExtension())
382  fn_out=fn_root.addExtension(_ext);
383  else
384  fn_out=fn_rootIn.addExtension("stk");
385 
386  if (rmStack)
387  fn_out.deleteFile();
388  size_t ii = 0;
389  size_t id;
390 
391  Particle_coords Pnoise;
392  Pnoise.valid = true;
393  Pnoise.label = 0;
394  Pnoise.cost = 1;
395  Pnoise.scoreVar = -1;
396  Pnoise.scoreGini = -1;
397 
398  int minNoiseDistance=Y_window_size/2;
399  std::vector<Particle_coords> noiseCoords;
400 
401  for (int n = 0; n < nmax; n++)
402  {
403  if (coords[n].valid && coords[n].cost > minCost && coords[n].label == label)
404  {
405  fn_aux.compose(++ii, fn_out);
406  id = SF.addObject();
407  // If the ctfRow was set, copy the info to images metadata
408  if (ctfRow.containsLabel(MDL_CTF_DEFOCUSU))
409  SF.setRow(ctfRow, id);
410  SF.setValue(MDL_IMAGE, fn_aux, id);
411  SF.setValue(MDL_MICROGRAPH, M->fn_micrograph, id);
412  SF.setValue(MDL_XCOOR, coords[n].X, id);
413  SF.setValue(MDL_YCOOR, coords[n].Y, id);
414  if (coords[n].scoreVar>0)
415  {
418  }
419  bool t=false;
420  if (extractNoise)
421  {
422  // Look for coordinate that is away from the rest of coordinates
423  bool found=false;
424  while (!found)
425  {
426  Pnoise.X=int(rnd_unif(X_window_size,thisXdim-X_window_size));
427  Pnoise.Y=int(rnd_unif(Y_window_size,thisYdim-Y_window_size));
428  found=true;
429  for (int nn=0; nn<nparticles; nn++)
430  {
431  if (std::abs(Pnoise.X-coords[nn].X)<minNoiseDistance && std::abs(Pnoise.Y-coords[nn].Y)<minNoiseDistance)
432  {
433  found=false;
434  break;
435  }
436  }
437  }
438  noiseCoords.push_back(Pnoise);
439  t = M->scissor(Pnoise, I(), Dmin, Dmax, scaleX, scaleY, false, fillBorders);
440  }
441  else
442  t = M->scissor(coords[n], I(), Dmin, Dmax, scaleX, scaleY, false, fillBorders);
443  if (!t)
444  {
445  std::cout << "Particle " << fn_aux
446  << " is very near the border, "
447  << "corresponding image is set to blank\n";
448  SF.setValue(MDL_ENABLED, -1, id);
449  }
450  else
451  SF.setValue(MDL_ENABLED, 1, id);
452  // if (ang!=0) I().rotate(-ang);
453  double mean=I().computeAvg();
454  if (compute_inverse)
455  SF.setValue(MDL_LOCAL_AVERAGE, Dmax-(Dmax-Dmin)*mean, id);
456  else
457  SF.setValue(MDL_LOCAL_AVERAGE, mean, id);
458  I.write(fn_out, ii, true, WRITE_APPEND);
459  }
460  }
461  SF.write(fn_out.withoutExtension() + ".xmd");
462 
463 
464  // Free source image??
465  if (fn_image != "")
466  {
467  M->close_micrograph();
468  delete M;
469  }
470 
471  if (extractNoise)
472  {
473  coords.clear();
474  coords=noiseCoords;
475  }
476 }
477 
478 /* Search coordinate near a position --------------------------------------- */
479 int Micrograph::search_coord_near(int x, int y, int prec) const
480 {
481  int imax = coords.size();
482  int prec2 = prec * prec;
483  for (int i = 0; i < imax; i++)
484  if ((coords[i].X - x) * (coords[i].X - x)
485  + (coords[i].Y - y) * (coords[i].Y - y) < prec2
486  && coords[i].valid)
487  return i;
488  return -1;
489 }
490 
491 /* Invalidate a coordinate ------------------------------------------------- */
493 {
494  if (n < 0 || n >= ParticleNo())
496  "Micrograph::invalidate_coord: Index out of range");
497  coords[n].valid = false;
498 }
499 
500 /* Add coordinate ---------------------------------------------------------- */
501 int Micrograph::add_coord(int x, int y, int label, double cost)
502 {
503  struct Particle_coords aux;
504  aux.valid = true;
505  aux.X = x;
506  aux.Y = y;
507  aux.label = label;
508  aux.cost = cost;
509  aux.scoreVar = -1;
510  aux.scoreGini = -1;
511  coords.push_back(aux);
512  return coords.size() - 1;
513 }
514 
515 /* Move last coordinate ---------------------------------------------------- */
517 {
518  if (coords.size() > 0)
519  {
520  coords.back().X = x;
521  coords.back().Y = y;
522  }
523 }
524 
525 void Micrograph::resize(int Xdim, int Ydim, const FileName &filename)
526 {
527  this->Xdim = Xdim;
528  this->Ydim = Ydim;
529  this->Zdim = 1;
530  this->Ndim = 1;
531  if (datatype == DT_UChar || datatype == DT_UHalfByte)
532  {
533  IUChar.data.setMmap(true);
534  IUChar.data.resize(1, 1, Ydim, Xdim);
535  }
536  else if (datatype == DT_UShort)
537  {
538  IUShort.data.setMmap(true);
539  IUShort.data.resize(1, 1, Ydim, Xdim);
540  }
541  else if (datatype == DT_Short)
542  {
543  IShort.data.setMmap(true);
544  IShort.data.resize(1, 1, Ydim, Xdim);
545  }
546  else if (datatype == DT_UInt)
547  {
548  IUInt.data.setMmap(true);
549  IUInt.data.resize(1, 1, Ydim, Xdim);
550  }
551  else if (datatype == DT_Int)
552  {
553  IInt.data.setMmap(true);
554  IInt.data.resize(1, 1, Ydim, Xdim);
555  }
556  else if (datatype == DT_Float)
557  {
558  IFloat.data.setMmap(true);
559  IFloat.data.resize(1, 1, Ydim, Xdim);
560  }
561  else
562  REPORT_ERROR(ERR_TYPE_INCORRECT, "Unknown datatype");
563 
564 }
565 void Micrograph::write(const FileName &fileName, CastWriteMode castMode)
566 {
567  if (datatype == DT_UChar)
568  {
569  IUChar.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
570  }
571  else if (datatype == DT_UHalfByte)
572  {
574  "Micrograph::set_val::(): non supported datatype UHalfByte");
575  }
576  else if (datatype == DT_UShort)
577  {
578  IUShort.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
579  }
580  else if (datatype == DT_Short)
581  {
582  IShort.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
583  }
584  else if (datatype == DT_UInt)
585  {
586  IUInt.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
587  }
588  else if (datatype == DT_Int)
589  {
590  IInt.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
591  }
592  else if (datatype == DT_Float)
593  {
594  IFloat.write(fileName, FIRST_IMAGE, false, WRITE_OVERWRITE, castMode);
595  }
596  else
598  "Micrograph::set_val::(): unknown datatype");
599 
600 }
601 
602 /* Tilt pair aligner ------------------------------------------------------ */
604 {
605  clear();
606 }
607 
609 {
610  coordU.clear();
611  coordT.clear();
612  Au.clear();
613  Bt.clear();
614  Put.clear();
615  Ptu.clear();
616  Au.initZeros(3, 3);
617  Bt.initZeros(3, 3);
618  Nu = 0;
619  m.resizeNoCopy(3);
620 }
621 
622 void TiltPairAligner::addCoordinatePair(int _muX, int _muY, int _mtX,
623  int _mtY)
624 {
625  coordU.push_back(_muX);
626  coordU.push_back(_muY);
627  coordT.push_back(_mtX);
628  coordT.push_back(_mtY);
629  Nu++; // Number of particles
630 
631 #ifdef _DEBUG
632 
633  std::cout << "Adding point U(" << U.X << "," << U.Y << ") T(" << T.X << ","
634  << T.Y << ")\n";
635  std::cout << "A at input" << Au << "B at input" << Bt;
636 #endif
637  // Adjust untilted dependent matrix
638  MAT_ELEM(Au,0, 0) += _muX * _muX;
639  MAT_ELEM(Au,0, 1) += _muX * _muY;
640  MAT_ELEM(Au,0, 2) += _muX;
641  MAT_ELEM(Au,1, 0) = MAT_ELEM(Au,0, 1);
642  MAT_ELEM(Au,1, 1) += _muY * _muY;
643  MAT_ELEM(Au,1, 2) += _muY;
644  MAT_ELEM(Au,2, 0) = MAT_ELEM(Au,0, 2);
645  MAT_ELEM(Au,2, 1) = MAT_ELEM(Au,1, 2);
646  MAT_ELEM(Au,2, 2) = Nu;
647 
648  // Adjust tilted dependent matrix
649  MAT_ELEM(Bt,0, 0) += _mtX * _muX;
650  MAT_ELEM(Bt,0, 1) += _mtY * _muX;
651  MAT_ELEM(Bt,0, 2) = MAT_ELEM(Au,0, 2);
652  MAT_ELEM(Bt,1, 0) += _mtX * _muY;
653  MAT_ELEM(Bt,1, 1) += _mtY * _muY;
654  MAT_ELEM(Bt,1, 2) = MAT_ELEM(Au,1, 2);
655  MAT_ELEM(Bt,2, 0) += _mtX;
656  MAT_ELEM(Bt,2, 1) += _mtY;
657  MAT_ELEM(Bt,2, 2) = MAT_ELEM(Au,2, 2);
658 
659 #ifdef _DEBUG
660 
661  std::cout << "A at output" << Au << "B at output" << Bt;
662 #endif
663 
664 
665 }
666 
667 /* Adjust passing matrix --------------------------------------------------- */
668 void TiltPairAligner::adjustPassingMatrix(int _muX, int _muY, int _mtX,
669  int _mtY)
670 {
671  addCoordinatePair(_muX, _muY, _mtX, _mtY);
672  calculatePassingMatrix();
673 }
674 
676 {
677  if (Nu > 3)
678  {
679  solve(Au, Bt, Put);
680  Put = Put.transpose();
681  Ptu = Put.inv();
682  }
683 }
684 
685 /* Passing to tilted ------------------------------------------------------- */
686 void TiltPairAligner::passToTilted(int _muX, int _muY, int &_mtX, int &_mtY)
687 {
688 
689 
690  if (Nu > 3)
691  {
693  VECTOR_R3(m, _muX, _muY, 1);
694  M3x3_BY_V3x1(m, Put, m);
695 
696  _mtX = (int) XX(m);
697  _mtY = (int) YY(m);
698  }
699  else
700  {
701  _mtX = _muX;
702  _mtY = _muY;
703  }
704 
705 }
706 
707 /* Passing to tilted ------------------------------------------------------- */
708 void TiltPairAligner::passToUntilted(int _mtX, int _mtY, int &_muX, int &_muY)
709 {
710  if (Nu > 3)
711  {
713 
714  VECTOR_R3(m, _mtX, _mtY, 1);
715  M3x3_BY_V3x1(m, Ptu, m);
716  _muX = (int) XX(m);
717  _muY = (int) YY(m);
718  }
719  else
720  {
721  _muX = _mtX;
722  _muY = _mtY;
723  }
724 }
725 
726 /* Compute tilting angle --------------------------------------------------- */
728 {
729 constexpr int TRIANGLE_NO = 15000;
730 constexpr int MIN_AREA = 15;
731 constexpr int MAX_AREA = 250000;
732  gamma = 0;
733  Matrix1D<int> iju(2); // From i to j in untilted
734  Matrix1D<int> iku(2); // From i to j in untilted
735  Matrix1D<int> ijt(2); // From i to j in untilted
736  Matrix1D<int> ikt(2); // From i to j in untilted
737  // From i to k in untilted
738  // From i to j in tilted
739  // From i to k in tilted
740  int triang = 0; // Number of triangles considered
741  int i;
742  int j;
743  int k;
744  int counter1;
745  counter1 = 0;
747  long noCombinations;
748  noCombinations = Nu * (Nu - 1) * (Nu - 2) / 6;
749  while (triang < TRIANGLE_NO && counter1 < noCombinations)
750  {
751  counter1++;
752  i = (int)round(rnd_unif(0, Nu - 1));
753  j = (int)round(rnd_unif(0, Nu - 1));
754  k = (int)round(rnd_unif(0, Nu - 1));
755 
756  // Compute area of triangle in untilted micrograph
757  VECTOR_R2(iju, coordU[j] - coordU[i], coordU[j+1] - coordU[i+1]);
758  VECTOR_R2(iku, coordU[k] - coordU[i], coordU[k+1] - coordU[i+1]);
759  double untilted_area = fabs(dotProduct(iju, iku)/*/2*/);
760  if (untilted_area < MIN_AREA
761  )
762  continue; // For numerical stability
763 
764  // Compute area of the same triangle in the tilted micrograph
765  VECTOR_R2(ijt, coordT[j] - coordT[i], coordT[j+1] - coordT[i+1]);
766  VECTOR_R2(ikt, coordT[k] - coordT[i], coordT[k+1] - coordT[i+1]);
767  double tilted_area = fabs(dotProduct(ijt, ikt)/*/2*/);
768  if (tilted_area < MIN_AREA
769  )
770  continue; // For numerical stability
771  if (tilted_area > MAX_AREA
772  )
773  continue; // micrograph are not perfect
774  // sheets so avoid
775  // very far away particles
776 
777  // Now we know that tilted_area=untilted_area*cos(gamma)
778  if (tilted_area > untilted_area)
779  continue; // There are user errors
780  // In the point selection
781  gamma += acos(tilted_area / untilted_area);
782  triang++;
783  }
784  if (0 == triang) {
785  REPORT_ERROR(ERR_NUMERICAL, "triang is zero (0), which would lead to division by zero");
786  }
787  gamma /= triang;
788  gamma = RAD2DEG(gamma);
789  if (triang < 100)
790  std::cout << "Not many particles, tilt angle may not be accurate"
791  << std::endl;
792 }
793 
794 /* Compute alphas ---------------------------------------------------------- */
795 double matrix_fitness(double *p, void *prm)
796 {
797  auto *aligner = (TiltPairAligner *) prm;
798  Euler_angles2matrix(-p[1], p[3], p[2], aligner->pair_E);
799  double retval = 0;
800  for (int i = 0; i < 2; i++)
801  for (int j = 0; j < 2; j++)
802  {
803  double error = fabs(
804  MAT_ELEM(aligner->pair_E,i, j)
805  - MAT_ELEM(aligner->Put, i, j));
806  retval += error * error;
807  }
808  return retval;
809 }
810 
811 
812 void TiltPairAligner::computeAngles(double &ualpha, double &talpha, double &ogamma)
813 {
814  alpha_u = alpha_t = 0;
815  Matrix1D<double> angles(3);
816  angles.initZeros();
817  double fitness;
818  int iter;
819 
820  // Coarse search
821  double *aux = angles.adaptForNumericalRecipes();
822  double best_alpha_u = 0;
823  double best_alpha_t = 0;
824  double best_fit = 1e8;
825  aux[3] = gamma;
826  for (aux[1] = 0; aux[1] < 180; aux[1] += 5)
827  for (aux[2] = 0; aux[2] < 180; aux[2] += 5)
828  {
829  double fit = matrix_fitness(aux, this);
830  if (fit < best_fit)
831  {
832  best_fit = fit;
833  best_alpha_u = aux[1];
834  best_alpha_t = aux[2];
835  }
836  }
838  angles(0) = best_alpha_u;
839  angles(1) = best_alpha_t;
840  angles(2) = gamma;
841 
842  // Fine search
844  steps.initConstant(1);
845  powellOptimizer(angles, 1, 3, &matrix_fitness, this, 0.001, fitness, iter,
846  steps, false);
847  alpha_u = angles(0);
848  alpha_t = angles(1);
849  gamma = angles(2);
850 
851  ualpha = alpha_u;
852  talpha = alpha_t;
853  ogamma = gamma;
854 }
void addCoordinatePair(int _muX, int _muY, int _mtX, int _mtY)
Add coordinates pair.
Definition: micrograph.cpp:622
Index out of bounds.
Definition: xmipp_error.h:132
#define VECTOR_R2(v, x, y)
Definition: matrix1d.h:112
void transform_coordinates(const Matrix2D< double > &M)
Definition: micrograph.cpp:256
int ParticleNo() const
Definition: micrograph.h:188
int * nmax
int Y
Y position.
Definition: micrograph.h:62
Defocus U (Angstroms)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
int scissor(const Particle_coords &P, MultidimArray< double > &result, double Dmin, double Dmax, double scaleX=1, double scaleY=1, bool only_check=false, bool fillBorders=false)
Definition: micrograph.cpp:290
void calculatePassingMatrix()
Calculate passing matrix.
Definition: micrograph.cpp:675
void clear()
Clear set of coordinates.
Definition: micrograph.cpp:608
FileName removeLastExtension() const
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
FileName removeFileFormat() const
void passToUntilted(int _mtX, int _mtY, int &_muX, int &_muY)
Pass to untilted.
Definition: micrograph.cpp:708
void read_coordinates(int label, const FileName &fn_coords)
Definition: micrograph.cpp:221
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
void adjustPassingMatrix(int _muX, int _muY, int _mtX, int _mtY)
Adjust passing matrix.
Definition: micrograph.cpp:668
static double * y
FileName addExtension(const String &ext) const
void write(const FileName &fileName, CastWriteMode castMode=CW_CAST)
Definition: micrograph.cpp:565
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)
std::vector< Particle_coords > coords
Definition: micrograph.h:118
int X
X position.
Definition: micrograph.h:60
void compose(const String &str, const size_t no, const String &ext="")
bool valid
Valid.
Definition: micrograph.h:64
void abs(Image< double > &op)
if read from file original image datatype, this is an struct defined in image
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
void produce_all_images(int label, double minCost, const FileName &fn_root, const FileName &fn_image="", double ang=0, bool rmStack=false, bool fillBorders=false, bool extractNoise=false, int Nnoise=-1)
Definition: micrograph.cpp:322
void powellOptimizer(Matrix1D< double > &p, int i0, int n, double(*f)(double *x, void *), void *prm, double ftol, double &fret, int &iter, const Matrix1D< double > &steps, bool show)
void passToTilted(int _muX, int _muY, int &_mtX, int &_mtY)
Pass to tilted.
Definition: micrograph.cpp:686
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
bool containsLabel(MDLabel label) const override
glob_prnt iter
void invalidate_coord(int n)
Definition: micrograph.cpp:492
TiltPairAligner()
Empty constructor.
Definition: micrograph.cpp:603
virtual IdIteratorProxy< false > ids()
double * gamma
void set_window_size(int _X_window_size, int _Y_window_size)
Definition: micrograph.h:209
double scoreVar
Score by var and Gini.
Definition: micrograph.h:68
doublereal * x
size_t size() const override
#define i
Is this image enabled? (int [-1 or 1])
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
virtual void setComment(const String &newComment="No comment")
void open_micrograph(const FileName &fn_micrograph)
Definition: micrograph.cpp:61
T & getValue(MDLabel label)
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
double rnd_unif()
MultidimArray< T > data
Definition: xmipp_image.h:55
void solve(const Matrix2D< T > &A, const Matrix2D< T > &b, Matrix2D< T > &result)
void computeAngles(double &ualpha, double &talpha, double &ogamma)
Definition: micrograph.cpp:812
void scale_coordinates(const double &c)
Definition: micrograph.cpp:275
#define XX(v)
Definition: matrix1d.h:85
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
< Particle variance (double)
void setMmap(bool mmap)
void clear()
Definition: micrograph.cpp:41
X component (int)
int templateScissor(const Image< T > &I, const Particle_coords &P, MultidimArray< double > &result, double Dmin, double Dmax, double scaleX, double scaleY, bool only_check, bool fillBorders)
Definition: micrograph.h:263
double scoreGini
Score by Gini.
Definition: micrograph.h:70
size_t Zdim
Definition: micrograph.h:114
Error related to numerical calculation.
Definition: xmipp_error.h:179
File or directory does not exist.
Definition: xmipp_error.h:136
size_t Xdim
Definition: micrograph.h:112
void log10(Image< double > &op)
Name of a micrograph (std::string)
void initZeros()
Definition: matrix1d.h:592
#define j
void deleteFile() const
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
void move_last_coord_to(int x, int y)
Definition: micrograph.cpp:516
double steps
#define YY(v)
Definition: matrix1d.h:93
void pixelDesvFilter(MultidimArray< T > &V, double thresFactor)
Definition: filters.h:1378
int label
Label.
Definition: micrograph.h:58
int m
int search_coord_near(int x, int y, int prec=3) const
Definition: micrograph.cpp:479
bool getValue(MDObject &mdValueOut, size_t id) const override
MDRowVec MDMainHeader
void error(char *s)
Definition: tools.cpp:107
void close_micrograph()
Definition: micrograph.cpp:140
int add_coord(int x, int y, int label, double cost)
Definition: micrograph.cpp:501
int round(double x)
Definition: ap.cpp:7245
FileName withoutExtension() const
T dotProduct(const Matrix1D< T > &v1, const Matrix1D< T > &v2)
Definition: matrix1d.h:1140
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
size_t Ndim
Definition: micrograph.h:115
void set_transmitance_flag(bool flag_value)
Definition: micrograph.h:220
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
average value in the micrograph (double)
String getFileFormat() const
double cost
Cost, scaled between 0 and 1.
Definition: micrograph.h:66
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
#define FIRST_IMAGE
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
size_t Ydim
Definition: micrograph.h:113
ProgClassifyCL2D * prm
Y component (int)
CastWriteMode
unsigned int randomize_random_generator()
bool containsLabel(const MDLabel label) const override
Incorrect type received.
Definition: xmipp_error.h:190
bool hasStackExtension() const
void set_inverse_flag(bool flag_value)
Definition: micrograph.h:244
void size(int &_Xdim, int &_Ydim) const
Definition: micrograph.h:530
T * adaptForNumericalRecipes() const
Definition: matrix1d.h:844
int getDatatypeDetph() const
Definition: micrograph.cpp:171
int readMapped(const FileName &name, size_t select_img=ALL_IMAGES, int mode=WRITE_READONLY)
bool setRow(const MDRow &row, size_t id)
void initConstant(T val)
Definition: matrix1d.cpp:83
int * n
Name of an image (std::string)
double fitness(double *p)
void killAdaptationForNumericalRecipes(T *m) const
Definition: matrix1d.h:855
void clear()
Definition: xmipp_image.h:144
void computeGamma()
Compute gamma.
Definition: micrograph.cpp:727
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
void write_coordinates(int label, double minCost, const FileName &fn_coords="")
Definition: micrograph.cpp:197
double matrix_fitness(double *p, void *prm)
Definition: micrograph.cpp:795
void resize(int Xdim, int Ydim, const FileName &filename="")
Set micrograph size (when you do not read the file from disk)
Definition: micrograph.cpp:525