Xmipp  v3.23.11-Nereus
aalign_significant.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Strelak (davidstrelak@gmail.com)
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 "aalign_significant.h"
28 
29 namespace Alignment {
30 
31 template<typename T>
33  addUsageLine("Find alignment of the experimental images in respect to a set of references");
34 
35  addParamsLine(" -i <md_file> : Metadata file with the experimental images");
36  addParamsLine(" -r <md_file> : Metadata file with the reference images");
37  addParamsLine(" -o <md_file> : Resulting metadata file with the aligned images");
38  addParamsLine(" [--thr <N=-1>] : Maximal number of the processing CPU threads");
39  addParamsLine(" [--angDistance <a=10>] : Angular distance");
40  addParamsLine(" [--odir <outputDir=\".\">] : Output directory");
41  addParamsLine(" [--keepBestN <N=1>] : For each image, store N best alignments to references. N must be smaller than no. of references");
42  addParamsLine(" [--allowInputSwap] : Allow swapping reference and experimental images");
43  addParamsLine(" [--useWeightInsteadOfCC] : Select the best reference using weight, instead of CC");
44  addParamsLine(" [--oUpdatedRefs <baseName=\"\">]: Update references using assigned experimental images. Store result here");
45 }
46 
47 template<typename T>
49  m_imagesToAlign.fn = getParam("-i");
50  m_referenceImages.fn = getParam("-r");
51  auto outDir = FileName(getParam("--odir"));
52  if ( ! outDir.exists()) {
53  if (outDir.makePath()) {
54  REPORT_ERROR(ERR_IO_NOWRITE, "cannot create " + outDir);
55  }
56  }
57  m_fnOut = outDir + "/" + std::string(getParam("-o"));
58  m_angDistance = getDoubleParam("--angDistance");
59  m_noOfBestToKeep = getIntParam("--keepBestN");
60  m_allowDataSwap = checkParam("--allowInputSwap");
61  m_useWeightInsteadOfCC = checkParam("--useWeightInsteadOfCC");
62  m_updateHelper.doUpdate = checkParam("--oUpdatedRefs");
63  if (m_updateHelper.doUpdate) {
64  FileName base = outDir + "/" + std::string(getParam("--oUpdatedRefs"));
65  m_updateHelper.fnStk = base + ".stk";
66  m_updateHelper.fnXmd = base + ".xmd";
67  }
68 
69  int threads = getIntParam("--thr");
70  if (-1 == threads) {
71  m_settings.cpuThreads = CPU::findCores();
72  } else {
73  m_settings.cpuThreads = threads;
74  }
75 }
76 
77 template<typename T>
79  if (verbose < 1) return;
80 
81  std::cout << "Input metadata : " << m_imagesToAlign.fn << "\n";
82  std::cout << "Reference metadata : " << m_referenceImages.fn << "\n";
83  std::cout << "Output metadata : " << m_fnOut << "\n";
84  std::cout << "Angular distance : " << m_angDistance << "\n";
85  std::cout << "Best references kept : " << m_noOfBestToKeep << "\n";
86  if (m_updateHelper.doUpdate) {
87  std::cout << "Updated references : " << m_updateHelper.fnXmd << "\n";
88  }
89  std::cout.flush();
90 }
91 
92 template<typename T>
93 template<bool IS_REF>
94 void AProgAlignSignificant<T>::load(DataHelper &h) {
95  MetaDataVec &md = h.md;
96  md.read(h.fn);
97  size_t origN = md.size();
98  md.removeDisabled();
99 
100  size_t Xdim;
101  size_t Ydim;
102  size_t Zdim;
103  size_t Ndim;
104  getImageSize(md, Xdim, Ydim, Zdim, Ndim);
105  Ndim = md.size();
106 
107  if (IS_REF && (origN != Ndim)) {
108  std::cerr << h.fn << " contains disabled images. This is not expected and might lead to wrong result\n";
109  }
110 
111  auto dims = Dimensions(Xdim, Ydim, Zdim, Ndim);
112  auto dimsCropped = Dimensions((Xdim / 2) * 2, (Ydim / 2) * 2, Zdim, Ndim);
113  bool mustCrop = (dims != dimsCropped);
114  h.dims = dimsCropped;
115 
116  // FIXME DS clean up the cropping routine somehow
117  h.data = std::unique_ptr<T[]>(new T[dims.size()]);
118  auto ptr = h.data.get();
119  // routine loading the actual content of the images
120  auto routine = [&dims, ptr]
121  (int thrId, const FileName &fn, size_t storeIndex) {
122  size_t offset = storeIndex * dims.sizeSingle();
123  MultidimArray<T> wrapper(1, dims.z(), dims.y(), dims.x(), ptr + offset);
124  auto img = Image<T>(wrapper);
125  img.read(fn);
126  };
127 
128  std::vector<Image<T>> tmpImages;
129  tmpImages.reserve(m_threadPool.size());
130  if (mustCrop) {
131  std::cerr << "We need an even input (sizes must be multiple of two). Input will be cropped\n";
132  for (size_t t = 0; t < m_threadPool.size(); ++t) {
133  tmpImages.emplace_back(Xdim, Ydim);
134  }
135  }
136  // routine loading the actual content of the images
137  auto routineCrop = [&dims, &dimsCropped, ptr, &tmpImages]
138  (int thrId, const FileName &fn, size_t storeIndex) {
139  // load image
140  tmpImages.at(thrId).read(fn);
141  // copy just the part we're interested in
142  const size_t destOffsetN = storeIndex * dimsCropped.sizeSingle();
143  for (size_t y = 0; y < dimsCropped.y(); ++y) {
144  size_t srcOffsetY = y * dims.x();
145  size_t destOffsetY = y * dimsCropped.x();
146  memcpy(ptr + destOffsetN + destOffsetY,
147  tmpImages.at(thrId).data.data + srcOffsetY,
148  dimsCropped.x() * sizeof(T));
149  }
150  };
151 
152  validate(h, IS_REF);
153 
154  // load all images in parallel
155  auto futures = std::vector<std::future<void>>();
156  futures.reserve(Ndim);
157  if (IS_REF) {
158  if (!md.containsLabel(MDL_ANGLE_ROT)) {
159  std::cerr << "No roration specified for reference images. Using 0 by default\n";
160  h.rots.resize(Ndim, 0); // rotation not specified, use default value
161  } else {
162  h.rots = md.getColumnValues<float>(MDL_ANGLE_ROT);
163  }
164  h.tilts.reserve(Ndim);
165  if (!md.containsLabel(MDL_ANGLE_TILT)) {
166  std::cerr << "No tilt specified for reference images. Using 0 by default\n";
167  h.tilts.resize(Ndim, 0); // tilt not specified, use default value
168  } else {
169  h.tilts = md.getColumnValues<float>(MDL_ANGLE_TILT);
170  }
171  h.indexes = md.getColumnValues<int>(MDL_REF);
172  }
173 
174  auto fileNames = md.getColumnValues<FileName>(MDL_IMAGE);
175  size_t i = 0;
176  for (size_t objId : md.ids()) {
177  FileName fn;
178  if (! IS_REF) {
179  h.rowIds.emplace_back(objId);
180  }
181  if (mustCrop) {
182  futures.emplace_back(m_threadPool.push(routineCrop, fileNames.at(i), i));
183  } else {
184  futures.emplace_back(m_threadPool.push(routine, fileNames.at(i), i));
185  }
186  i++;
187  }
188  // wait till done
189  for (auto &f : futures) {
190  f.get();
191  }
192 }
193 
194 template<typename T>
195 void AProgAlignSignificant<T>::validate(const DataHelper &h, bool isRefData) {
196  if ( ! h.md.containsLabel(MDL_IMAGE)) {
197  REPORT_ERROR(ERR_MD, h.fn + ": does not have MDL_IMAGE label");
198  }
199 
200  if (isRefData && (! h.md.containsLabel(MDL_REF))) {
201  REPORT_ERROR(ERR_MD, h.fn + ": missing MDL_REF label");
202  }
203 }
204 
205 template<typename T>
207  if ( ! m_referenceImages.dims.equalExceptNPadded(m_imagesToAlign.dims)) {
208  REPORT_ERROR(ERR_LOGIC_ERROR, "Dimensions of the images to align and reference images do not match");
209  }
210  if (m_noOfBestToKeep > m_referenceImages.dims.n()) {
211  REPORT_ERROR(ERR_LOGIC_ERROR, "--keepBestN is higher than number of references");
212  }
213  if (m_referenceImages.dims.n() <= 1) {
214  REPORT_ERROR(ERR_LOGIC_ERROR, "We need at least two references");
215  }
216 }
217 
218 template<typename T>
219 template<bool IS_ESTIMATION_TRANSPOSED>
221  const std::vector<AlignmentEstimation> &est) {
222  const size_t noOfRefs = m_referenceImages.dims.n();
223  m_weights.resize(noOfRefs);
224 
225  // for all references
226  for (size_t r = 0; r < noOfRefs; ++r) {
227  computeWeightsAndSave<IS_ESTIMATION_TRANSPOSED>(est, r);
228  }
229 }
230 
231 template<typename T>
232 template<bool IS_ESTIMATION_TRANSPOSED>
234  const std::vector<AlignmentEstimation> &est,
235  size_t refIndex) {
236  const size_t noOfRefs = m_referenceImages.dims.n();
237  const size_t noOfSignals = m_imagesToAlign.dims.n();
238 
239  // compute angle between two reference orientation
240  auto getAngle = [&](size_t index) {
242  m_referenceImages.rots.at(refIndex),
243  m_referenceImages.tilts.at(refIndex),
244  0.f,
245  m_referenceImages.rots.at(index),
246  m_referenceImages.tilts.at(index),
247  0.f,
248  true);
249  };
250 
251  // find out which references are sufficiently similar
252  size_t count = 0;
253  auto mask = std::vector<bool>(noOfRefs, false);
254  for (size_t r = 0; r < noOfRefs; ++r) {
255  if ((refIndex == r)
256  || (getAngle(r) <= m_angDistance)) {
257  mask.at(r) = true;
258  count++;
259  }
260  }
261 
262  // allocate necessary memory
263  auto figsOfMerit = std::vector<WeightCompHelper>();
264  figsOfMerit.reserve(count * noOfSignals);
265 
266  // for all similar references
267  for (size_t r = 0; r < noOfRefs; ++r) {
268  if (mask.at(r)) {
269  // get figure of merit of all signals
270  for (size_t s = 0; s < noOfSignals; ++s) {
271  if (IS_ESTIMATION_TRANSPOSED) {
272  figsOfMerit.emplace_back(est.at(s).figuresOfMerit.at(r), r, s);
273  } else {
274  figsOfMerit.emplace_back(est.at(r).figuresOfMerit.at(s), r, s);
275  }
276  }
277  }
278  }
279  computeWeightsAndSave(figsOfMerit, refIndex);
280 }
281 
282 template<typename T>
284  std::vector<WeightCompHelper> &figsOfMerit,
285  size_t refIndex) {
286  const size_t noOfSignals = m_imagesToAlign.dims.n();
287  auto &weights = m_weights.at(refIndex);
288  weights = std::vector<float>(noOfSignals, 0); // zero weight by default
289  const size_t noOfNumbers = figsOfMerit.size();
290 
291  // sort ascending using figure of merit
292  std::sort(figsOfMerit.begin(), figsOfMerit.end(),
293  [](const WeightCompHelper &l, const WeightCompHelper &r) {
294  return l.merit < r.merit;
295  });
296  auto invMaxMerit = 1.f / figsOfMerit.back().merit;
297 
298  // set weight for all images
299  for (size_t c = 0; c < noOfNumbers; ++c) {
300  const auto &tmp = figsOfMerit.at(c);
301  if (tmp.refIndex != refIndex) {
302  continue; // current record is for different reference
303  }
304  // cumulative density function - probability of having smaller value then the rest
305  float cdf = c / (float)(noOfNumbers - 1); // <0..1> // won't work if we have just one reference
306  float merit = tmp.merit;
307  if (merit > 0.f) {
308  weights.at(tmp.imgIndex) = merit * invMaxMerit * cdf;
309  }
310  }
311 }
312 
313 template<typename T>
315  const Matrix2D<float> &pose,
316  size_t refIndex,
317  double weight,
318  size_t imgIndex) {
319  // get orientation
320  bool flip;
321  float scale;
322  float shiftX;
323  float shiftY;
324  float psi;
326  pose.inv(), // we want to store inverse transform
327  flip, scale,
328  shiftX, shiftY,
329  psi);
330  // FIXME DS add check of max shift / rotation
331  row.setValue(MDL_ENABLED, 1);
332  row.setValue(MDL_ANGLE_ROT, (double)m_referenceImages.rots.at(refIndex));
333  row.setValue(MDL_ANGLE_TILT, (double)m_referenceImages.tilts.at(refIndex));
334  // save both weight and weight significant, so that we can keep track of result of this
335  // program, even after some other program re-weights the particle
336  row.setValue(MDL_WEIGHT_SIGNIFICANT, weight);
337  row.setValue(MDL_WEIGHT, weight);
338  row.setValue(MDL_ANGLE_PSI, (double)psi);
339  row.setValue(MDL_SHIFT_X, (double)-shiftX); // store negative translation
340  row.setValue(MDL_SHIFT_Y, (double)-shiftY); // store negative translation
341  row.setValue(MDL_FLIP, flip);
342  row.setValue(MDL_REF, getRefMetaIndex(refIndex));
343  row.setValue(MDL_IMAGE_IDX, getImgMetaIndex(row, imgIndex));
344 }
345 
346 template<typename T>
348  const Matrix2D<float> &pose,
349  size_t refIndex,
350  double weight,
351  size_t imgIndex,
352  double maxVote) {
353  fillRow(row, pose, refIndex, weight, imgIndex);
354  row.setValue(MDL_MAXCC, (double)maxVote);
355 }
356 
357 template<typename T>
359  std::vector<float> &data,
360  size_t &pos, float &val) {
361  using namespace ExtremaFinder;
362  float p = 0;
363  float v = 0;
364  SingleExtremaFinder<T>::sFindMax(CPU(), Dimensions(data.size()), data.data(), &p, &v);
365  pos = std::round(p);
366  val = data.at(pos);
367  data.at(pos) = std::numeric_limits<float>::lowest();
368 }
369 
370 template<typename T>
371 template<bool IS_ESTIMATION_TRANSPOSED, bool USE_WEIGHT>
373  const std::vector<AlignmentEstimation> &est) {
374  const size_t noOfRefs = m_referenceImages.dims.n();
375  auto accessor = [&](size_t image, size_t reference) {
376  if (USE_WEIGHT) {
377  return m_weights.at(reference).at(image);
378  } else if (IS_ESTIMATION_TRANSPOSED) {
379  return est.at(image).figuresOfMerit.at(reference);
380  } else {
381  return est.at(reference).figuresOfMerit.at(image);
382  }
383  };
384 
385  const size_t noOfImages = m_imagesToAlign.dims.n();
386  m_assignments.reserve(noOfImages * m_noOfBestToKeep);
387  for (size_t i = 0; i < noOfImages; ++i) {
388  // collect voting from all references
389  auto votes = std::vector<float>();
390  votes.reserve(noOfRefs);
391  for (size_t r = 0; r < noOfRefs; ++r) {
392  votes.emplace_back(accessor(i, r));
393  }
394  // for all references that we want to store, starting from the best matching one
395  for (size_t nthBest = 0; nthBest < m_noOfBestToKeep; ++nthBest) {
396  size_t refIndex;
397  float val;
398  // get the max vote
399  extractMax(votes, refIndex, val);
400  if (val <= 0) {
401  continue; // skip saving the particles which have non-positive figure of merit to the reference
402  }
403  const auto &p = IS_ESTIMATION_TRANSPOSED
404  ? est.at(i).poses.at(refIndex).inv()
405  : est.at(refIndex).poses.at(i);
406  m_assignments.emplace_back(refIndex, i,
407  m_weights.at(refIndex).at(i), val,
408  p);
409  }
410  }
411 }
412 
413 template<typename T>
414 template<bool USE_WEIGHT>
416  if (0 == m_assignments.size()) {
417  MetaDataVec().write(m_fnOut);
418  return;
419  }
420 
421  auto &md = m_imagesToAlign.md;
422 
423  std::sort(m_assignments.begin(), m_assignments.end(),
424  [](const Assignment &l, const Assignment &r) {
425  return (l.imgIndex != r.imgIndex)
426  ? (l.imgIndex < r.imgIndex) // sort by image index asc
427  : (USE_WEIGHT // then by voting criteria dest
428  ? (l.weight > r.weight)
429  :(l.merit > r.merit));
430  });
431 
432  std::vector<MDRowVec> rows;
433  size_t indexMeta = 0;
434  size_t indexAssign = 0; // if we're here, we have at least one assignment
435  rows.reserve(m_assignments.size());
436  for (const auto& _row : md) {
437  const auto& row = dynamic_cast<const MDRowVec&>(_row);
438  // we migh have skipped some images due to bad reference
439  if (indexMeta != m_assignments.at(indexAssign).imgIndex) {
440  indexMeta++;
441  continue;
442  }
443  // we found the first row in metadata with image that we have
444  // get the original row from the input metadata
445  auto maxVote = m_assignments.at(indexAssign).merit; // because we sorted it above
446  while (m_assignments.at(indexAssign).imgIndex == indexMeta) {
447  // create new record using the data
448  rows.emplace_back(row);
449  auto &r = rows.back();
450  const auto &a = m_assignments.at(indexAssign);
451  fillRow(r, a.pose, a.refIndex, a.weight, a.imgIndex, maxVote);
452  // continue with next assignment
453  indexAssign++;
454  if (indexAssign == m_assignments.size()) {
455  goto storeData; // we're done here
456  }
457  }
458  indexMeta++;
459  }
460 
461  storeData:
462  const auto labels = rows.at(0).labels();
463  MetaDataVec mdOut(labels);
464  mdOut.addRows(rows);
465  mdOut.write(m_fnOut);
466 }
467 
468 template<typename T>
470  m_settings.refDims = m_referenceImages.dims;
471  m_settings.otherDims = m_imagesToAlign.dims;
472 }
473 
474 template<typename T>
476  const Dimensions &dims = m_referenceImages.dims;
477  const auto &fn = m_updateHelper.fnStk;
478  checkLogDelete(fn);
479  for (size_t n = 0; n < dims.n(); ++n ) {
480  FileName name;
481  // we create a new file, so we start naming from scratch
482  name.compose(n + 1, fn); // within stk file, index images from one (1)
483  size_t offset = n * dims.sizeSingle();
484  MultidimArray<T> wrapper(1, 1, dims.y(), dims.x(), m_referenceImages.data.get() + offset);
485  auto img = Image<T>(wrapper);
486  img.write(name, n, true, WRITE_APPEND);
487  }
488 }
489 
490 template<typename T>
492  const auto &fn = m_updateHelper.fnXmd;
493  checkLogDelete(fn);
494  // write the ref block
495  m_updateHelper.refBlock.write("classes@" + fn, MD_APPEND);
496  // write the per-ref images blocks
497  const size_t noOfBlocks = m_updateHelper.imgBlocks.size();
498  const auto pattern = "class%06d_images@";
499  for (size_t n = 0; n < noOfBlocks; ++n) {
500  const auto &md = m_updateHelper.imgBlocks.at(n);
501  if (0 == md.size()) {
502  continue; // ignore MD for empty references
503  }
504  // block names should be consistent with the original reference index
505  auto blockName = formatString(pattern, getRefMetaIndex(n));
506  md.write(blockName + fn, MD_APPEND);
507  }
508 }
509 
510 template<typename T>
511 void AProgAlignSignificant<T>::updateRefXmd(size_t refIndex, std::vector<Assignment> &images) {
512  static std::mutex mutex;
513  std::lock_guard<std::mutex> lk(mutex); // released at the end of scope
514 
515  const size_t indexInStk = refIndex + 1; // within metadata file, index images from one (1)
516  FileName refName;
517  auto &refMeta = m_updateHelper.refBlock;
518  // name of the reference
519  refName.compose(indexInStk, m_updateHelper.fnStk);
520  // some info about it
521  auto refRow = MDRowVec();
522  assert(std::numeric_limits<int>::max() >= refIndex);
523  refRow.setValue(MDL_REF, getRefMetaIndex(refIndex), true);
524  refRow.setValue(MDL_IMAGE, refName, true);
525  refRow.setValue(MDL_CLASS_COUNT, images.size(), true);
526  refMeta.addRows({refRow});
527 
528  // create image description block
529  std::sort(images.begin(), images.end(), [](const Assignment &l, const Assignment &r) {
530  return l.imgIndex < r.imgIndex; // sort by image index
531  });
532 
533  const size_t noOfImages = images.size();
534  if (0 != noOfImages) {
535  std::vector<MDRowVec> rows(noOfImages);
536  for (size_t i = 0; i < noOfImages; ++i) {
537  auto &row = rows.at(i);
538  const auto &a = images.at(i);
539  getImgRow(row, a.imgIndex);
540  fillRow(row, a.pose, refIndex, a.weight, a.imgIndex);
541  }
542  const auto& labels = rows.at(0).labels();
543  if (0 == m_updateHelper.imgBlocks.size()) {
544  m_updateHelper.imgBlocks.resize(m_referenceImages.dims.n(), labels);
545  }
546  auto &md = m_updateHelper.imgBlocks.at(refIndex);
547  md.addRows(rows);
548  }
549 }
550 
551 template<typename T>
553  if (fn.exists()) {
554  std::cerr << fn << " exists. It will be overwritten.\n";
555  fn.deleteFile(); // since we will append, we need to delete original file
556  }
557 }
558 
559 template<typename T>
561  if (1 < m_noOfBestToKeep) {
562  std::cout << "Each experimental image will contribute to more than one reference image.\n";
563  }
564  // make sure we start from scratch
565  m_updateHelper.imgBlocks.clear(); // postpone allocation for better performance
566  m_updateHelper.refBlock = MetaDataVec();
567  // update references. Metadata will be updated on background
568  updateRefs(m_referenceImages.data.get(), m_imagesToAlign.data.get(), m_assignments);
569  // store result to drive
570  saveRefStk();
571  saveRefXmd();
572 }
573 
574 template<typename T>
576  show();
577  m_threadPool.resize(getSettings().cpuThreads);
578  // load data
579  load<false>(m_imagesToAlign);
580  load<true>(m_referenceImages);
581 
582  bool hasMoreReferences = m_allowDataSwap
583  && (m_referenceImages.dims.n() > m_imagesToAlign.dims.n());
584  if (hasMoreReferences) {
585  std::cerr << "We are swapping reference images and experimental images. "
586  "This will enhance the performance. This might lead to worse results if the experimental "
587  "images are not well centered. Use it with care!\n";
588  std::swap(m_referenceImages, m_imagesToAlign);
589  }
590 
591  // for each reference, get alignment of all images
592  updateSettings();
593  check();
594  auto alignment = align(m_referenceImages.data.get(), m_imagesToAlign.data.get());
595 
596  // process the alignment and store
597  if (hasMoreReferences) {
598  std::swap(m_referenceImages, m_imagesToAlign);
599  computeWeights<true>(alignment);
600  if (m_useWeightInsteadOfCC) {
601  computeAssignment<true, true>(alignment);
602  } else {
603  computeAssignment<true, false>(alignment);
604  }
605  } else {
606  computeWeights<false>(alignment);
607  if (m_useWeightInsteadOfCC) {
608  computeAssignment<false, true>(alignment);
609  } else {
610  computeAssignment<false, false>(alignment);
611  }
612  }
613  // at this moment, we can release some memory
614  m_weights.clear();
615  alignment.clear();
616 
617  if (m_useWeightInsteadOfCC) {
618  storeAlignedImages<true>();
619  } else {
620  storeAlignedImages<false>();
621  }
622 
623  if (m_updateHelper.doUpdate) {
624  updateRefs();
625  }
626 }
627 
628 // explicit instantiation
629 template class AProgAlignSignificant<float>;
630 
631 } /* namespace Alignment */
632 
Mutex mutex
Rotation angle of an image (double,degrees)
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
void transformationMatrix2Parameters2D(const Matrix2D< T > &A, bool &flip, T &scale, T &shiftX, T &shiftY, T &psi)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
doublereal * c
Index of an image within a list (size_t)
Tilting angle of an image (double,degrees)
static double * y
Couldn&#39;t write to file.
Definition: xmipp_error.h:140
Shift for the image in the X axis (double)
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 inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
Special label to be used when gathering MDs in MpiMetadataPrograms.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
static unsigned findCores()
Definition: cpu.h:41
virtual IdIteratorProxy< false > ids()
size_t size() const override
#define i
Is this image enabled? (int [-1 or 1])
virtual void readParams() override
void addRows(const std::vector< MDRowVec > &rows)
CUDA_HD constexpr size_t x() const
Definition: dimensions.h:51
Weight due to Angular significance.
viol index
double * f
Matrix1D< double > psi
CUDA_HD constexpr size_t sizeSingle() const
Definition: dimensions.h:100
Flip the image? (bool)
virtual void defineParams() override
void write(const FileName &fn) const
T Euler_distanceBetweenAngleSets(T rot1, T tilt1, T psi1, T rot2, T tilt2, T psi2, bool only_projdir)
Definition: geometry.cpp:681
void max(Image< double > &op1, const Image< double > &op2)
MetaData error.
Definition: xmipp_error.h:154
virtual void show() const override
CUDA_HD constexpr size_t y() const
Definition: dimensions.h:60
Maximum cross-correlation for the image (double)
bool exists() const
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
CUDA_HD constexpr size_t n() const
Definition: dimensions.h:78
void deleteFile() const
Class to which the image belongs (int)
void getColumnValues(const MDLabel label, std::vector< MDObject > &valuesOut) const override
void setValue(MDLabel label, const T &d, bool addLabel=true)
int round(double x)
Definition: ap.cpp:7245
Number of images assigned to the same class as this image.
T align(T number, uint32_t alignment)
virtual void removeDisabled()
void updateRefXmd(size_t refIndex, std::vector< Assignment > &images)
String formatString(const char *format,...)
Definition: cpu.h:37
Shift for the image in the Y axis (double)
bool containsLabel(const MDLabel label) const override
int * n
Name of an image (std::string)
doublereal * a
< Score 4 for volumes
check(nparam, nf, nfsr, &Linfty, nineq, nineqn, neq, neqn, ncsrl, ncsrn, mode, &modem, eps, bgbnd, param)
Some logical error in the pipeline.
Definition: xmipp_error.h:147