Xmipp  v3.23.11-Nereus
Classes | Namespaces | Macros | Functions | Variables
tomo_align_tilt_series.cpp File Reference
#include <fstream>
#include <queue>
#include "tomo_align_tilt_series.h"
#include "core/metadata_sql.h"
#include "core/xmipp_image.h"
#include "core/transformations.h"
#include "core/utils/memory_utils.h"
#include "data/fourier_filter.h"
#include "data/mask.h"
#include "data/morphology.h"
#include "data/numerical_tools.h"
Include dependency graph for tomo_align_tilt_series.cpp:

Go to the source code of this file.

Classes

class  AffineFitness
 
struct  ThreadComputeTransformParams
 
struct  ThreadGenerateLandmarkSetParams
 

Namespaces

 TomographAlignment
 

Macros

#define DEBUG
 

Functions

void generateMask (const MultidimArray< double > &I, MultidimArray< unsigned char > &mask, int patchSize)
 
void setupAffineFitness (AffineFitness &fitness, const MultidimArray< double > &I1, const MultidimArray< double > &I2, int maxShift, bool isMirror, bool checkRotation, int pyramidLevel)
 
double computeAffineTransformation (const MultidimArray< unsigned char > &I1, const MultidimArray< unsigned char > &I2, int maxShift, int maxIterDE, Matrix2D< double > &A12, Matrix2D< double > &A21, bool show, double thresholdAffine, bool globalAffine, bool isMirror, bool checkRotation, int pyramidLevel)
 
void * threadComputeTransform (void *args)
 
void * threadgenerateLandmarkSetGrid (void *args)
 
void * threadgenerateLandmarkSetBlind (void *args)
 
void * threadgenerateLandmarkSetCriticalPoints (void *args)
 
double wrapperError (double *p, void *prm)
 
std::ostream & operator<< (std::ostream &out, Alignment &alignment)
 

Variables

const ProgTomographAlignmentTomographAlignment::global_prm
 

Macro Definition Documentation

◆ DEBUG

#define DEBUG

Definition at line 2517 of file tomo_align_tilt_series.cpp.

Function Documentation

◆ computeAffineTransformation()

double computeAffineTransformation ( const MultidimArray< unsigned char > &  I1,
const MultidimArray< unsigned char > &  I2,
int  maxShift,
int  maxIterDE,
Matrix2D< double > &  A12,
Matrix2D< double > &  A21,
bool  show,
double  thresholdAffine,
bool  globalAffine,
bool  isMirror,
bool  checkRotation,
int  pyramidLevel 
)

Definition at line 345 of file tomo_align_tilt_series.cpp.

350 {
351  try
352  {
353  AffineFitness affy;
354  MultidimArray<double> I1d, I2d;
355  typeCast(I1, I1d);
356  typeCast(I2, I2d);
357  setupAffineFitness(affy, I1d, I2d, maxShift, isMirror, checkRotation,
358  pyramidLevel);
359 
360  // Return result
361  double cost = 0.0;
362 
363  // Optimize with differential evolution
364  Matrix1D<double> A(6);
365  A(0)=A(3)=1;
366  if (isMirror)
367  A(3)*=-1;
368  if (MAT_XSIZE(A12)==0)
369  {
370  if (globalAffine)
371  {
372  // Exhaustive search
373  double bestCost=2;
374  double stepX=(affy.maxAllowed(4)-affy.minAllowed(4))/40.0;
375  double stepY=(affy.maxAllowed(5)-affy.minAllowed(5))/40.0;
376  for (double shiftY=affy.minAllowed(5); shiftY<=affy.maxAllowed(5); shiftY+=stepY)
377  for (double shiftX=affy.minAllowed(4); shiftX<=affy.maxAllowed(4); shiftX+=stepX)
378  {
379  A(4)=shiftX;
380  A(5)=shiftY;
381  double cost=affy.affine_fitness_individual(MATRIX1D_ARRAY(A));
382  if (cost<bestCost)
383  bestCost=cost;
384  }
385  }
386  else
387  {
388  // Initialize with cross correlation
389  double tx, ty;
390  pthread_mutex_lock( &globalAffineMutex );
391  CorrelationAux aux;
392  if (!isMirror)
393  bestShift(I1d,I2d,tx,ty,aux);
394  else
395  {
396  MultidimArray<double> auxI2d=I2d;
397  auxI2d.selfReverseY();
398  STARTINGX(auxI2d)=STARTINGX(I2d);
399  STARTINGY(auxI2d)=STARTINGY(I2d);
400  bestShift(I1d,auxI2d,tx,ty,aux);
401  ty=-ty;
402  }
403  pthread_mutex_unlock( &globalAffineMutex );
404  A(4)=-tx;
405  A(5)=-ty;
406  }
407 
408  // Optimize with Powell
410  steps.initConstant(1);
411  int iter;
412  powellOptimizer(A, 1, VEC_XSIZE(A),
414  cost, iter, steps, false);
415 
416  // Separate solution
417  A12.initIdentity(3);
418  A12(0,0)=A(0);
419  A12(0,1)=A(1);
420  A12(0,2)=A(4);
421  A12(1,0)=A(2);
422  A12(1,1)=A(3);
423  A12(1,2)=A(5);
424 
425  A21=A12.inv();
426  }
427 
428  if (show)
429  {
430  affy.showMode=true;
431  Matrix1D<double> p(6);
432  p(0)=A12(0,0);
433  p(1)=A12(0,1);
434  p(4)=A12(0,2);
435  p(2)=A12(1,0);
436  p(3)=A12(1,1);
437  p(5)=A12(1,2);
439  affy.showMode=false;
440  }
441 
442  return cost;
443  }
444  catch (XmippError &XE)
445  {
446  std::cout << XE;
447  exit(1);
448  }
449 }
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
Matrix1D< double > minAllowed
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
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)
glob_prnt iter
Matrix1D< double > maxAllowed
#define STARTINGX(v)
static double Powell_affine_fitness_individual(double *p, void *prm)
#define STARTINGY(v)
double affine_fitness_individual(double *p)
void setupAffineFitness(AffineFitness &fitness, const MultidimArray< double > &I1, const MultidimArray< double > &I2, int maxShift, bool isMirror, bool checkRotation, int pyramidLevel)
double steps
#define MATRIX1D_ARRAY(v)
Definition: matrix1d.h:58
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
template float bestShift(MultidimArray< float > &, float &, float &, const MultidimArray< int > *, int)
void initIdentity()
Definition: matrix2d.h:673

