Xmipp  v3.23.11-Nereus
align2d.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors Scheres (scheres@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 "align2d.h"
27 
28 #include "core/transformations.h"
31 #include "data/filters.h"
32 #include "data/mask.h"
33 
34 // Read arguments ==========================================================
36 {
37  fnSel = getParam("-i");
38  fnRoot = getParam("--oroot");
39  fnRef = getParam("--ref");
40  Niter = getIntParam("--iter");
41  dont_mirror = checkParam("--do_not_check_mirrors");
42  pspc = checkParam("--pspc");
43 }
44 
45 // Show ====================================================================
47 {
48  if (verbose==0)
49  return;
50  std::cerr
51  << "Input selfile: " << fnSel << std::endl
52  << "Input reference: " << fnRef << std::endl
53  << "Output rootname: " << fnRoot << std::endl
54  << "Number of iterations: " << Niter << std::endl
55  << "Do not check mirrors: " << dont_mirror << std::endl
56  << "PSPC: " << pspc << std::endl
57  ;
58 }
59 
60 // usage ===================================================================
62 {
63  addUsageLine("Aligns a set of images");
64  addParamsLine(" -i <selfile> : Selfile containing images to be aligned");
65  addParamsLine(" --oroot <rootname> : Output rootname");
66  addParamsLine(" [--ref <image=\"\">] : reference image; if none: pyramidal combination of subset of images");
67  addParamsLine(" [--iter <N=5>] : Number of iterations to perform");
68  addParamsLine(" [--do_not_check_mirrors] : Do not consider mirrors when aligning");
69  addParamsLine(" [--pspc] : Compute first reference by pspc");
70 }
71 
72 // PsPc pyramidal combination of images ========================================
73 //#define DEBUG
74 void ProgAlign2d::alignPairs(MetaData &MDin, MetaData &MDout, int level)
75 {
76  // Compute output stack size
77  size_t imax=MDin.size()/2;
78  size_t remaining=MDin.size()-2*imax;
79  size_t Xdim, Ydim, Zdim, Ndim;
80  getImageSize(MDin,Xdim,Ydim,Zdim,Ndim);
81  if (Zdim!=1 || Ndim!=1)
82  REPORT_ERROR(ERR_MATRIX_DIM,"Files in metadata are not 2D images");
83  FileName fnOutputStack=fnRoot+"_level_"+integerToString(level,2)+".stk";
84  fnOutputStack.deleteFile();
85  createEmptyFile(fnOutputStack,Xdim,Ydim,1,imax+remaining,true,WRITE_REPLACE);
86 
87  // Align all pairs
88  auto mdIdIter(MDin.ids().begin());
89  Image<double> I1, I2;
92  AlignmentAux aux1;
93  CorrelationAux aux2;
95  std::cerr << "Aligning level " << level << std::endl;
96  init_progress_bar(imax);
97  for (size_t i=0; i<imax; i++)
98  {
99  // Read the two input images
100  I1.readApplyGeo(MDin, *mdIdIter);
101  ++mdIdIter;
102  I2.readApplyGeo(MDin, *mdIdIter);
103  ++mdIdIter;
104 
105  // Align images
106  MultidimArray<double> &I1m=I1();
107  MultidimArray<double> &I2m=I2();
108  if (dont_mirror)
109  alignImages(I1m,I2m,M);
110  else
111  alignImagesConsideringMirrors(I1m,I2m,M,aux1,aux2,aux3);
114  DIRECT_MULTIDIM_ELEM(I2m,n));
115  centerImage(I1m,aux2,aux3);
116 
117  // Write to output stack
118  fnOut.compose(i+1,fnOutputStack);
119  I1.write(fnOut);
120  size_t objId=MDout.addObject();
121  MDout.setValue(MDL_IMAGE,fnOut,objId);
122 
123 #ifdef DEBUG
124  I1.write("PPPI1.xmp");
125  I2.write("PPPI2.xmp");
126  std::cout << "M=" << M;
127  std::cout << "Press any key\n";
128  char c;
129  std::cin >> c;
130 #endif
131  if (i%100==0)
132  progress_bar(i);
133  }
134  progress_bar(imax);
135 
136  if (remaining)
137  {
138  I1.readApplyGeo(MDin, *mdIdIter);
139  ++mdIdIter;
140  fnOut.compose(imax+1,fnOutputStack);
141  I1.write(fnOut);
142  }
143 }
144 #undef DEBUG
145 
147 {
148  int level=0;
149  MetaDataVec SFlevel = SF;
150  MetaDataVec SFlevel_1;
151  while (SFlevel.size()>1)
152  {
153  alignPairs(SFlevel,SFlevel_1,level);
154  if (level>=1)
155  unlink((fnRoot+"_level_"+integerToString(level-1,2)+".stk").c_str());
156  level++;
157  SFlevel=SFlevel_1;
158  SFlevel_1.clear();
159  }
160  size_t objId=SFlevel.firstRowId();
161  Iref.readApplyGeo(SFlevel,objId);
162  unlink((fnRoot+"_level_"+integerToString(level-1,2)+".stk").c_str());
163  Iref.write(fnRoot+"_pspc.xmp");
164 }
165 
167 {
168  size_t Xdim, Ydim, Zdim, Ndim;
169  getImageSize(SF,Xdim,Ydim,Zdim,Ndim);
170  if (Zdim!=1 || Ndim!=1)
171  REPORT_ERROR(ERR_MATRIX_DIM,"Files in metadata are not 2D images");
172  Iref().initZeros(Ydim,Xdim);
173  Image<double> I;
174  FileName fnImg;
175  size_t N=SF.size();
176  std::cerr << "Computing average of images ...\n";
178  int i=0;
179  for (size_t objId : SF.ids())
180  {
181  I.readApplyGeo(SF, objId);
182  Iref()+=I();
183  if ((++i)%100==0)
184  progress_bar(i);
185  }
186  progress_bar(N);
187  Iref()*=1.0/N;
188  CorrelationAux aux;
190  centerImage(Iref(),aux,aux2);
191 }
192 
193 // Alignment of all images by iterative refinement ========================================
194 //#define DEBUG
196 {
197  Image<double> I;
198  size_t N=SF.size();
199  double lambda=1.0/(N/2.0);
200  double lambdap=1-lambda;
202  int i=0;
203  MultidimArray<double> &Irefm=Iref();
205  int centerCount=0;
206  FileName fnImg;
207  AlignmentAux aux1;
208  CorrelationAux aux2;
210  for (size_t objId : SF.ids())
211  {
212  SF.getValue(MDL_IMAGE, fnImg, objId);
213  I.read(fnImg);
214  I().setXmippOrigin();
215  MultidimArray<double> Ibackup, Ialigned;
216  Ibackup=I();
217 
218  // Align images
219  MultidimArray<double> &Im=I();
220  double corr;
221  if (dont_mirror)
222  corr=alignImages(Irefm,Im,M);
223  else
224  corr=alignImagesConsideringMirrors(Irefm,Im,M,aux1,aux2,aux3);
225  applyGeometry(xmipp_transformation::LINEAR, Ialigned, Ibackup, M, xmipp_transformation::IS_NOT_INV, xmipp_transformation::WRAP);
226  Im=Ialigned;
227 
228  // Save alignment
229  bool flip;
230  double scale, shiftX, shiftY, psi;
231  transformationMatrix2Parameters2D(M, flip, scale, shiftX, shiftY, psi);
232  SF.setValue(MDL_SHIFT_X, shiftX, objId);
233  SF.setValue(MDL_SHIFT_Y, shiftY, objId);
234  SF.setValue(MDL_ANGLE_PSI, psi, objId);
235  SF.setValue(MDL_FLIP, flip, objId);
236  SF.setValue(MDL_MAXCC, corr, objId);
237 
238  // Update reference
240  DIRECT_MULTIDIM_ELEM(Irefm,n)=lambdap*DIRECT_MULTIDIM_ELEM(Irefm,n)+
241  lambda*DIRECT_MULTIDIM_ELEM(Im,n);
242 
243  // From time to time, recenter the reference
244  if ((++centerCount)%10==0)
245  {
246  centerImage(Irefm,aux2,aux3);
247  centerCount=0;
248  }
249 
250  if ((++i)%100==0)
251  progress_bar(i);
252 #ifdef DEBUG
253  Iref.write("PPPref.xmp");
254  I.write("PPPexp.xmp");
255  std::cout << "Press any key\n";
256  char c;
257  std::cin >> c;
258 #endif
259  }
260  progress_bar(N);
261  Iref.write(fnRoot+"_ref.xmp");
262  SF.write(fnRoot+"_alignment.xmd");
263 }
264 #undef DEBUG
265 
266 // Write out results ========================================================
268 {
269  // Read the input metadata
270  SF.read(fnSel);
271 
272  // Get Reference
273  if (fnRef != "")
274  Iref.read(fnRef);
275  else
276  {
277  if (pspc)
278  do_pspc();
279  else
280  computeMean();
281  }
282  Iref().setXmippOrigin();
283 
284  // Circular mask the reference image
285  MultidimArray<int> mask;
286  mask.resize(Iref());
287  mask.setXmippOrigin();
288  BinaryCircularMask(mask,XSIZE(Iref())/2);
289  apply_binary_mask(mask, Iref(), Iref());
290 
291  // Refine
292  std::cout << "Refining ...\n";
293  for (int n=0; n<Niter; n++)
294  {
295  std::cerr << "Refinement iteration " << n << std::endl;
296  refinement();
297  }
298 }
void init_progress_bar(long total)
void run()
Main routine.
Definition: align2d.cpp:267
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
virtual size_t addObject()=0
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
void defineParams()
Define parameters.
Definition: align2d.cpp:61
void transformationMatrix2Parameters2D(const Matrix2D< T > &A, bool &flip, T &scale, T &shiftX, T &shiftY, T &psi)
double alignImages(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, bool wrap, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3)
Definition: filters.cpp:2047
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void apply_binary_mask(const MultidimArray< int > &mask, const MultidimArray< T > &m_in, MultidimArray< T > &m_out, T subs_val=(T) 0)
Definition: mask.h:857
doublereal * c
void BinaryCircularMask(MultidimArray< int > &mask, double radius, int mode, double x0, double y0, double z0)
Definition: mask.cpp:193
MetaDataVec SF
Definition: align2d.h:53
Shift for the image in the X axis (double)
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
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 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="")
Special label to be used when gathering MDs in MpiMetadataPrograms.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
String integerToString(int I, int _width, char fill_with)
virtual IdIteratorProxy< false > ids()
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
size_t size() const override
#define i
Matrix2D< double > centerImage(MultidimArray< double > &I, CorrelationAux &aux, RotationalCorrelationAux &aux2, int Niter, bool limitShift)
Definition: filters.cpp:3277
void clear() override
const char * getParam(const char *param, int arg=0)
double * lambda
bool setValue(const MDObject &mdValueIn, size_t id)
Problem with matrix dimensions.
Definition: xmipp_error.h:150
size_t firstRowId() const override
FileName fnOut
FileName fnSel
Definition: align2d.h:40
Flip the image? (bool)
#define XSIZE(v)
void progress_bar(long rlen)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
Maximum cross-correlation for the image (double)
Image< double > Iref
Definition: align2d.h:55
void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim, size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
int verbose
Verbosity level.
virtual size_t size() const =0
bool pspc
Definition: align2d.h:50
bool dont_mirror
Definition: align2d.h:48
void computeMean()
Compute mean.
Definition: align2d.cpp:166
void deleteFile() const
bool getValue(MDObject &mdValueOut, size_t id) const override
bool setValue(const MDLabel label, const T &valueIn, size_t id)
void do_pspc()
Pyramidal combination of images to construct a reference.
Definition: align2d.cpp:146
FileName fnRoot
Definition: align2d.h:44
FileName fnRef
Definition: align2d.h:42
double psi(const double x)
void alignPairs(MetaData &MDin, MetaData &MDout, int level)
Align pairs.
Definition: align2d.cpp:74
bool checkParam(const char *param)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
void readParams()
Read argument.
Definition: align2d.cpp:35
Shift for the image in the Y axis (double)
void addUsageLine(const char *line, bool verbatim=false)
int getIntParam(const char *param, int arg=0)
void show()
Show.
Definition: align2d.cpp:46
void refinement()
Alignment of all images by iterative refinement.
Definition: align2d.cpp:195
double alignImagesConsideringMirrors(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3, bool wrap, const MultidimArray< int > *mask)
Definition: filters.cpp:2150
int * n
Name of an image (std::string)
int Niter
Definition: align2d.h:46
void addParamsLine(const String &line)