Xmipp  v3.23.11-Nereus
tomo_extract_subvolume.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors Scheres scheres@cnb.csic.es (2010)
4  *
5  * Unidad de Bioinformatica del 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 #include "tomo_extract_subvolume.h"
26 
27 //#define DEBUG
28 
29 // Read arguments ==========================================================
30 
32 {
33  defaultComments["-i"].addComment("Metadata file with input volumes (and rotations/shifts)");
34 
36  addUsageLine("Extract subvolumes of the asymmetric parts of each subtomogram");
37 
38  addUsageLine("+++This program works closely together with the ml_tomo program, which is used to align");
39  addUsageLine("+++ (and classify) a series of subtomograms. Now, if each subtomogram contains some sort");
40  addUsageLine("+++ of (pseudo-) symmetry, tomo_extract_subvolume can be used to extract subvolumes of the");
41  addUsageLine("+++ asymmetric parts of each subtomogram. The metadata file that is output by this program orients");
42  addUsageLine("+++ each subvolume and its missing wedge in the correct orientation, so that it can be fed");
43  addUsageLine("+++ directly back into ml_tomo. There, the sub-subtomograms can be further aligned and/or classified");
44  addParamsLine("[--oroot <rootname=\"\">]: Rootname for output stacks of subvolumes");
45  addParamsLine("[-o <filename=\"\">] : Name of output metadata (\"oroot\".xmd by default)");
46  addParamsLine("--sym <sym=\"c1\"> : Symmetry group");
47  addParamsLine("--size <dim> : size output subvolumes");
48  addParamsLine("[--mindist <distance=-1>] : Minimum distance between subvolume centers, useful to avoid repetition of subvolumes place at simmetry axis");
49  addParamsLine(" : If set to -1 minsdist will be size/4");
50  addParamsLine("--center <x> <y> <z> : position of center of subvolume to be extracted");
51  addExampleLine("Extract 12 vertices (subvolumes) in boxes of size 21x21x21 pixels from each subtomogram in the data set: ", false);
52  addExampleLine("xmipp_extract_subvolume -i align/mltomo_1deg_it000001.doc -center 0 0 59 -size 21 -sym i3 -o vertices");
53 
54  addExampleLine("+++Imagine we have N subtomograms of a virus particle and we have aligned them",false);
55  addExampleLine("+++ with respect to a reference structure (or we have aligned them in a reference-free manner).",false);
56  addExampleLine("+++ Then, suppose we are interested in the vertices of the virus: perhaps because we suspect",false);
57  addExampleLine("+++ that one of them is 'special': e.g. it is a portal. All we have to do is:",false);
58 
59  addExampleLine("+++* Pass the metadata of the aligned subtomograms of the ml_tomo prgram",false);
60  addExampleLine("+++* Find the x,y,z coordinates of one of the vertices in the average (reference) map",false);
61  addExampleLine("+++* Pass the (pseudo) symmetry description of the virus (icosahedral, see Symmetries)",false);
62 
63  addExampleLine("+++The program will then extract all symmetry-related vertices in each of the N aligned subtomograms.",false);
64  addExampleLine("+++Each icosahedral has 12 vertices, so if the x,y,z coordinates coincided with a vertex (with an accuracy ",false);
65  addExampleLine("+++given by the --mindist option, see below)",false);
66  addExampleLine("+++, then we will end up with 12*N sub-subtomograms. The sub-subtomograms are not rotated ",false);
67  addExampleLine("+++to avoid interpolation. Instead, the output metadata holds the correct orientations ",false);
68  addExampleLine("+++and translation for each of them to subsequently superimpose them in the ml_tomo program. ",false);
69  addExampleLine("+++Also the missing wedges of all sub-subtomograms will be treated correctly in this way. Then, in the ",false);
70  addExampleLine("+++ml_tomo program one could attempt to classify the 12*N vertices, in an attempt to 'fish out' the N ",false);
71  addExampleLine("+++supposed portal structures.",false);
72 
73  addExampleLine("+++The format of the input and output files is as described for the ml_tomo program.",false);
74 
75  addExampleLine("+++ First, lets align our set of virus subtomograms (images.sel, with missing wedges defined ",false);
76  addExampleLine("+++ in images.doc and wedges.doc, see ml_tomo for details) ",false);
77  addExampleLine("+++. We will use a known virus structure (myreference.vol) as reference and will use ",false);
78  addExampleLine("+++ maximum cross-correlation (rather than maximum likelihood) to avoid problems with absolute ",false);
79  addExampleLine("+++ greyscales and the standard deviation in the noise. ",false);
80 
81  addExampleLine("+++ ml_tomo -i images.sel -doc images.doc -ref myreference.vol --oroot align/mltomo_10deg -missing wedges.doc -iter 1 -ang 10");
82  addExampleLine("+++ ml_tomo -i images.sel -doc align/mltomo_10deg_it000001.doc -ref myreference.vol --oroot align/mltomo_5deg -missing wedges.doc -iter 1 -ang 5 -ang_search 20");
83  addExampleLine("+++ ml_tomo -i images.sel -doc align/mltomo_5deg_it000001.doc -ref myreference.vol --oroot align/mltomo_2deg -missing wedges.doc -iter 1 -ang 2 -ang_search 8");
84  addExampleLine("+++ ml_tomo -i images.sel -doc align/mltomo_2deg_it000001.doc -ref myreference.vol --oroot align/mltomo_1deg -missing wedges.doc -iter 1 -ang 1 -ang_search 3");
85 
86  addExampleLine("+++ Now, we will identify the x,y,z coordinates of the vertex in the reference structure (which has symmetry i3): ",false);
87  addExampleLine("+++ -center 0 0 59. And we will extract 12 vertices (subvolumes) in boxes of size 12x12x12 pixels ",false);
88  addExampleLine("+++ from each subtomogram in the data set: ",false);
89 
90  addExampleLine("+++ xmipp_extract_subvolume -doc align/mltomo_1deg_it000001.doc -center 0 0 59 -size 21 -sym i3 -o vertices ",false);
91 
92  addExampleLine("+++ his has generated subvolumes in the same directory as the original subtomograms. For each subtomogram 12 ",false);
93  addExampleLine("+++ subvolumes, which are named in the same way as the original subtomograms, but ending in _sub000001.vol etc. ",false);
94  addExampleLine("+++ The orientations and translations are in a file called vertices.doc, the selection file is called vertices.sel. ",false);
95  addExampleLine("+++ These files are already in the correct format for the ml_tomo program. Therefore, classifying the vertices into ",false);
96  addExampleLine("+++ 4 classes using ML is now straightforward (see ml_tomo for details again) ",false);
97  addExampleLine("+++ : ",false);
98 
99  addExampleLine("+++ xmipp_ml_tomo -i vertices.sel -doc vertices.doc -dont_align -keep_angles -missing wedges.doc -nref 4 -reg0 5 -iter 25");
100 
101  addExampleLine("+++ Note that the whole functionality of ml_tomo can be employed on the sub-subtomograms: alignment, ",false);
102  addExampleLine("+++ classification, local angular searches, symmetry, etc. For example, in case of the vertices, on ",false);
103  addExampleLine("+++ could apply -sym c5, and/or one could allow the vertices to re-orient slightly (with respect ",false);
104  addExampleLine("+++ to the i3 symmetry) by using -ang 5 ang_search 15. ",false);
105 }
106 
108 {
110  oroot = getParam("--oroot");
111  fn_out = getParam("-o");
112  // Read command line
113  fn_sym = getParam( "--sym");
114  center_ref.resize(3);
115  size = getIntParam("--size");
116  XX(center_ref) = getIntParam( "--center",0);
117  YY(center_ref) = getIntParam( "--center",1);
118  ZZ(center_ref) = getIntParam( "--center",2);
119  mindist = getDoubleParam("--mindist");
120  if (mindist == -1)
121  mindist = size/4.;
122 }
123 
124 // Usage ===================================================================
126 {
127 #ifdef DEBUG
128  std::cerr << "start show" <<std::endl;
129 #endif
130 
131  if (verbose)
132  {
133  std::cout << " -----------------------------------------------------------------" << std::endl;
134  std::cout << " | Read more about this program in the following publication: |" << std::endl;
135  std::cout << " | Scheres ea. (2009) Structure, 17, 1563-1572 |" << std::endl;
136  std::cout << " | |" << std::endl;
137  std::cout << " | *** Please cite it if this program is of use to you! *** |" << std::endl;
138  std::cout << " -----------------------------------------------------------------" << std::endl;
139 
140  std::cout << "Input Metadata File " << fn_in << std::endl;
141  std::cout << "Output volume root " << oroot << std::endl;
142  std::cout << "Output metadata file " << fn_out << std::endl;
143  std::cout << "Coordenate center " << center_ref << std::endl;
144  std::cout << "Size subvolume " << size << std::endl;
145  std::cout << "Symmetry group " << fn_sym << std::endl;
146  std::cout << "Minimum distance between subvolumes " << mindist << std::endl;
147  }
148 #ifdef DEBUG
149  std::cerr << "end show" <<std::endl;
150 #endif
151 }
152 
154 {
155  // produceSideInfo();
156 #ifdef DEBUG
157  std::cerr<<"Start produceSideInfo"<<std::endl;
158 #endif
159 
160  // //Read in Docfile
161  // DF.read(fn_doc);
162  // nr_exp_images = DF.size();
163 
164  // Setup symmetry
166  REPORT_ERROR(ERR_PARAM_INCORRECT, "tomo_extract_subvolume: Invalid symmetry " + fn_sym);
168 
169  // Check which symmetry operators give unique output points
170  centers_subvolumes.clear();
171  rotations_subvolumes.clear();
172  Matrix2D<double> L(4, 4), R(4, 4);
173  Matrix2D<double> Iref(3,3);
174  Matrix1D<double> newcenter(3), distcenter(3);
175  double dist;
176  bool is_uniq;
177  Iref.initIdentity();
178 
179  centers_subvolumes.push_back(center_ref);
180  rotations_subvolumes.push_back(Iref);
181 
182  for (int isym = 0; isym < SL.symsNo(); isym++)
183  {
184  SL.getMatrices(isym, L, R);
185  L.resize(3,3);
186  R.resize(3,3);
187  newcenter = L * (center_ref.transpose() * R).transpose();
188  is_uniq=true;
189  for (size_t i = 0; i < centers_subvolumes.size(); i++)
190  {
191  distcenter = centers_subvolumes[i] - newcenter;
192  dist = sqrt(distcenter.sum2());
193  if (dist < mindist)
194  {
195  is_uniq=false;
196  break;
197  }
198  }
199  if (is_uniq)
200  {
201  centers_subvolumes.push_back(newcenter);
202  rotations_subvolumes.push_back(R);
203  }
204  }
205 //#define DEBUG
206 #ifdef DEBUG
207  for (int isym = 0; isym < SL.symsNo(); isym++)
208  {
209  std::cerr << "centers_subvolumes" << centers_subvolumes[isym] << std::endl;
210  std::cerr << "rotations_subvolumes" << rotations_subvolumes[isym] << std::endl;
211  } std::cerr<<"End produceSideInfo"<<std::endl;
212 #endif
213 
214  center.resizeNoCopy(3);
216  A.resizeNoCopy(3,3);
217  R.resizeNoCopy(3,3);
218  I.resizeNoCopy(3,3);
219  I.initIdentity();
220 }
221 
223  , const FileName &fnImgOut
224  , const MDRow &rowIn
225  , MDRow &rowOut)
226 {
227 
228 #ifdef DEBUG
229  std::cerr<<"Start processImages"<<std::endl;
230 #endif
231 
232  // for (int imgno=imgno_start; imgno <imgno_end; imgno++)
233  rot = rowIn.getValueOrDefault(MDL_ANGLE_ROT, 0.);
235  psi = rowIn.getValueOrDefault(MDL_ANGLE_PSI, 0.);
236 
237  double auxD;
238  rowIn.getValue(MDL_ORIGIN_X,auxD);
239  XX(doccenter) = auxD;
240  rowIn.getValue(MDL_ORIGIN_Y,auxD);
241  YY(doccenter) = auxD;
242  rowIn.getValue(MDL_ORIGIN_Z,auxD);
243  ZZ(doccenter) = auxD;
244 
245  // Read volume
246  vol.read(fnImg2);
247  vol().setXmippOrigin();
248  FileName fnImg;
249  fnImg = fnImg2.removeFileFormat().removeLastExtension();
250 
253 
254  FileName fnOutStack, fnOutMd;
255 
256  size_t image_num = 0;
257  FileName dump;
258  if (mdInSize > 1)// Other case, is a unique volume name so there is no need to add the number
259  {
260  if (oroot.empty())
261  {
262  fn_aux = fnImg.removePrefixNumber().removeLastExtension()+ "_sub";
263 
264  if (fnImg.isInStack())
265  {
266  fnImg.decompose(image_num, dump);
267  fn_aux.compose(fn_aux,image_num);
268  }
269  }
270  else if (fnImg.isInStack())
271  {
272  fnImg.decompose(image_num, dump);
273  fn_aux.compose(oroot,image_num);
274  }
275  else
276  fn_aux = oroot + "_" + fnImg.afterLastOf("/");
277  }
278  else if (!oroot.empty())
279  fn_aux = oroot;
280  else
281  fn_aux = fnImg+"_sub";
282 
283  if (mdInSize > 1)
284  {
285  if (fn_out.empty())
286  fnOutMd = fn_aux.addExtension("xmd");
287  else if (fnImg.isInStack())
288  fnOutMd.compose(fn_out.removeLastExtension(), image_num, fn_out.getExtension());
289  else
290  fnOutMd = fn_out.insertBeforeExtension("_" + fnImg.getBaseName());
291  }
292  else if (!fn_out.empty())
293  fnOutMd = fn_out;
294  else
295  fnOutMd = fn_aux.addExtension("xmd");
296 
297  // Tomo_Extract each of the unique subvolumes
298  size_t oId;
300  for (size_t i = 0; i < centers_subvolumes.size(); i++)
301  {
303 
304  // 1. rotate center
305  Euler_angles2matrix(-psi,-tilt,-rot,A,false);
307  // 2. translate center
308  center -= doccenter;
309  // 3. Apply possible non-integer center to volume
310  //translations may be non-integer
312 
313  //vol().translate(-center, volout(), DONT_WRAP);
314  //4. Window operation and write subvolume to disc
315  volout().selfWindow(x0,x0,x0,xF,xF,xF);
316  //remove type if present
317  fnOutStack.compose(i+1,fn_aux,"stk");
318  volout.write(fnOutStack);
319 
320 
321  // 5. Calculate output angles: apply symmetry rotation to rot,tilt and psi
323  oId=DFout.addObject();
324 
325  DFout.setValue(MDL_IMAGE,fnOutStack,oId);
332  }
333  // 6. Output translations will be zero because subvolumes are centered by definition
337 
338  DFout.setComment("shift keeps the center of the box in the original virus");
339  DFout.write(fnOutMd);
340  DFout.clear();
341 
342 
343 
344 #ifdef DEBUG
345 
346  std::cerr<<"end processImages"<<std::endl;
347 #endif
348 }
350 {}
Rotation angle of an image (double,degrees)
Parameter incorrect.
Definition: xmipp_error.h:181
double getDoubleParam(const char *param, int arg=0)
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
FileName removeLastExtension() const
size_t mdInSize
Number of input elements.
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
FileName removeFileFormat() const
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
void sqrt(Image< double > &op)
Tilting angle of an image (double,degrees)
FileName removePrefixNumber() const
FileName addExtension(const String &ext) const
int readSymmetryFile(FileName fn_sym, double accuracy=SYM_ACCURACY)
Definition: symmetries.cpp:33
Shift for the image in the X axis (double)
FileName insertBeforeExtension(const String &str) const
std::vector< Matrix1D< double > > centers_subvolumes
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)
bool isSymmetryGroup(FileName fn_sym, int &pgGroup, int &pgOrder)
Definition: symmetries.cpp:601
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
auxiliary label to be used as an index (long)
void decompose(size_t &no, String &str) const
int symsNo() const
Definition: symmetries.h:268
void Euler_apply_transf(const Matrix2D< double > &L, const Matrix2D< double > &R, double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:1038
#define i
virtual void setComment(const String &newComment="No comment")
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
void resizeNoCopy(int Ydim, int Xdim)
Definition: matrix2d.h:534
FileName afterLastOf(const String &str) const
String getExtension() const
void clear() override
double sum2() const
Definition: matrix1d.cpp:673
T & getValue(MDLabel label)
FileName fn_in
Filenames of input and output Metadata.
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
void transpose(double *array, int size)
void readParams()
Read arguments from command line.
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
Origin for the image in the Y axis (double)
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
void defineParams()
Define the arguments accepted.
void addExampleLine(const char *example, bool verbatim=true)
int verbose
Verbosity level.
std::vector< Matrix2D< double > > rotations_subvolumes
bool setValueCol(const MDObject &mdValueIn) override
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
const T & getValueOrDefault(MDLabel label, const T &def) const
void translate(PDB *pdb_original, PDB *pdb_move, unsigned num_atoms, double x0, double y0, double z0)
Definition: lib_pwk.cpp:125
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
Shift for the image in the Z axis (double)
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
Origin for the image in the Z axis (double)
Shift for the image in the Y axis (double)
void addUsageLine(const char *line, bool verbatim=false)
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
int getIntParam(const char *param, int arg=0)
FileName getBaseName() const
Name of an image (std::string)
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022
#define ZZ(v)
Definition: matrix1d.h:101
void addParamsLine(const String &line)
void initIdentity()
Definition: matrix2d.h:673
bool isInStack() const
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
std::map< String, CommentList > defaultComments
Definition: xmipp_program.h:83