◆ generateMask()

void generateMask ( const MultidimArray< double > &  I,
MultidimArray< unsigned char > &  mask,
int  patchSize 
)

Definition at line 40 of file tomo_align_tilt_series.cpp.

42 {
44  dmask.initZeros(I);
46  if (I(i,j)!=0)
47  dmask(i,j)=1;
48 
49  MultidimArray<double> maskEroded;
50  maskEroded.initZeros(dmask);
51  erode2D(dmask,maskEroded,8,0,patchSize);
52  typeCast(maskEroded,mask);
53  mask.setXmippOrigin();
54 
55 #ifdef DEBUG
56 
57  ImageXmipp save;
58  save()=I;
59  save.write("PPP.xmp");
60  save()=maskEroded;
61  save.write("PPPmask.xmp");
62  std::cout << "Masks saved. Press any key\n";
63  char c;
64  std::cin >> c;
65 #endif
66 }
doublereal * c
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void erode2D(const MultidimArray< double > &in, MultidimArray< double > &out, int neig, int count, int size)
Definition: morphology.cpp:116
void write(const FileName &fn) const
#define j
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
void initZeros(const MultidimArray< T1 > &op)

◆ operator<<()

std::ostream& operator<< ( std::ostream &  out,
Alignment alignment 
)

Print an alignment

Definition at line 2879 of file tomo_align_tilt_series.cpp.

2880 {
2881  out << "Alignment parameters ===========================================\n"
2882  << "rot=" << alignment.rot << " tilt=" << alignment.tilt << std::endl
2883  << "raxis=" << alignment.raxis.transpose() << std::endl;
2884  out << "Images ---------------------------------------------------------\n";
2885  for (int i=0; i<alignment.Nimg; i++)
2886  out << "Image " << i << " psi= " << alignment.psi(i)
2887  << " di= " << alignment.di[i].transpose()
2888  << " diaxis= " << alignment.diaxis[i].transpose()
2889  << " (" << alignment.prm->ni(i) << ")\n";
2890  out << "Landmarks ------------------------------------------------------\n";
2891  alignment.computeErrorForLandmarks();
2892  for (int j=0; j<alignment.Nlandmark; j++)
2893  out << "Landmark " << j << " rj= " << alignment.rj[j].transpose()
2894  << " " << alignment.errorLandmark(j) << std::endl;
2895  return out;
2896 }
std::vector< Matrix1D< double > > di
const ProgTomographAlignment * prm
std::vector< Matrix1D< double > > rj
MultidimArray< double > errorLandmark
#define i
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
std::vector< Matrix1D< double > > diaxis
Matrix1D< double > psi
#define j
Matrix1D< double > raxis

◆ setupAffineFitness()

void setupAffineFitness ( AffineFitness fitness,
const MultidimArray< double > &  I1,
const MultidimArray< double > &  I2,
int  maxShift,
bool  isMirror,
bool  checkRotation,
int  pyramidLevel 
)

Definition at line 251 of file tomo_align_tilt_series.cpp.

254 {
255  fitness.checkRotation=checkRotation;
256 
257  // Set images
258  int level=0;
259  MultidimArray<double> I1aux=I1;
260  MultidimArray<double> I2aux=I2;
261 
262  // Remove the borders
263  int borderY=CEIL(0.1*YSIZE(I1));
264  int borderX=CEIL(0.1*XSIZE(I1));
265  I1aux.selfWindow(STARTINGY(I1)+borderY,STARTINGX(I1)+borderX,
266  FINISHINGY(I1)-borderY,FINISHINGX(I1)-borderX);
267  I2aux.selfWindow(STARTINGY(I1)+borderY,STARTINGX(I1)+borderX,
268  FINISHINGY(I1)-borderY,FINISHINGX(I1)-borderX);
269 
270  MultidimArray<double> Mask1;
271  Mask1.initZeros(I1aux);
273  if (A2D_ELEM(I1,i,j)!=0)
274  A2D_ELEM(Mask1,i,j)=1;
275 
276  MultidimArray<double> Mask2;
277  Mask2.initZeros(I2aux);
279  if (A2D_ELEM(I2,i,j)!=0)
280  A2D_ELEM(Mask2,i,j)=1;
281 
282  do
283  {
284  // Push back the current images
285  I1aux.setXmippOrigin();
286  I2aux.setXmippOrigin();
287  Mask1.setXmippOrigin();
288  Mask2.setXmippOrigin();
289 
290  MultidimArray<double> *dummy=nullptr;
291  dummy=new MultidimArray<double>;
292  *dummy=I1aux;
293  fitness.I1.push_back(dummy);
294  dummy=new MultidimArray<double>;
295  *dummy=I2aux;
296  fitness.I2.push_back(dummy);
297  dummy=new MultidimArray<double>;
298  *dummy=Mask1;
299  fitness.Mask1.push_back(dummy);
300  dummy=new MultidimArray<double>;
301  *dummy=Mask2;
302  fitness.Mask2.push_back(dummy);
303 
304  // Prepare for next level
305  level++;
306  if (pyramidLevel>=level)
307  {
308  selfScaleToSize(xmipp_transformation::LINEAR,I1aux,YSIZE(I1aux)/2,XSIZE(I1aux)/2);
309  selfScaleToSize(xmipp_transformation::LINEAR,I2aux,YSIZE(I2aux)/2,XSIZE(I2aux)/2);
310  selfScaleToSize(xmipp_transformation::LINEAR,Mask1,YSIZE(Mask1)/2,XSIZE(Mask1)/2);
311  selfScaleToSize(xmipp_transformation::LINEAR,Mask2,YSIZE(Mask2)/2,XSIZE(Mask2)/2);
313  Mask1(i,j)=(Mask1(i,j)>0.5)? 1:0;
315  Mask2(i,j)=(Mask2(i,j)>0.5)? 1:0;
316  }
317  }
318  while (level<=pyramidLevel);
319 
320  // Set limits for the affine matrices
321  // Order: 1->2: 4 affine params+2 translations
322  // Order: 2->1: 4 affine params+2 translations
323  fitness.minAllowed.resize(6);
324  fitness.maxAllowed.resize(6);
325 
326  // Scale factors
327  fitness.minAllowed(0)=fitness.minAllowed(3)=0.9;
328  fitness.maxAllowed(0)=fitness.maxAllowed(3)=1.1;
329  if (isMirror)
330  {
331  fitness.minAllowed(3)=-1.1;
332  fitness.maxAllowed(3)=-0.9;
333  }
334 
335  // Rotation factors
336  fitness.minAllowed(1)=fitness.minAllowed(2)=-0.2;
337  fitness.maxAllowed(1)=fitness.maxAllowed(2)= 0.2;
338 
339  // Shifts
340  fitness.minAllowed(4)=fitness.minAllowed(5)=-maxShift;
341  fitness.maxAllowed(4)=fitness.maxAllowed(5)= maxShift;
342 }
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
#define FINISHINGX(v)
std::vector< MultidimArray< double > * > Mask2
Matrix1D< double > minAllowed
Matrix1D< double > maxAllowed
#define STARTINGX(v)
#define i
void selfScaleToSize(int SplineDegree, MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
#define STARTINGY(v)
std::vector< MultidimArray< double > * > I2
#define CEIL(x)
Definition: xmipp_macros.h:225
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
std::vector< MultidimArray< double > * > Mask1
double dummy
std::vector< MultidimArray< double > * > I1
#define j
#define FINISHINGY(v)
void initZeros(const MultidimArray< T1 > &op)

◆ threadComputeTransform()

void* threadComputeTransform ( void *  args)

Definition at line 584 of file tomo_align_tilt_series.cpp.

585 {
586  auto * master =
588 
589  ProgTomographAlignment * parent = master->parent;
590  int thread_id = master->myThreadID;
591  int localnumThreads = parent->numThreads;
592  bool isCapillar = parent->isCapillar;
593  int Nimg = parent->Nimg;
594  double maxShiftPercentage = parent->maxShiftPercentage;
595  int maxIterDE = parent->maxIterDE;
596  bool showAffine = parent->showAffine;
597  double thresholdAffine = parent->thresholdAffine;
598  std::vector < MultidimArray<unsigned char> *> & img = parent->img;
599  std::vector< std::vector< Matrix2D<double> > > & affineTransformations = parent->affineTransformations;
600  double globalAffine = parent->globalAffine;
601 
602  int maxShift=FLOOR(XSIZE(*img[0])*maxShiftPercentage);
603  int initjj=1;
604  if (isCapillar)
605  initjj=0;
606 
607  initjj += thread_id;
608 
609  double cost;
610  for (int jj=initjj; jj<Nimg; jj+= localnumThreads)
611  {
612  int jj_1;
613  if (isCapillar)
614  jj_1=intWRAP(jj-1,0,Nimg-1);
615  else
616  jj_1=jj-1;
617  MultidimArray<unsigned char>& img_i=*img[jj_1];
618  MultidimArray<unsigned char>& img_j=*img[jj];
619  bool isMirror=(jj==0) && (jj_1==Nimg-1);
620 
621  if (MAT_XSIZE(affineTransformations[jj_1][jj])==0)
622  {
623  Matrix2D<double> Aij, Aji;
624  cost = computeAffineTransformation(img_i, img_j, maxShift,
625  maxIterDE, Aij, Aji,
626  showAffine, thresholdAffine, globalAffine,
627  isMirror,true, parent->pyramidLevel);
628  parent->correlationList[jj]=1-cost;
629 
630  pthread_mutex_lock( &printingMutex );
631  affineTransformations[jj_1][jj]=Aij;
632  affineTransformations[jj][jj_1]=Aji;
633  if (cost<1)
634  parent->writeTransformations(
635  parent->fnRoot+"_transformations.txt");
636  std::cout << "Cost for [" << jj_1 << "] - ["
637  << jj << "] = " << cost << std::endl;
638  parent->iteration++;
639  pthread_mutex_unlock( &printingMutex );
640  }
641  else
642  {
643  Matrix2D<double> Aij;
644  Aij=affineTransformations[jj_1][jj];
645 
646  MultidimArray<double> img_id, img_jd;
647  typeCast(img_i, img_id);
648  typeCast(img_j, img_jd);
649 
651  setupAffineFitness(fitness, img_id, img_jd, maxShift, isMirror,
652  false, parent->pyramidLevel);
653  Matrix1D<double> p(6);
654  p(0)=Aij(0,0);
655  p(1)=Aij(0,1);
656  p(4)=Aij(0,2);
657  p(2)=Aij(1,0);
658  p(3)=Aij(1,1);
659  p(5)=Aij(1,2);
660  cost = fitness.affine_fitness_individual(MATRIX1D_ARRAY(p));
661  parent->correlationList[jj]=1-cost;
662 
663  pthread_mutex_lock( &printingMutex );
664  std::cout << "Cost for [" << jj_1 << "] - ["
665  << jj << "] = " << cost << std::endl;
666  pthread_mutex_unlock( &printingMutex );
667  parent->iteration++;
668  }
669  }
670 
671  return nullptr;
672 }
bool globalAffine
Look for local affine transformation.
double maxShiftPercentage
Maxshift percentage.
int maxIterDE
Maximum number of iterations in Differential Evolution.
FileName fnRoot
Output root.
#define FLOOR(x)
Definition: xmipp_macros.h:240
int numThreads
Number of threads to use for parallel computing.
#define XSIZE(v)
double thresholdAffine
Threshold affine.
double affine_fitness_individual(double *p)
double computeAffineTransformation(const MultidimArray< unsigned char > &I1, const MultidimArray< unsigned char > &I2, int maxShift, int maxIterDE, Matrix2D< double > &A12, Matrix2D< double > &A21, bool show, double thresholdAffine, bool globalAffine, bool isMirror, bool checkRotation, int pyramidLevel)
void setupAffineFitness(AffineFitness &fitness, const MultidimArray< double > &I1, const MultidimArray< double > &I2, int maxShift, bool isMirror, bool checkRotation, int pyramidLevel)
std::vector< MultidimArray< unsigned char > * > img
std::vector< std::vector< Matrix2D< double > > > affineTransformations
#define MATRIX1D_ARRAY(v)
Definition: matrix1d.h:58
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
bool isCapillar
This tilt series comes from a capillar.
void writeTransformations(const FileName &fnTransformations) const
Write affine transformations.
bool showAffine
Show affine transformations.
double fitness(double *p)
std::vector< double > correlationList
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272

◆ threadgenerateLandmarkSetBlind()

void* threadgenerateLandmarkSetBlind ( void *  args)

Definition at line 1216 of file tomo_align_tilt_series.cpp.

1217 {
1218  auto * master =
1220  ProgTomographAlignment * parent = master->parent;
1221  int thread_id = master->myThreadID;
1222  int Nimg=parent->Nimg;
1223  int numThreads=parent->numThreads;
1224  const std::vector< std::vector< Matrix2D<double> > > &affineTransformations=
1225  parent->affineTransformations;
1226  int gridSamples=parent->gridSamples;
1227 
1228  auto deltaShift=(int)floor(XSIZE(*(parent->img)[0])/gridSamples);
1229  master->chainList=new std::vector<LandmarkChain>;
1230  Matrix1D<double> rii(3), rjj(3);
1231  ZZ(rii)=1;
1232  ZZ(rjj)=1;
1233  if (thread_id==0)
1234  init_progress_bar(gridSamples);
1235  int includedPoints=0;
1236  int maxSideLength=(parent->blindSeqLength-1)/2;
1237  for (int nx=thread_id; nx<gridSamples; nx+=numThreads)
1238  {
1239  XX(rii)=STARTINGX(*(parent->img)[0])+ROUND(deltaShift*(0.5+nx));
1240  for (int ny=0; ny<gridSamples; ny+=1)
1241  {
1242  YY(rii)=STARTINGY(*(parent->img)[0])+ROUND(deltaShift*(0.5+ny));
1243  for (int ii=0; ii<=Nimg-1; ++ii)
1244  {
1245  // Check if inside the mask
1246  if (!(*(parent->maskImg[ii]))((int)YY(rii),(int)XX(rii)))
1247  continue;
1248  if (parent->isOutlier(ii))
1249  continue;
1250 
1251  LandmarkChain chain;
1252  chain.clear();
1253  Landmark l;
1254  l.x=XX(rii);
1255  l.y=YY(rii);
1256  l.imgIdx=ii;
1257  chain.push_back(l);
1258 
1259  // Follow this landmark backwards
1260  bool acceptLandmark=true;
1261  int jj;
1262  int sideLength=0;
1263  if (parent->isCapillar)
1264  jj=intWRAP(ii-1,0,Nimg-1);
1265  else
1266  jj=ii-1;
1267  Matrix2D<double> Aij, Aji;
1268  Matrix1D<double> rcurrent=rii;
1269  while (jj>=0 && acceptLandmark && sideLength<maxSideLength &&
1270  !parent->isOutlier(jj))
1271  {
1272  // Compute the affine transformation between ii and jj
1273  int jj_1;
1274  if (parent->isCapillar)
1275  jj_1=intWRAP(jj+1,0,Nimg-1);
1276  else
1277  jj_1=jj+1;
1278  Aij=affineTransformations[jj][jj_1];
1279  Aji=affineTransformations[jj_1][jj];
1280  rjj=Aji*rcurrent;
1281  auto iYYrjj=(int)YY(rjj);
1282  auto iXXrjj=(int)XX(rjj);
1283  if (!(*(parent->maskImg[jj])).outside(iYYrjj,iXXrjj))
1284  acceptLandmark=(*(parent->maskImg[jj]))(iYYrjj,iXXrjj);
1285  else
1286  acceptLandmark=false;
1287  if (acceptLandmark)
1288  {
1289  l.x=XX(rjj);
1290  l.y=YY(rjj);
1291  l.imgIdx=jj;
1292  chain.push_back(l);
1293  if (parent->isCapillar)
1294  jj=intWRAP(jj-1,0,Nimg-1);
1295  else
1296  jj=jj-1;
1297  rcurrent=rjj;
1298  sideLength++;
1299  }
1300  }
1301 
1302  // Follow this landmark forward
1303  acceptLandmark=true;
1304  if (parent->isCapillar)
1305  jj=intWRAP(ii+1,0,Nimg-1);
1306  else
1307  jj=ii+1;
1308  rcurrent=rii;
1309  sideLength=0;
1310  while (jj<Nimg && acceptLandmark && sideLength<maxSideLength &&
1311  !parent->isOutlier(jj))
1312  {
1313  // Compute the affine transformation between ii and jj
1314  int jj_1;
1315  if (parent->isCapillar)
1316  jj_1=intWRAP(jj-1,0,Nimg-1);
1317  else
1318  jj_1=jj-1;
1319  Aij=affineTransformations[jj_1][jj];
1320  Aji=affineTransformations[jj][jj_1];
1321  rjj=Aij*rcurrent;
1322  auto iYYrjj=(int)YY(rjj);
1323  auto iXXrjj=(int)XX(rjj);
1324  if (!(*(parent->maskImg[jj])).outside(iYYrjj,iXXrjj))
1325  acceptLandmark=(*(parent->maskImg[jj]))(iYYrjj,iXXrjj);
1326  else
1327  acceptLandmark=false;
1328  if (acceptLandmark)
1329  {
1330  l.x=XX(rjj);
1331  l.y=YY(rjj);
1332  l.imgIdx=jj;
1333  chain.push_back(l);
1334  if (parent->isCapillar)
1335  jj=intWRAP(jj+1,0,Nimg-1);
1336  else
1337  jj=jj+1;
1338  rcurrent=rjj;
1339  sideLength++;
1340  }
1341  }
1342 
1343 #ifdef DEBUG
1344  std::cout << "img=" << ii << " chain length="
1345  << chain.size() << " [" << jjleft
1346  << " - " << jjright << "]\n";
1347 #endif
1348 
1349  master->chainList->push_back(chain);
1350  includedPoints+=chain.size();
1351  }
1352 #ifdef DEBUG
1353  std::cout << "Point nx=" << nx << " ny=" << ny
1354  << " Number of points="
1355  << includedPoints
1356  << " Number of chains=" << master->chainList->size()
1357  << " ( " << ((double) includedPoints)/
1358  master->chainList->size() << " )\n";
1359 #endif
1360 
1361  }
1362  if (thread_id==0)
1363  progress_bar(nx);
1364  }
1365  if (thread_id==0)
1366  progress_bar(gridSamples);
1367  return nullptr;
1368 }
void init_progress_bar(long total)
__host__ __device__ float2 floor(const float2 v)
std::vector< MultidimArray< unsigned char > * > maskImg
#define STARTINGX(v)
#define STARTINGY(v)
#define XX(v)
Definition: matrix1d.h:85
int numThreads
Number of threads to use for parallel computing.
std::vector< Landmark > LandmarkChain
#define XSIZE(v)
void progress_bar(long rlen)
#define ROUND(x)
Definition: xmipp_macros.h:210
std::vector< MultidimArray< unsigned char > * > img
#define YY(v)
Definition: matrix1d.h:93
std::vector< std::vector< Matrix2D< double > > > affineTransformations
bool isCapillar
This tilt series comes from a capillar.
#define ZZ(v)
Definition: matrix1d.h:101
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272

◆ threadgenerateLandmarkSetCriticalPoints()

void* threadgenerateLandmarkSetCriticalPoints ( void *  args)

Definition at line 1371 of file tomo_align_tilt_series.cpp.

1372 {
1373  auto * master =
1375  ProgTomographAlignment * parent = master->parent;
1376  int thread_id = master->myThreadID;
1377  int Nimg=parent->Nimg;
1378  int numThreads=parent->numThreads;
1379  const std::vector< std::vector< Matrix2D<double> > > &affineTransformations=
1380  parent->affineTransformations;
1381 
1382  master->chainList=new std::vector<LandmarkChain>;
1383  std::vector<LandmarkChain> candidateChainList;
1384  if (thread_id==0)
1385  init_progress_bar(Nimg);
1386  int halfSeqLength=parent->seqLength/2;
1387 
1388  // Design a mask for the dilation
1389  int radius=4;
1390  MultidimArray<int> mask;
1391  mask.resize(2*radius+1,2*radius+1);
1392  mask.setXmippOrigin();
1394 
1395  Image<double> I;
1396  for (int ii=thread_id; ii<=Nimg-1; ii+=numThreads)
1397  {
1398  if (parent->isOutlier(ii))
1399  continue;
1400  I.read(parent->name_list[ii]);
1401 
1402  // Generate mask
1403  MultidimArray<unsigned char> largeMask;
1404  generateMask(I(),largeMask,
1405  XMIPP_MAX(ROUND(parent->localSize*XSIZE(I()))/2,5));
1406 
1407  // Filter the image
1408  MultidimArray<double> Ifiltered;
1409  Ifiltered=I();
1410  Ifiltered.setXmippOrigin();
1411  FourierFilter FilterBP;
1412  FilterBP.FilterBand=BANDPASS;
1413  FilterBP.w1=2.0/XSIZE(Ifiltered);
1414  FilterBP.w2=128.0/XSIZE(Ifiltered);
1415  FilterBP.raised_w=1.0/XSIZE(Ifiltered);
1416  ;
1417  FilterBP.generateMask(Ifiltered);
1418  FilterBP.applyMaskSpace(Ifiltered);
1419 
1420  // Identify low valued points and perform dilation
1421  MultidimArray<double> Iaux=Ifiltered;
1422  Iaux.selfWindow(
1423  -ROUND(0.45*YSIZE(Ifiltered)),-ROUND(0.45*XSIZE(Ifiltered)),
1424  ROUND(0.45*YSIZE(Ifiltered)), ROUND(0.45*XSIZE(Ifiltered)));
1425  Histogram1D hist;
1426  compute_hist(Iaux, hist, 400);
1427  double th=hist.percentil(2);
1428  std::vector< Matrix1D<double> > Q;
1430  if (Ifiltered(i,j)<th && largeMask(i,j))
1431  {
1432  // Check if it is a local minimum
1433  bool localMinimum=true;
1434  int x0=j;
1435  int y0=i;
1437  {
1438  int x=x0+j;
1439  int y=y0+i;
1440  if (x>=STARTINGX(Iaux) && x<=FINISHINGX(Iaux) &&
1441  y>=STARTINGY(Iaux) && y<=FINISHINGY(Iaux))
1442  if (A2D_ELEM(Iaux,y,x)<A2D_ELEM(Iaux,y0,x0))
1443  {
1444  localMinimum=false;
1445  break;
1446  }
1447  }
1448  if (localMinimum)
1449  Q.push_back(vectorR2(x0,y0));
1450  }
1451 
1452  // Check that the list is not too long
1453  if (Q.size()>10*parent->Ncritical)
1454  {
1455  size_t qmax=Q.size();
1456  MultidimArray<double> minDistance;
1457  minDistance.resize(qmax);
1458  minDistance.initConstant(1e20);
1459  for (size_t q1=0; q1<qmax; q1++)
1460  for (size_t q2=q1+1; q2< qmax; q2++)
1461  {
1462  double diffX=XX(Q[q1])-XX(Q[q2]);
1463  double diffY=YY(Q[q1])-YY(Q[q2]);
1464  double d12=diffX*diffX+diffY*diffY;
1465  if (d12<minDistance(q1))
1466  minDistance(q1)=d12;
1467  if (d12<minDistance(q2))
1468  minDistance(q2)=d12;
1469  }
1470  MultidimArray<int> idxDistanceSort;
1471  minDistance.indexSort(idxDistanceSort);
1472  std::vector< Matrix1D<double> > Qaux;
1473  int qlimit=XMIPP_MIN(10*(parent->Ncritical),qmax);
1474  for (int q=0; q<qlimit; q++)
1475  Qaux.push_back(Q[idxDistanceSort(qmax-1-q)-1]);
1476  Q.clear();
1477  Q=Qaux;
1478  }
1479 
1480  int qmax=Q.size();
1481  Matrix1D<double> rii(3), rjj(3);
1482  ZZ(rii)=1;
1483  ZZ(rjj)=1;
1484  MultidimArray<double> corrQ;
1485  corrQ.initZeros(qmax);
1486  for (int q=0; q<qmax; q++)
1487  {
1488  XX(rii)=XX(Q[q]);
1489  YY(rii)=YY(Q[q]);
1490 
1491  // Initiate a chain here
1492  LandmarkChain chain;
1493  chain.clear();
1494  Landmark l;
1495  l.x=XX(rii);
1496  l.y=YY(rii);
1497  l.imgIdx=ii;
1498  chain.push_back(l);
1499 
1500  // Follow this landmark backwards
1501  int jjmin=XMIPP_MAX(0,ii-halfSeqLength);
1502  int jjmax=ii-1;
1503  Matrix2D<double> Aij, Aji;
1504  Matrix1D<double> rcurrent=rii;
1505  for (int jj=jjmax; jj>=jjmin; --jj)
1506  {
1507  if (parent->isOutlier(jj))
1508  break;
1509 
1510  // Compute the affine transformation between jj and jj+1
1511  int jj_1=jj+1;
1512  Aij=affineTransformations[jj][jj_1];
1513  Aji=affineTransformations[jj_1][jj];
1514  rjj=Aji*rcurrent;
1515  double corr;
1516  parent->refineLandmark(jj_1,jj,rcurrent,rjj, corr,true);
1517  l.x=XX(rjj);
1518  l.y=YY(rjj);
1519  l.imgIdx=jj;
1520  chain.push_back(l);
1521  rcurrent=rjj;
1522  }
1523 
1524  // Follow this landmark forwards
1525  jjmin=ii+1;
1526  jjmax=XMIPP_MIN(Nimg-1,ii+halfSeqLength);
1527  rcurrent=rii;
1528  for (int jj=jjmin; jj<=jjmax; ++jj)
1529  {
1530  if (parent->isOutlier(jj))
1531  break;
1532 
1533  // Compute the affine transformation between jj-1 and jj
1534  int jj_1=jj-1;
1535  Aij=affineTransformations[jj_1][jj];
1536  Aji=affineTransformations[jj][jj_1];
1537  rjj=Aij*rcurrent;
1538  double corr;
1539  parent->refineLandmark(jj_1,jj,rcurrent,rjj,corr,true);
1540  l.x=XX(rjj);
1541  l.y=YY(rjj);
1542  l.imgIdx=jj;
1543  chain.push_back(l);
1544  rcurrent=rjj;
1545  }
1546 
1547  // Refine chain
1548  parent->refineChain(chain,corrQ(q));
1549  candidateChainList.push_back(chain);
1550  }
1551  if (thread_id==0)
1552  progress_bar(ii);
1553 
1554  // Sort all chains according to its correlation
1555  MultidimArray<int> idx;
1556  corrQ.indexSort(idx);
1557  int imax=XMIPP_MIN(XSIZE(idx),parent->Ncritical);
1558  for (int iq=0; iq<imax; iq++)
1559  {
1560  int q=idx(XSIZE(idx)-1-iq)-1;
1561  if (corrQ(q)>0.5)
1562  {
1563  master->chainList->push_back(candidateChainList[q]);
1564 #ifdef DEBUG
1565 
1566  std::cout << "Corr " << iq << ": " << corrQ(q) << ":";
1567  for (int i=0; i<candidateChainList[q].size(); i++)
1568  std::cout << candidateChainList[q][i].imgIdx << " ";
1569  std::cout << std::endl;
1570 #endif
1571 
1572  }
1573  else
1574  std::cout << "It's recommended to reduce the number of critical points\n";
1575  }
1576  candidateChainList.clear();
1577 
1578 #ifdef DEBUG
1579 
1580  Image<double> save;
1581  typeCast(*(parent->img[ii]),save());
1582  save.write("PPPoriginal.xmp");
1583  save()=Ifiltered;
1584  save.write("PPPfiltered.xmp");
1585  double minval=Ifiltered.computeMin();
1586  FOR_ALL_ELEMENTS_IN_MATRIX2D(Ifiltered)
1587  if (Ifiltered(i,j)>=th || !largeMask(i,j))
1588  save(i,j)=th;
1589  for (int q=0; q<Q.size(); q++)
1591  if (YY(Q[q])+i>=STARTINGY(Ifiltered) && YY(Q[q])+i<=FINISHINGY(Ifiltered) &&
1592  XX(Q[q])+j>=STARTINGX(Ifiltered) && XX(Q[q])+j<=FINISHINGX(Ifiltered))
1593  save(YY(Q[q])+i,XX(Q[q])+j)=minval;
1594  imax=XMIPP_MIN(XSIZE(idx),parent->Ncritical);
1595  for (int iq=0; iq<imax; iq++)
1596  {
1597  int q=idx(XSIZE(idx)-1-iq)-1;
1599  if (YY(Q[q])+i>=STARTINGY(Ifiltered) && YY(Q[q])+i<=FINISHINGY(Ifiltered) &&
1600  XX(Q[q])+j>=STARTINGX(Ifiltered) && XX(Q[q])+j<=FINISHINGX(Ifiltered))
1601  save(YY(Q[q])+i,XX(Q[q])+j)=(minval+th)/2;
1602  }
1603 
1604  save.write("PPPcritical.xmp");
1605  std::cout << "Number of critical points=" << Q.size() << std::endl;
1606  std::cout << "CorrQ stats:";
1607  corrQ.printStats();
1608  std::cout << std::endl;
1609  std::cout << "Press any key\n";
1610  char c;
1611  std::cin >> c;
1612 #endif
1613 
1614  }
1615  if (thread_id==0)
1616  progress_bar(Nimg);
1617  return nullptr;
1618 }
#define FOR_ALL_ELEMENTS_IN_MATRIX2D(m)
Definition: matrix2d.h:104
void init_progress_bar(long total)
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
bool refineLandmark(int ii, int jj, const Matrix1D< double > &rii, Matrix1D< double > &rjj, double &maxCorr, bool tryFourier) const
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
#define FINISHINGX(v)
size_t seqLength
Sequence Length.
doublereal * c
void generateMask(const MultidimArray< double > &I, MultidimArray< unsigned char > &mask, int patchSize)
void BinaryCircularMask(MultidimArray< int > &mask, double radius, int mode, double x0, double y0, double z0)
Definition: mask.cpp:193
static double * y
#define BANDPASS
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)
void initConstant(T val)
double percentil(double percent_mass)
Definition: histogram.cpp:160
#define q1
#define STARTINGX(v)
bool refineChain(LandmarkChain &chain, double &corrChain)
doublereal * x
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
size_t Ncritical
Number of critical points.
std::vector< std::string > name_list
#define STARTINGY(v)
T computeMin() const
#define y0
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
Definition: histogram.cpp:572
#define x0
#define XX(v)
Definition: matrix1d.h:85
int numThreads
Number of threads to use for parallel computing.
std::vector< Landmark > LandmarkChain
#define XSIZE(v)
void progress_bar(long rlen)
#define ROUND(x)
Definition: xmipp_macros.h:210
Matrix1D< double > vectorR2(double x, double y)
Definition: matrix1d.cpp:884
void printStats(std::ostream &out=std::cout) const
std::vector< MultidimArray< unsigned char > * > img
#define q2
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
#define YY(v)
Definition: matrix1d.h:93
std::vector< std::vector< Matrix2D< double > > > affineTransformations
double localSize
Local refinement size.
#define FINISHINGY(v)
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
constexpr int OUTSIDE_MASK
Definition: mask.h:48
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
void initZeros(const MultidimArray< T1 > &op)
void generateMask(MultidimArray< double > &v)
#define ZZ(v)
Definition: matrix1d.h:101
void indexSort(MultidimArray< int > &indx) const
void applyMaskSpace(MultidimArray< double > &v)

◆ threadgenerateLandmarkSetGrid()

void* threadgenerateLandmarkSetGrid ( void *  args)

Definition at line 1047 of file tomo_align_tilt_series.cpp.

1048 {
1049  auto * master =
1051  ProgTomographAlignment * parent = master->parent;
1052  int thread_id = master->myThreadID;
1053  int Nimg=parent->Nimg;
1054  int numThreads=parent->numThreads;
1055  const std::vector< std::vector< Matrix2D<double> > > &affineTransformations=
1056  parent->affineTransformations;
1057  int gridSamples=parent->gridSamples;
1058 
1059  auto deltaShift=(int)floor(XSIZE(*(parent->img)[0])/gridSamples);
1060  master->chainList=new std::vector<LandmarkChain>;
1061  Matrix1D<double> rii(3), rjj(3);
1062  ZZ(rii)=1;
1063  ZZ(rjj)=1;
1064  if (thread_id==0)
1065  init_progress_bar(gridSamples);
1066  int includedPoints=0;
1067  Matrix1D<int> visited(Nimg);
1068  for (int nx=thread_id; nx<gridSamples; nx+=numThreads)
1069  {
1070  XX(rii)=STARTINGX(*(parent->img)[0])+ROUND(deltaShift*(0.5+nx));
1071  for (int ny=0; ny<gridSamples; ny+=1)
1072  {
1073  YY(rii)=STARTINGY(*(parent->img)[0])+ROUND(deltaShift*(0.5+ny));
1074  for (int ii=0; ii<=Nimg-1; ++ii)
1075  {
1076  // Check if inside the mask
1077  if (!(*(parent->maskImg[ii]))((int)YY(rii),(int)XX(rii)))
1078  continue;
1079  if (parent->isOutlier(ii))
1080  continue;
1081 
1082  LandmarkChain chain;
1083  chain.clear();
1084  Landmark l;
1085  l.x=XX(rii);
1086  l.y=YY(rii);
1087  l.imgIdx=ii;
1088  chain.push_back(l);
1089  visited.initZeros();
1090  visited(ii)=1;
1091 
1092  // Follow this landmark backwards
1093  bool acceptLandmark=true;
1094  int jj;
1095  if (parent->isCapillar)
1096  jj=intWRAP(ii-1,0,Nimg-1);
1097  else
1098  jj=ii-1;
1099  Matrix2D<double> Aij, Aji;
1100  Matrix1D<double> rcurrent=rii;
1101  while (jj>=0 && acceptLandmark && !visited(jj) &&
1102  !parent->isOutlier(jj))
1103  {
1104  // Compute the affine transformation between ii and jj
1105  int jj_1;
1106  if (parent->isCapillar)
1107  jj_1=intWRAP(jj+1,0,Nimg-1);
1108  else
1109  jj_1=jj+1;
1110  visited(jj)=1;
1111  Aij=affineTransformations[jj][jj_1];
1112  Aji=affineTransformations[jj_1][jj];
1113  rjj=Aji*rcurrent;
1114  double corr;
1115  acceptLandmark=parent->refineLandmark(jj_1,jj,rcurrent,rjj,
1116  corr,true);
1117  if (acceptLandmark)
1118  {
1119  l.x=XX(rjj);
1120  l.y=YY(rjj);
1121  l.imgIdx=jj;
1122  chain.push_back(l);
1123  if (parent->isCapillar)
1124  jj=intWRAP(jj-1,0,Nimg-1);
1125  else
1126  jj=jj-1;
1127  rcurrent=rjj;
1128  }
1129  }
1130 
1131  // Follow this landmark forward
1132  acceptLandmark=true;
1133  if (parent->isCapillar)
1134  jj=intWRAP(ii+1,0,Nimg-1);
1135  else
1136  jj=ii+1;
1137  rcurrent=rii;
1138  while (jj<Nimg && acceptLandmark && !visited(jj) &&
1139  !parent->isOutlier(jj))
1140  {
1141  // Compute the affine transformation between ii and jj
1142  int jj_1;
1143  if (parent->isCapillar)
1144  jj_1=intWRAP(jj-1,0,Nimg-1);
1145  else
1146  jj_1=jj-1;
1147  visited(jj)=1;
1148  Aij=affineTransformations[jj_1][jj];
1149  Aji=affineTransformations[jj][jj_1];
1150  rjj=Aij*rcurrent;
1151  double corr;
1152  acceptLandmark=parent->refineLandmark(jj_1,jj,rcurrent,rjj,
1153  corr,true);
1154  if (acceptLandmark)
1155  {
1156  l.x=XX(rjj);
1157  l.y=YY(rjj);
1158  l.imgIdx=jj;
1159  chain.push_back(l);
1160  if (parent->isCapillar)
1161  jj=intWRAP(jj+1,0,Nimg-1);
1162  else
1163  jj=jj+1;
1164  rcurrent=rjj;
1165  }
1166  }
1167 
1168 #ifdef DEBUG
1169  std::cout << "img=" << ii << " chain length="
1170  << chain.size() << " [" << jjleft
1171  << " - " << jjright << "]";
1172 #endif
1173 
1174  if (chain.size()>parent->seqLength)
1175  {
1176  double corrChain;
1177  bool accepted=parent->refineChain(chain,corrChain);
1178  if (accepted)
1179  {
1180 #ifdef DEBUG
1181  std::cout << " Accepted with length= "
1182  << chain.size()
1183  << " [" << chain[0].imgIdx << " - "
1184  << chain[chain.size()-1].imgIdx << "]= ";
1185  for (int i=0; i<chain.size(); i++)
1186  std::cout << chain[i].imgIdx << " ";
1187 #endif
1188 
1189  master->chainList->push_back(chain);
1190  includedPoints+=chain.size();
1191  }
1192  }
1193 #ifdef DEBUG
1194  std::cout << std::endl;
1195 #endif
1196 
1197  }
1198 #ifdef DEBUG
1199  std::cout << "Point nx=" << nx << " ny=" << ny
1200  << " Number of points="
1201  << includedPoints
1202  << " Number of chains=" << master->chainList->size()
1203  << " ( " << ((double) includedPoints)/
1204  master->chainList->size() << " )\n";
1205 #endif
1206 
1207  }
1208  if (thread_id==0)
1209  progress_bar(nx);
1210  }
1211  if (thread_id==0)
1212  progress_bar(gridSamples);
1213  return nullptr;
1214 }
void init_progress_bar(long total)
bool refineLandmark(int ii, int jj, const Matrix1D< double > &rii, Matrix1D< double > &rjj, double &maxCorr, bool tryFourier) const
__host__ __device__ float2 floor(const float2 v)
size_t seqLength
Sequence Length.
std::vector< MultidimArray< unsigned char > * > maskImg
#define STARTINGX(v)
bool refineChain(LandmarkChain &chain, double &corrChain)
#define i
#define STARTINGY(v)
#define XX(v)
Definition: matrix1d.h:85
int numThreads
Number of threads to use for parallel computing.
std::vector< Landmark > LandmarkChain
#define XSIZE(v)
void progress_bar(long rlen)
#define ROUND(x)
Definition: xmipp_macros.h:210
std::vector< MultidimArray< unsigned char > * > img
#define YY(v)
Definition: matrix1d.h:93
std::vector< std::vector< Matrix2D< double > > > affineTransformations
bool isCapillar
This tilt series comes from a capillar.
#define ZZ(v)
Definition: matrix1d.h:101
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272

◆ wrapperError()

double wrapperError ( double *  p,
void *  prm 
)

Definition at line 2508 of file tomo_align_tilt_series.cpp.

2509 {
2512  alignment.rot=p[1];
2513  alignment.tilt=p[2];
2514  return alignment.optimizeGivenAxisDirection();
2515 }
const ProgTomographAlignment * global_prm