Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TMalign.hh
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file
11 /// @brief A reimplementation of TM-align algorithm
12 /// @author Yifan Song
13 
14 #ifndef INCLUDED_protocols_hybridization_TMalign_hh
15 #define INCLUDED_protocols_hybridization_TMalign_hh
16 
17 #define getmax(a,b) a>b?a:b
18 #define getmin(a,b) a>b?b:a
19 //#define MAXLEN 10000 //maximum length of filenames
20 
21 //#include <stdio.h>
22 //#include <stdlib.h>
23 #include <math.h>
24 //#include <time.h>
25 #include <string>
26 //#include <malloc.h>
27 
28 //#include <sstream>
29 //#include <iostream>
30 //#include <fstream>
31 #include <vector>
32 #include <iterator>
33 #include <algorithm>
34 
35 #include <core/pose/Pose.hh>
36 #include <core/pose/PDBInfo.hh>
37 
38 #include <numeric/xyzVector.hh>
39 #include <numeric/xyzMatrix.hh>
40 #include <numeric/xyz.functions.hh>
41 #include <core/id/AtomID.hh>
42 #include <core/id/AtomID_Map.hh>
44 
45 namespace protocols {
46 //namespace comparative_modeling {
47 namespace hybridization {
48 
49 using namespace std;
50 using core::Size;
51 
52 // ===============================================================================
53 // Implementation of TM-align in C/C++
54 //
55 // This program is written by Jianyi Yang at
56 // Yang Zhang lab
57 // Center for Computational Medicine and Bioinformatics
58 // University of Michigan
59 // 100 Washtenaw Avenue, Ann Arbor, MI 48109-2218
60 //
61 // Please report bugs and questions to yangji@umich.edu or or zhng@umich.edu
62 // ===============================================================================
63 
64 class TMalign {
65 private:
66  char version[20];
67  double D0_MIN;
68  double Lnorm; //normalization length
69  double score_d8, d0, d0_search, dcu0; //for TMscore search
70  std::vector < std::vector < double > > score; //Input score table for dynamic programming
71  std::vector < std::vector < bool > > path; //for dynamic programming
72  std::vector < std::vector < double > > val; //for dynamic programming
73  int xlen, ylen, minlen; //length of proteins
74  std::vector < numeric::xyzVector<core::Real> > xa, ya; //for input vectors xa[0...xlen-1][0..2], ya[0...ylen-1][0..2]
75  std::vector < int > xresno, yresno; //residue numbers, used in fragment gapless threading
76  vector < numeric::xyzVector <core::Real> > xtm, ytm; //for TMscore search engine
77  vector < numeric::xyzVector <core::Real> > xt; //for saving the superposed version of r_1 or xtm
78  std::string seqx, seqy; //for the protein sequence
79  std::vector < int > secx, secy; //for the secondary structure
80  vector < numeric::xyzVector <core::Real> > r1, r2; //for Kabsch rotation
82  numeric::xyzMatrix <core::Real> u; //Kabsch translation vector and rotation matrix
83 
84  int n_ali8_;
85  std::vector < int > m1_, m2_;
86  double d0_out_;
87 
88  //argument variables
89  double Lnorm_ass, Lnorm_d0, d0_scale, d0A, d0B, d0u, d0a;
90  bool o_opt, a_opt, u_opt, d_opt, v_opt;
91  double TM3, TM4, TM5;
92 
93 public:
94  void PrintErrorAndQuit(string sErrorString) {
95  cout << sErrorString << endl;
96  exit(1);
97  }
98 
99  template < class A > void ResizeArray( A & array, int Narray1, int Narray2) {
100  array.resize(Narray1);
101  for(int i=0; i<Narray1; i++) array[i].resize(Narray2);
102  }
103 
105  core::pose::Pose const & pose,
106  std::list <core::Size> const & residue_list,
107  std::vector < numeric::xyzVector < core::Real > > & a,
108  string & seq, std::vector < int > & resno) {
109  int i=0;
110  seq.resize(residue_list.size());
111  for (std::list<core::Size>::const_iterator it = residue_list.begin();
112  it != residue_list.end();
113  ++it) {
114  core::Size ires = *it;
115  if (!pose.residue_type(ires).is_protein()) continue;
116 
117  a[i] = pose.residue(ires).xyz("CA");
118  seq[i] = pose.residue_type(ires).name1();
119  if (pose.pdb_info() != 0) {
120  resno[i] = pose.pdb_info()->number(ires);
121  } else {
122  resno[i] = ires;
123  }
124  i++;
125  }
126  return residue_list.size();
127  }
128 
129 
130  inline double dist(numeric::xyzVector<core::Real> x, numeric::xyzVector<core::Real> y) { return x.distance(y); }
131 
132  inline void transform(
137  x1 = t + u*x;
138  }
139 
141  std::vector < numeric::xyzVector<core::Real> > const x,
142  std::vector < numeric::xyzVector<core::Real> > & x1,
143  int len,
146  for(int i=0; i<len; i++) {
147  transform(t, u, x[i], x1[i]);
148  }
149  }
150 
151  // Please note this function is not a correct implementation of
152  // the N-W dynamic programming because the score tracks back only
153  // one layer of the matrix. This code was exploited in TM-align
154  // because it is about 1.5 times faster than a complete N-W code
155  // and does not influence much the final structure alignment result.
156  void NWDP_TM(Size const len1, Size const len2, double const gap_open, vector < int > & j2i)
157  {
158  //NW dynamic programming for alignment
159  //not a standard implementation of NW algorithm
160  //Input: score[1:len1, 1:len2], and gap_open
161  //Output: j2i[1:len2] \in {1:len1} U {-1}
162  //path[0:len1, 0:len2]=1,2,3, from diagonal, horizontal, vertical
163  double h, v, d;
164 
165  //initialization
166  val[0][0]=0;
167  for(Size i=0; i<=len1; ++i) {
168  val[i][0]=0;
169  path[i][0]=false; //not from diagonal
170  }
171 
172  for(Size j=0; j<=len2; ++j) {
173  val[0][j]=0;
174  path[0][j]=false; //not from diagonal
175  j2i[j]=-1; //all are not aligned, only use j2i[1:len2]
176  }
177 
178  //decide matrix and path
179  for(Size i=1; i<=len1; ++i) {
180  for(Size j=1; j<=len2; ++j) {
181  d=val[i-1][j-1]+score[i][j]; //diagonal
182 
183  //symbol insertion in horizontal (= a gap in vertical)
184  h=val[i-1][j];
185  if(path[i-1][j]) //aligned in last position
186  h += gap_open;
187 
188  //symbol insertion in vertical
189  v=val[i][j-1];
190  if(path[i][j-1]) //aligned in last position
191  v += gap_open;
192 
193 
194  if(d>=h && d>=v) {
195  path[i][j]=true; //from diagonal
196  val[i][j]=d;
197  } else {
198  path[i][j]=false; //from horizontal
199  if(v>=h)
200  val[i][j]=v;
201  else
202  val[i][j]=h;
203  }
204  } //for i
205  } //for j
206 
207  //trace back to extract the alignment
208  int i=len1;
209  int j=len2;
210  while(i>0 && j>0) {
211  if(path[i][j]) { //from diagonal
212  j2i[j-1]=i-1;
213  i--; j--;
214  } else {
215  h=val[i-1][j];
216  if(path[i-1][j]) h +=gap_open;
217 
218  v=val[i][j-1];
219  if(path[i][j-1]) v +=gap_open;
220 
221  if(v>=h) j--;
222  else i--;
223  }
224  }
225  }
226 
227  void NWDP_TM(
228  std::vector < numeric::xyzVector<core::Real> > const x,
229  std::vector < numeric::xyzVector<core::Real> > const y,
230  int const len1, int const len2,
232  double d02, double gap_open, vector < int > & j2i) {
233  //NW dynamic programming for alignment
234  //not a standard implementation of NW algorithm
235  //Input: vectors x, y, rotation matrix t, u, scale factor d02, and gap_open
236  //Output: j2i[1:len2] \in {1:len1} U {-1}
237  //path[0:len1, 0:len2]=1,2,3, from diagonal, horizontal, vertical
238  int i, j;
239  double h, v, d;
240 
241  //initialization
242  val[0][0]=0;
243  for(i=0; i<=len1; i++) {
244  val[i][0]=0;
245  path[i][0]=false; //not from diagonal
246  }
247 
248  for(j=0; j<=len2; j++) {
249  val[0][j]=0;
250  path[0][j]=false; //not from diagonal
251  j2i[j]=-1; //all are not aligned, only use j2i[1:len2]
252  }
254  double dij;
255 
256  //decide matrix and path
257  for(i=1; i<=len1; i++) {
258  transform(t, u, x[i-1], xx);
259  for(j=1; j<=len2; j++) {
260  //d=val[i-1][j-1]+score[i][j]; //diagonal
261  dij=dist(xx, y[j-1]);
262  d=val[i-1][j-1] + 1.0/(1+dij/d02);
263 
264  //symbol insertion in horizontal (= a gap in vertical)
265  h=val[i-1][j];
266  if(path[i-1][j]) //aligned in last position
267  h += gap_open;
268 
269  //symbol insertion in vertical
270  v=val[i][j-1];
271  if(path[i][j-1]) //aligned in last position
272  v += gap_open;
273 
274  if(d>=h && d>=v) {
275  path[i][j]=true; //from diagonal
276  val[i][j]=d;
277  } else {
278  path[i][j]=false; //from horizontal
279  if(v>=h)
280  val[i][j]=v;
281  else
282  val[i][j]=h;
283  }
284  } //for i
285  } //for j
286 
287  //trace back to extract the alignment
288  i=len1; j=len2;
289  while(i>0 && j>0) {
290  if(path[i][j]) { //from diagonal
291  j2i[j-1]=i-1;
292  i--; j--;
293  } else {
294  h=val[i-1][j];
295  if(path[i-1][j]) h +=gap_open;
296 
297  v=val[i][j-1];
298  if(path[i][j-1]) v +=gap_open;
299 
300  if(v>=h) j--;
301  else i--;
302  }
303  }
304  }
305 
306  //+ss
307  void NWDP_TM(
308  std::vector < int > const secx,
309  std::vector < int > const secy,
310  int const len1, int const len2,
311  double gap_open, vector < int > & j2i)
312  {
313  //NW dynamic programming for alignment
314  //not a standard implementation of NW algorithm
315  //Input: secondary structure secx, secy, and gap_open
316  //Output: j2i[1:len2] \in {1:len1} U {-1}
317  //path[0:len1, 0:len2]=1,2,3, from diagonal, horizontal, vertical
318  int i, j;
319  double h, v, d;
320 
321  //initialization
322  val[0][0]=0;
323  for(i=0; i<=len1; i++) {
324  val[i][0]=0;
325  path[i][0]=false; //not from diagonal
326  }
327 
328  for(j=0; j<=len2; j++) {
329  val[0][j]=0;
330  path[0][j]=false; //not from diagonal
331  j2i[j]=-1; //all are not aligned, only use j2i[1:len2]
332  }
333 
334  //decide matrix and path
335  for(i=1; i<=len1; i++) {
336  for(j=1; j<=len2; j++) {
337  //d=val[i-1][j-1]+score[i][j]; //diagonal
338  if(secx[i-1]==secy[j-1]) {
339  d=val[i-1][j-1] + 1.0;
340  } else {
341  d=val[i-1][j-1];
342  }
343 
344  //symbol insertion in horizontal (= a gap in vertical)
345  h=val[i-1][j];
346  if(path[i-1][j]) //aligned in last position
347  h += gap_open;
348 
349  //symbol insertion in vertical
350  v=val[i][j-1];
351  if(path[i][j-1]) //aligned in last position
352  v += gap_open;
353 
354 
355  if(d>=h && d>=v) {
356  path[i][j]=true; //from diagonal
357  val[i][j]=d;
358  } else {
359  path[i][j]=false; //from horizontal
360  if(v>=h)
361  val[i][j]=v;
362  else
363  val[i][j]=h;
364  }
365  } //for i
366  } //for j
367 
368  //trace back to extract the alignment
369  i=len1; j=len2;
370  while(i>0 && j>0) {
371  if(path[i][j]) { //from diagonal
372  j2i[j-1]=i-1;
373  i--; j--;
374  } else {
375  h=val[i-1][j];
376  if(path[i-1][j]) h +=gap_open;
377 
378  v=val[i][j-1];
379  if(path[i][j-1]) v +=gap_open;
380 
381  if(v>=h) j--;
382  else i--;
383  }
384  }
385  }
386 
387  void
390  vector <core::Real> & xx) {
391  xx.resize(3);
392  xx[0]= x.x();
393  xx[1]= x.y();
394  xx[2]= x.z();
395  }
396 
397  void
400  vector <vector <core::Real> > & xx) {
401  xx.resize(3);
402  for (Size i = 0; i<3; ++i) {
403  xx[i].resize(3);
404  for (Size j = 0; j<3; ++j) {
405  xx[i][j]= x(i+1,j+1);
406  }
407  }
408  }
409 
410 
411  void
413  vector <core::Real> const x,
415  xx.x() = x[0];
416  xx.y() = x[1];
417  xx.z() = x[2];
418  }
419  void
421  vector <vector <core::Real> > const x,
423  for (Size i = 0; i<3; ++i) {
424  for (Size j = 0; j<3; ++j) {
425  xx(i+1,j+1) = x[i][j];
426  }
427  }
428  }
429 
430  void
432  vector < numeric::xyzVector <core::Real> > const x,
433  vector < vector < double > > & xx) {
434  xx.resize(x.size());
435  for (Size i=0;i<xx.size();++i) {
436  convert_xyz_to_vector(x[i],xx[i]);
437  }
438  }
439 
440 
441  // wrapper is a temp fix -yfsong
442  bool Kabsch(
443  vector < numeric::xyzVector <core::Real> > const x,
444  vector < numeric::xyzVector <core::Real> > const y,
445  int const n,
446  int const mode,
447  double *rms,
450  vector < vector < double > > xx;
451  convert_xyz_v_to_vectors(x,xx);
452 
453  vector < vector < double > > yy;
454  convert_xyz_v_to_vectors(y,yy);
455 
456  vector < double > tt;
457  convert_xyz_to_vector(t,tt);
458 
459  vector < vector < double > > uu;
460  convert_xyz_to_matrix(u,uu);
461 
462  bool retval =
463  Kabsch(xx,yy,n,mode,rms,tt,uu);
464  convert_vector_to_xyz(tt,t);
465  convert_matrix_to_xyz(uu,u);
466 
467  return retval;
468  }
469 
470 
471  // Implemetation of Kabsch algoritm for finding the best rotation matrix
472  // ---------------------------------------------------------------------------
473  // x - x(i,m) are coordinates of atom m in set x (input)
474  // y - y(i,m) are coordinates of atom m in set y (input)
475  // n - n is number of atom pairs (input)
476  // mode - 0:calculate rms only (input)
477  // 1:calculate rms,u,t (takes longer)
478  // rms - sum of w*(ux+t-y)**2 over all atom pairs (output)
479  // u - u(i,j) is rotation matrix for best superposition (output)
480  // t - t(i) is translation vector for best superposition (output)
481  bool Kabsch(
482  vector < vector < double > > const x,
483  vector < vector < double > > const y,
484  int const n,
485  int const mode,
486  double *rms,
487  vector < double > & t,
488  vector < vector < double > > & u ) {
489  int i, j, m, m1, l, k;
490  double e0, rms1, d, h, g;
491  double cth, sth, sqrth, p, det, sigma;
492  double xc[3], yc[3];
493  double a[3][3], b[3][3], r[3][3], e[3], rr[6], ss[6];
494  double sqrt3=1.73205080756888, tol=0.01;
495  int ip[]={0, 1, 3, 1, 2, 4, 3, 4, 5};
496  int ip2312[]={1, 2, 0, 1};
497 
498  int a_failed=0, b_failed=0;
499  double epsilon=0.00000001;
500 
501  //initializtation
502  *rms=0;
503  rms1=0;
504  e0=0;
505  for(i=0; i<3; i++) {
506  xc[i]=0.0;
507  yc[i]=0.0;
508  t[i]=0.0;
509  for(j=0; j<3; j++) {
510  u[i][j]=0.0;
511  r[i][j]=0.0;
512  a[i][j]=0.0;
513  if(i==j) {
514  u[i][j]=1.0;
515  a[i][j]=1.0;
516  }
517  }
518  }
519 
520  if(n<1) return false;
521 
522  //compute centers for vector sets x, y
523  for(i=0; i<n; i++) {
524  xc[0] += x[i][0];
525  xc[1] += x[i][1];
526  xc[2] += x[i][2];
527 
528  yc[0] += y[i][0];
529  yc[1] += y[i][1];
530  yc[2] += y[i][2];
531  }
532  for(i=0; i<3; i++) {
533  xc[i] = xc[i]/n;
534  yc[i] = yc[i]/n;
535  }
536 
537  //compute e0 and matrix r
538  for(m=0; m<n; m++) {
539  for (i=0; i<3; i++) {
540  e0 += (x[m][i]-xc[i])*(x[m][i]-xc[i])+\
541  (y[m][i]-yc[i])*(y[m][i]-yc[i]);
542  d = y[m][i] - yc[i];
543  for(j=0; j<3; j++) {
544  r[i][j] += d*(x[m][j] - xc[j]);
545  }
546  }
547  }
548 
549  //compute determinat of matrix r
550  det = r[0][0] * ( r[1][1]*r[2][2] - r[1][2]*r[2][1] )\
551  - r[0][1] * ( r[1][0]*r[2][2] - r[1][2]*r[2][0] )\
552  + r[0][2] * ( r[1][0]*r[2][1] - r[1][1]*r[2][0] );
553  sigma=det;
554 
555  //compute tras(r)*r
556  m = 0;
557  for(j=0; j<3; j++) {
558  for (i=0; i<=j; i++) {
559  rr[m]=r[0][i]*r[0][j]+r[1][i]*r[1][j]+r[2][i]*r[2][j];
560  m++;
561  }
562  }
563 
564  double spur=(rr[0]+rr[2]+rr[5]) / 3.0;
565  double cof = (((((rr[2]*rr[5] - rr[4]*rr[4]) + rr[0]*rr[5])\
566  - rr[3]*rr[3]) + rr[0]*rr[2]) - rr[1]*rr[1]) / 3.0;
567  det = det*det;
568 
569  for (i=0; i<3; i++) {
570  e[i]=spur;
571  }
572 
573  if(spur>0) {
574  d = spur*spur;
575  h = d - cof;
576  g = (spur*cof - det)/2.0 - spur*h;
577 
578  if(h>0) {
579  sqrth = sqrt(h);
580  d = h*h*h - g*g;
581  if(d<0.0) d=0.0;
582  d = atan2( sqrt(d), -g ) / 3.0;
583  cth = sqrth * cos(d);
584  sth = sqrth*sqrt3*sin(d);
585  e[0]= (spur + cth) + cth;
586  e[1]= (spur - cth) + sth;
587  e[2]= (spur - cth) - sth;
588 
589  if(mode!=0) {
590  for(l=0; l<3; l=l+2) {
591  d = e[l];
592  ss[0] = (d-rr[2]) * (d-rr[5]) - rr[4]*rr[4];
593  ss[1] = (d-rr[5]) * rr[1] + rr[3]*rr[4];
594  ss[2] = (d-rr[0]) * (d-rr[5]) - rr[3]*rr[3];
595  ss[3] = (d-rr[2]) * rr[3] + rr[1]*rr[4];
596  ss[4] = (d-rr[0]) * rr[4] + rr[1]*rr[3];
597  ss[5] = (d-rr[0]) * (d-rr[2]) - rr[1]*rr[1];
598 
599  if(fabs(ss[0])<=epsilon) ss[0]=0.0;
600  if(fabs(ss[1])<=epsilon) ss[1]=0.0;
601  if(fabs(ss[2])<=epsilon) ss[2]=0.0;
602  if(fabs(ss[3])<=epsilon) ss[3]=0.0;
603  if(fabs(ss[4])<=epsilon) ss[4]=0.0;
604  if(fabs(ss[5])<=epsilon) ss[5]=0.0;
605 
606  if( fabs(ss[0]) >= fabs(ss[2]) ) {
607  j=0;
608  if( fabs(ss[0]) < fabs(ss[5])) {
609  j = 2;
610  }
611  } else if ( fabs(ss[2]) >= fabs(ss[5]) ) {
612  j = 1;
613  } else {
614  j = 2;
615  }
616 
617  d = 0.0;
618  j = 3 * j;
619  for(i=0; i<3; i++) {
620  k=ip[i+j];
621  a[i][l] = ss[k];
622  d = d + ss[k]*ss[k];
623  }
624 
625  if( d > epsilon ) d = 1.0 / sqrt(d);
626  else d=0.0;
627  for(i=0; i<3; i++) {
628  a[i][l] = a[i][l] * d;
629  }
630  } //for l
631 
632  d = a[0][0]*a[0][2] + a[1][0]*a[1][2] + a[2][0]*a[2][2];
633  if ((e[0] - e[1]) > (e[1] - e[2])) {
634  m1=2; m=0;
635  } else {
636  m1=0; m=2;
637  }
638  p=0;
639  for(i=0; i<3; i++) {
640  a[i][m1] = a[i][m1] - d*a[i][m];
641  p = p + a[i][m1]*a[i][m1];
642  }
643  if( p <= tol ) {
644  p = 1.0;
645  for(i=0; i<3; i++) {
646  if (p < fabs(a[i][m]))
647  continue;
648  p = fabs( a[i][m] );
649  j = i;
650  }
651  k = ip2312[j];
652  l = ip2312[j+1];
653  p = sqrt( a[k][m]*a[k][m] + a[l][m]*a[l][m] );
654  if( p > tol ) {
655  a[j][m1] = 0.0;
656  a[k][m1] = -a[l][m]/p;
657  a[l][m1] = a[k][m]/p;
658  } else {
659  a_failed=1;
660  }
661  } else {
662  p = 1.0 / sqrt(p);
663  for(i=0; i<3; i++)
664  {
665  a[i][m1] = a[i][m1]*p;
666  }
667  }
668  if(a_failed!=1) {
669  a[0][1] = a[1][2]*a[2][0] - a[1][0]*a[2][2];
670  a[1][1] = a[2][2]*a[0][0] - a[2][0]*a[0][2];
671  a[2][1] = a[0][2]*a[1][0] - a[0][0]*a[1][2];
672  }
673  }//if(mode!=0)
674  }//h>0
675 
676  //compute b anyway
677  if(mode!=0 && a_failed!=1) { //a is computed correctly
678  //compute b
679  for(l=0; l<2; l++) {
680  d=0.0;
681  for(i=0; i<3; i++) {
682  b[i][l] = r[i][0]*a[0][l] + r[i][1]*a[1][l] + r[i][2]*a[2][l];
683  d = d + b[i][l]*b[i][l];
684  }
685  if( d > epsilon )
686  d = 1.0 / sqrt(d);
687  else
688  d = 0.0;
689  for(i=0; i<3; i++) {
690  b[i][l] = b[i][l]*d;
691  }
692  }
693  d = b[0][0]*b[0][1] + b[1][0]*b[1][1] + b[2][0]*b[2][1];
694  p=0.0;
695 
696  for(i=0; i<3; i++) {
697  b[i][1] = b[i][1] - d*b[i][0];
698  p += b[i][1]*b[i][1];
699  }
700 
701  if( p <= tol ) {
702  p = 1.0;
703  for(i=0; i<3; i++) {
704  if(p<fabs(b[i][0]))
705  continue;
706  p = fabs( b[i][0] );
707  j=i;
708  }
709  k = ip2312[j];
710  l = ip2312[j+1];
711  p = sqrt( b[k][0]*b[k][0] + b[l][0]*b[l][0] );
712  if( p > tol ) {
713  b[j][1] = 0.0;
714  b[k][1] = -b[l][0]/p;
715  b[l][1] = b[k][0]/p;
716  } else {
717  b_failed=1;
718  }
719  } else {
720  p = 1.0 / sqrt(p);
721  for(i=0; i<3; i++) {
722  b[i][1]=b[i][1]*p;
723  }
724  }
725  if(b_failed!=1) {
726  b[0][2] = b[1][0]*b[2][1] - b[1][1]*b[2][0];
727  b[1][2] = b[2][0]*b[0][1] - b[2][1]*b[0][0];
728  b[2][2] = b[0][0]*b[1][1] - b[0][1]*b[1][0];
729  //compute u
730  for(i=0; i<3; i++) {
731  for(j=0; j<3; j++) {
732  u[i][j] = b[i][0]*a[j][0] + b[i][1]*a[j][1]\
733  + b[i][2]*a[j][2];
734  }
735  }
736  }
737 
738  //compute t
739  for(i=0; i<3; i++) {
740  t[i] = ((yc[i] - u[i][0]*xc[0]) - u[i][1]*xc[1])\
741  - u[i][2]*xc[2];
742  }
743  }//if(mode!=0 && a_failed!=1)
744  } else {
745  //compute t
746  for(i=0; i<3; i++) {
747  t[i] = ((yc[i] - u[i][0]*xc[0]) - u[i][1]*xc[1]) - u[i][2]*xc[2];
748  }
749  }
750 
751  //compute rms
752  for(i=0; i<3; i++) {
753  if( e[i] < 0 ) e[i] = 0;
754  e[i] = sqrt( e[i] );
755  }
756  d = e[2];
757  if( sigma < 0.0 ) {
758  d = - d;
759  }
760  d = (d + e[1]) + e[0];
761  rms1 = (e0 - d) - d;
762  if( rms1 < 0.0 ) rms1 = 0.0;
763 
764  *rms=rms1;
765  return true;
766  }
767 
768  void load_pose_allocate_memory(core::pose::Pose pose1, core::pose::Pose pose2, std::list <core::Size> residue_list1, std::list <core::Size> residue_list2)
769  {
770  //------get length first------>
771  xlen=residue_list1.size();
772  ylen=residue_list2.size();
773  minlen=min(xlen, ylen);
774 
775  //------allocate memory for x and y------>
776  xa.resize(xlen);
777  seqx.resize(xlen);
778  secx.resize(xlen);
779  xresno.resize(xlen);
780 
781  ya.resize(ylen);
782  seqy.resize(ylen);
783  yresno.resize(ylen);
784  secy.resize(ylen);
785 
786  //------load data------>
787  read_pose(pose1, residue_list1, xa, seqx, xresno);
788  read_pose(pose2, residue_list2, ya, seqy, yresno);
789 
790  //------allocate memory for other temporary varialbes------>
791  r1.resize(minlen);
792  r2.resize(minlen);
793  xtm.resize(minlen);
794  ytm.resize(minlen);
795  xt.resize(xlen);
796 
797  ResizeArray(score, xlen+1, ylen+1);
798  ResizeArray(path, xlen+1, ylen+1);
799  ResizeArray(val, xlen+1, ylen+1);
800  }
801 
802  // 1, collect those residues with dis<d;
803  // 2, calculate TMscore
805  vector < numeric::xyzVector <core::Real> > const xa,
806  vector < numeric::xyzVector <core::Real> > const ya,
807  int const n_ali,
808  double const d,
809  vector <int> & i_ali,
810  double *score1,
811  int score_sum_method ) {
812  double score_sum=0, di;
813  double d_tmp=d*d;
814  double d02=d0*d0;
815  double score_d8_cut = score_d8*score_d8;
816 
817  int i, n_cut, inc=0;
818 
819  while(1) {
820  n_cut=0;
821  score_sum=0;
822  for(i=0; i<n_ali; i++) {
823  di = dist(xa[i], ya[i]);
824  if(di<d_tmp) {
825  i_ali[n_cut]=i;
826  n_cut++;
827  }
828  if(score_sum_method==8) {
829  if(di<=score_d8_cut) {
830  score_sum += 1/(1+di/d02);
831  }
832  } else {
833  score_sum += 1/(1+di/d02);
834  }
835  }
836 
837  //there are not enough feasible pairs, reliefe the threshold
838  if(n_cut<3 && n_ali>3) {
839  inc++;
840  double dinc=(d+inc*0.5);
841  d_tmp = dinc * dinc;
842  } else {
843  break;
844  }
845  }
846 
847  *score1=score_sum/Lnorm;
848  return n_cut;
849  }
850 
851  // TMscore search engine
852  // input: two aligned vector sets: x, y
853  // scale parameter d0
854  // simplify_step: 1 or 40 or other integers
855  // score_sum_method: 0 for score over all pairs
856  // 8 for socre over the pairs with dist<score_d8
857  // output: the best rotaion matrix t0, u0 that results in highest TMscore
859  vector < numeric::xyzVector <core::Real> > const xtm,
860  vector < numeric::xyzVector <core::Real> > const ytm,
861  int Lali,
864  int const simplify_step,
865  int const score_sum_method,
866  double *Rcomm ) {
867  int i, m;
868  double score_max, score, rmsd;
869  const int kmax=Lali;
870  vector <int> k_ali(kmax);
871  int ka, k;
874  double d;
875 
876  //iterative parameters
877  int n_it=20; //maximum number of iterations
878  const int n_init_max=6; //maximum number of different fragment length
879  vector <int> L_ini(n_init_max); //fragment lengths, Lali, Lali/2, Lali/4 ... 4
880  int L_ini_min=4;
881  if(Lali<4) L_ini_min=Lali;
882  int n_init=0, i_init;
883  for(i=0; i<n_init_max-1; i++) {
884  n_init++;
885  L_ini[i]=(int) (Lali/pow(2.0, (double) i));
886  if(L_ini[i]<=L_ini_min) {
887  L_ini[i]=L_ini_min;
888  break;
889  }
890  }
891  if(i==n_init_max-1) {
892  n_init++;
893  L_ini[i]=L_ini_min;
894  }
895 
896  //find the maximum score starting from local structures superposition
897  score_max=-1;
898  vector <int> i_ali(kmax);
899  int n_cut;
900  int L_frag; //fragment length
901  int iL_max; //maximum starting postion for the fragment
902  for(i_init=0; i_init<n_init; i_init++) {
903  L_frag=L_ini[i_init];
904  iL_max=Lali-L_frag;
905 
906  i=0;
907  while(1) {
908  //extract the fragment starting from position i
909  ka=0;
910  for(k=0; k<L_frag; k++) {
911  int kk=k+i;
912  r1[k]=xtm[kk];
913  r2[k]=ytm[kk];
914  k_ali[ka]=kk;
915  ka++;
916  }
917 
918  //extract rotation matrix based on the fragment
919  Kabsch(r1, r2, L_frag, 1, &rmsd, t, u);
920  if(i_init==0) {
921  *Rcomm=sqrt(rmsd/Lali);
922  }
923  do_rotation(xtm, xt, Lali, t, u);
924 
925  //get subsegment of this fragment
926  d=d0_search-1;
927  n_cut=score_fun8(xt, ytm, Lali, d, i_ali, &score, score_sum_method);
928  if(score>score_max) {
929  score_max=score;
930 
931  //save the rotation matrix
932  t0 = t;
933  u0 = u;
934  }
935 
936  //try to extend the alignment iteratively
937  d=d0_search+1;
938  for(int it=0; it<n_it; it++) {
939  ka=0;
940  for(k=0; k<n_cut; k++) {
941  m=i_ali[k];
942  r1[k]=xtm[m];
943  r2[k]=ytm[m];
944 
945  k_ali[ka]=m;
946  ka++;
947  }
948  //extract rotation matrix based on the fragment
949  Kabsch(r1, r2, n_cut, 1, &rmsd, t, u);
950  do_rotation(xtm, xt, Lali, t, u);
951  n_cut=score_fun8(xt, ytm, Lali, d, i_ali, &score, score_sum_method);
952  if(score>score_max) {
953  score_max=score;
954 
955  //save the rotation matrix
956  t0 = t;
957  u0 = u;
958  }
959 
960  //check if it converges
961  if(n_cut==ka) {
962  for(k=0; k<n_cut; k++) {
963  if(i_ali[k]!=k_ali[k]) {
964  break;
965  }
966  }
967  if(k==n_cut) {
968  break; //stop iteration
969  }
970  }
971  } //for iteration
972 
973  if(i<iL_max) {
974  i=i+simplify_step; //shift the fragment
975  if(i>iL_max) i=iL_max; //do this to use the last missed fragment
976  } else if(i>=iL_max) {
977  break;
978  }
979  }//while(1)
980  }//for(i_init...)
981  return score_max;
982  }
983 
984  //Comprehensive TMscore search engine
985  // input: two vector sets: x, y
986  // an alignment invmap0[] between x and y
987  // simplify_step: 1 or 40 or other integers
988  // score_sum_method: 0 for score over all pairs
989  // 8 for socre over the pairs with dist<score_d8
990  // output: the best rotaion matrix t, u that results in highest TMscore
992  vector < numeric::xyzVector <core::Real> > const x,
993  vector < numeric::xyzVector <core::Real> > const y,
994  int const,
995  int const y_len,
996  vector < int > const invmap0,
999  int simplify_step,
1000  int score_sum_method) {
1001  //x is model, y is template, try to superpose onto y
1002  int i, j, k;
1003  double tmscore;
1004  double rmsd;
1005 
1006  k=0;
1007  for(i=0; i<y_len; i++) {
1008  j=invmap0[i];
1009  if(j>=0) { //aligned
1010  xtm[k] = x[j];
1011  ytm[k] = y[i];
1012  k++;
1013  }
1014  }
1015 
1016  //detailed search 40-->1
1017  tmscore=TMscore8_search(xtm, ytm, k, t, u, simplify_step, score_sum_method, &rmsd);
1018  return tmscore;
1019  }
1020 
1021 
1022  //compute the score quickly in three iterations
1024  vector < numeric::xyzVector <core::Real> > const x,
1025  vector < numeric::xyzVector <core::Real> > const y,
1026  int const , int const y_len, vector < int > const invmap) {
1027  double rms, tmscore, tmscore1, tmscore2;
1028  int i, j, k=0;
1029 
1030  for(j=0; j<y_len; j++) {
1031  i=invmap[j];
1032  if(i>=0) {
1033  r1[k]=x[i];
1034  r2[k]=y[j];
1035  xtm[k]=x[i];
1036  ytm[k]=y[j];
1037 
1038  k++;
1039  } else if(i!=-1) {
1040  PrintErrorAndQuit("Wrong map!\n");
1041  }
1042  }
1043  Kabsch(r1, r2, k, 1, &rms, t, u);
1044 
1045  //evaluate score
1046  double di;
1047  const int len=k;
1048  vector <double> dis(len);
1049  double d00=d0_search;
1050  double d002=d00*d00;
1051  double d02=d0*d0;
1052 
1053  int n_ali=k;
1055  tmscore=0;
1056  for(k=0; k<n_ali; k++) {
1057  transform(t, u, xtm[k], xrot);
1058  di=dist(xrot, ytm[k]);
1059  dis[k]=di;
1060  tmscore += 1/(1+di/d02);
1061  }
1062 
1063  //second iteration
1064  double d002t=d002;
1065  while(1) {
1066  j=0;
1067  for(k=0; k<n_ali; k++) {
1068  if(dis[k]<=d002t) {
1069  r1[j]=xtm[k];
1070  r2[j]=ytm[k];
1071 
1072  j++;
1073  }
1074  }
1075 
1076  //there are not enough feasible pairs, relieve the threshold
1077  if(j<3 && n_ali>3) {
1078  d002t += 0.5;
1079  } else {
1080  break;
1081  }
1082  }
1083 
1084  if(n_ali!=j) {
1085  Kabsch(r1, r2, j, 1, &rms, t, u);
1086  tmscore1=0;
1087  for(k=0; k<n_ali; k++) {
1088  transform(t, u, xtm[k], xrot);
1089  di=dist(xrot, ytm[k]);
1090  dis[k]=di;
1091  tmscore1 += 1/(1+di/d02);
1092  }
1093 
1094  //third iteration
1095  d002t=d002+1;
1096 
1097  while(1) {
1098  j=0;
1099  for(k=0; k<n_ali; k++) {
1100  if(dis[k]<=d002t) {
1101  r1[j]=xtm[k];
1102  r2[j]=ytm[k];
1103 
1104  j++;
1105  }
1106  }
1107 
1108  //there are not enough feasible pairs, relieve the threshold
1109  if(j<3 && n_ali>3) {
1110  d002t += 0.5;
1111  } else {
1112  break;
1113  }
1114  }
1115 
1116  //evaluate the score
1117  Kabsch(r1, r2, j, 1, &rms, t, u);
1118  tmscore2=0;
1119  for(k=0; k<n_ali; k++) {
1120  transform(t, u, xtm[k], xrot);
1121  di=dist(xrot, ytm[k]);
1122  tmscore2 += 1/(1+di/d02);
1123  }
1124  } else {
1125  tmscore1=tmscore;
1126  tmscore2=tmscore;
1127  }
1128 
1129  if(tmscore1>=tmscore) tmscore=tmscore1;
1130  if(tmscore2>=tmscore) tmscore=tmscore2;
1131  return tmscore; // no need to normalize this score because it will not be used for latter scoring
1132  }
1133 
1134 
1135  //perform gapless threading to find the best initial alignment
1136  //input: x, y, x_len, y_len
1137  //output: y2x0 stores the best alignment: e.g.,
1138  //y2x0[j]=i means:
1139  //the jth element in y is aligned to the ith element in x if i>=0
1140  //the jth element in y is aligned to a gap in x if i==-1
1141  double get_initial(
1142  vector < numeric::xyzVector <core::Real> > const x,
1143  vector < numeric::xyzVector <core::Real> > const y,
1144  int const x_len,
1145  int const y_len,
1146  vector < int > & y2x ) {
1147  int min_len=getmin(x_len, y_len);
1148  if(min_len<=5) {
1149  return 0.;
1150  }
1151 
1152  int min_ali= min_len/2; //minimum size of considered fragment
1153  if (min_ali<=5)
1154  min_ali=5;
1155  int n1, n2;
1156  n1 = -y_len+min_ali;
1157  n2 = x_len-min_ali;
1158 
1159  int i, j, k, k_best;
1160  double tmscore, tmscore_max=-1;
1161 
1162  k_best=n1;
1163  for(k=n1; k<=n2; k++) {
1164  //get the map
1165  for(j=0; j<y_len; j++) {
1166  i=j+k;
1167  if(i>=0 && i<x_len) {
1168  y2x[j]=i;
1169  } else {
1170  y2x[j]=-1;
1171  }
1172  }
1173 
1174  //evaluate the map quickly in three iterations
1175  //this is not real tmscore, it is used to evaluate the goodness of the initial alignment
1176  tmscore=get_score_fast(x, y, x_len, y_len, y2x);
1177  if(tmscore>=tmscore_max) {
1178  tmscore_max=tmscore;
1179  k_best=k;
1180  }
1181  }
1182 
1183  //extract the best map
1184  k=k_best;
1185  for(j=0; j<y_len; j++) {
1186  i=j+k;
1187  if(i>=0 && i<x_len) {
1188  y2x[j]=i;
1189  } else {
1190  y2x[j]=-1;
1191  }
1192  }
1193  return tmscore_max;
1194  }
1195 
1196  void smooth(vector < int > & sec, int const len) {
1197  int i, j;
1198  //smooth single --x-- => -----
1199  for(i=2; i<len-2; i++) {
1200  if(sec[i]==2 || sec[i]==4) {
1201  j=sec[i];
1202  if(sec[i-2] != j) {
1203  if(sec[i-1] != j) {
1204  if(sec[i+1] != j) {
1205  if(sec[i+2] != j) {
1206  sec[i]=1;
1207  }
1208  }
1209  }
1210  }
1211  }
1212  }
1213 
1214  // smooth double
1215  // --xx-- => ------
1216  for(i=0; i<len-5; i++) {
1217  //helix
1218  if(sec[i] != 2) {
1219  if(sec[i+1] != 2) {
1220  if(sec[i+2] == 2) {
1221  if(sec[i+3] == 2) {
1222  if(sec[i+4] != 2) {
1223  if(sec[i+5] != 2) {
1224  sec[i+2]=1;
1225  sec[i+3]=1;
1226  }
1227  }
1228  }
1229  }
1230  }
1231  }
1232 
1233  //beta
1234  if(sec[i] != 4) {
1235  if(sec[i+1] != 4) {
1236  if(sec[i+2] ==4) {
1237  if(sec[i+3] == 4) {
1238  if(sec[i+4] != 4) {
1239  if(sec[i+5] != 4) {
1240  sec[i+2]=1;
1241  sec[i+3]=1;
1242  }
1243  }
1244  }
1245  }
1246  }
1247  }
1248  }
1249 
1250  //smooth connect
1251  for(i=0; i<len-2; i++) {
1252  if(sec[i] == 2) {
1253  if(sec[i+1] != 2) {
1254  if(sec[i+2] == 2) {
1255  sec[i+1]=2;
1256  }
1257  }
1258  }
1259  else if(sec[i] == 4) {
1260  if(sec[i+1] != 4) {
1261  if(sec[i+2] == 4) {
1262  sec[i+1]=4;
1263  }
1264  }
1265  }
1266  }
1267  }
1268 
1269  int sec_str(double dis13, double dis14, double dis15, double dis24, double dis25, double dis35) {
1270  int s=1;
1271 
1272  double delta=2.1;
1273  if(fabs(dis15-6.37)<delta) {
1274  if(fabs(dis14-5.18)<delta) {
1275  if(fabs(dis25-5.18)<delta) {
1276  if(fabs(dis13-5.45)<delta) {
1277  if(fabs(dis24-5.45)<delta) {
1278  if(fabs(dis35-5.45)<delta) {
1279  s=2; //helix
1280  return s;
1281  }
1282  }
1283  }
1284  }
1285  }
1286  }
1287 
1288  delta=1.42;
1289  if(fabs(dis15-13)<delta) {
1290  if(fabs(dis14-10.4)<delta) {
1291  if(fabs(dis25-10.4)<delta) {
1292  if(fabs(dis13-6.1)<delta) {
1293  if(fabs(dis24-6.1)<delta) {
1294  if(fabs(dis35-6.1)<delta) {
1295  s=4; //strand
1296  return s;
1297  }
1298  }
1299  }
1300  }
1301  }
1302  }
1303 
1304  if(dis15 < 8) {
1305  s=3; //turn
1306  }
1307 
1308  return s;
1309  }
1310 
1311  //1->coil, 2->helix, 3->turn, 4->strand
1312  void make_sec(std::vector < numeric::xyzVector <core::Real> > const x, int const len, vector < int > & sec) {
1313  int j1, j2, j3, j4, j5;
1314  double d13, d14, d15, d24, d25, d35;
1315  for(int i=0; i<len; i++) {
1316  sec[i]=1;
1317  j1=i-2;
1318  j2=i-1;
1319  j3=i;
1320  j4=i+1;
1321  j5=i+2;
1322 
1323  if(j1>=0 && j5<len) {
1324  d13=sqrt(dist(x[j1], x[j3]));
1325  d14=sqrt(dist(x[j1], x[j4]));
1326  d15=sqrt(dist(x[j1], x[j5]));
1327  d24=sqrt(dist(x[j2], x[j4]));
1328  d25=sqrt(dist(x[j2], x[j5]));
1329  d35=sqrt(dist(x[j3], x[j5]));
1330  sec[i]=sec_str(d13, d14, d15, d24, d25, d35);
1331  }
1332  }
1333  smooth(sec, len);
1334  }
1335 
1336  //get initial alignment from secondary structure alignment
1337  //input: x, y, x_len, y_len
1338  //output: y2x stores the best alignment: e.g.,
1339  //y2x[j]=i means:
1340  //the jth element in y is aligned to the ith element in x if i>=0
1341  //the jth element in y is aligned to a gap in x if i==-1
1343  std::vector < numeric::xyzVector <core::Real> > const x,
1344  std::vector < numeric::xyzVector <core::Real> > const y,
1345  int const x_len, int const y_len,
1346  std::vector < int > & y2x ) {
1347  //assign secondary structures
1348  make_sec(x, x_len, secx);
1349  make_sec(y, y_len, secy);
1350 
1351  double gap_open=-1.0;
1352  NWDP_TM(secx, secy, x_len, y_len, gap_open, y2x);
1353  }
1354 
1355 
1356  // get_initial5 in TMalign
1357  //get initial alignment of local structure superposition
1358  //input: x, y, x_len, y_len
1359  //output: y2x stores the best alignment: e.g.,
1360  //y2x[j]=i means:
1361  //the jth element in y is aligned to the ith element in x if i>=0
1362  //the jth element in y is aligned to a gap in x if i==-1
1364  std::vector < numeric::xyzVector <core::Real> > const x,
1365  std::vector < numeric::xyzVector <core::Real> > const y,
1366  int const x_len,
1367  int const y_len,
1368  std::vector < int > & y2x ) {
1369  double GL, rmsd;
1372 
1373  double d01=d0+1.5;
1374  if(d01 < D0_MIN) d01=D0_MIN;
1375  double d02=d01*d01;
1376 
1377  double GLmax=0;
1378  int n_frag=20; //length of fragment for superposition
1379  int ns=20; //tail length to discard
1380  vector < int > invmap(y_len+1);
1381 
1382  int aL=getmin(x_len, y_len);
1383  if(aL>250) {
1384  n_frag=50;
1385  } else if(aL>200) {
1386  n_frag=40;
1387  } else if(aL>150) {
1388  n_frag=30;
1389  } else {
1390  n_frag=20;
1391  }
1392 
1393  int smallest=aL/3; // I change here from aL/2 to aL/3
1394 
1395  if(n_frag>smallest) n_frag=smallest;
1396  if(ns>smallest) ns=smallest;
1397 
1398  int m1=x_len-n_frag-ns;
1399  int m2=y_len-n_frag-ns;
1400 
1401  bool flag=false;
1402 
1403  for(int ii=0; ii<y_len; ii++) {
1404  y2x[ii]=-1;
1405  }
1406 
1407  int count=0;
1408  for(int i=ns-1; i<m1; i=i+n_frag) { //index starts from 0, different from FORTRAN
1409  for(int j=ns-1; j<m2; j=j+n_frag) {
1410  for(int k=0; k<n_frag; k++) { //fragment in y
1411  r1[k]=x[k+i];
1412  r2[k]=y[k+j];
1413  }
1414 
1415  Kabsch(r1, r2, n_frag, 1, &rmsd, t, u);
1416  count++;
1417 
1418  double gap_open=0.0;
1419  NWDP_TM(x, y, x_len, y_len, t, u, d02, gap_open, invmap);
1420  GL=get_score_fast(x, y, x_len, y_len, invmap);
1421  if(GL>GLmax) {
1422  GLmax=GL;
1423  for(int ii=0; ii<y_len; ii++) {
1424  y2x[ii]=invmap[ii];
1425  }
1426  flag=true;
1427  }
1428  }
1429  }
1430 
1431  return flag;
1432  }
1433 
1434  //with invmap(i) calculate score(i,j) using RMSD rotation
1436  std::vector < numeric::xyzVector <core::Real> > const x,
1437  std::vector < numeric::xyzVector <core::Real> > const y,
1438  int const x_len,
1439  int const y_len,
1440  std::vector < int > const y2x ) {
1443  double rmsd, dij;
1444  double d01=d0+1.5;
1445  if(d01 < D0_MIN) d01=D0_MIN;
1446  double d02=d01*d01;
1447 
1449  int i, k=0;
1450  for(int j=0; j<y_len; j++) {
1451  i=y2x[j];
1452  if(i>=0) {
1453  r1[k]=x[i];
1454  r2[k]=y[j];
1455  k++;
1456  }
1457  }
1458  Kabsch(r1, r2, k, 1, &rmsd, t, u);
1459 
1460  for(int ii=0; ii<x_len; ii++) {
1461  transform(t, u, x[ii], xx);
1462  for(int jj=0; jj<y_len; jj++) {
1463  dij=dist(xx, y[jj]);
1464  score[ii+1][jj+1] = 1.0/(1+dij/d02);
1465  }
1466  }
1467  }
1468 
1470  vector < numeric::xyzVector <core::Real> > const x,
1471  vector < numeric::xyzVector <core::Real> > const y,
1472  int const x_len,
1473  int const y_len,
1474  vector < int > const y2x ) {
1477  double rmsd, dij;
1478  double d01=d0+1.5;
1479  if(d01 < D0_MIN) d01=D0_MIN;
1480  double d02=d01*d01;
1481 
1483  int i, k=0;
1484  for(int j=0; j<y_len; j++) {
1485  i=y2x[j];
1486  if(i>=0) {
1487  r1[k]=x[i];
1488  r2[k]=y[j];
1489 
1490  k++;
1491  }
1492  }
1493  Kabsch(r1, r2, k, 1, &rmsd, t, u);
1494 
1495  for(int ii=0; ii<x_len; ii++) {
1496  transform(t, u, x[ii], xx);
1497  for(int jj=0; jj<y_len; jj++) {
1498  dij=dist(xx, y[jj]);
1499  if(secx[ii]==secy[jj]) {
1500  score[ii+1][jj+1] = 1.0/(1+dij/d02) + 0.5;
1501  } else {
1502  score[ii+1][jj+1] = 1.0/(1+dij/d02);
1503  }
1504  }
1505  }
1506  }
1507 
1508  //get initial alignment from secondary structure and previous alignments
1509  //input: x, y, x_len, y_len
1510  //output: y2x stores the best alignment: e.g.,
1511  //y2x[j]=i means:
1512  //the jth element in y is aligned to the ith element in x if i>=0
1513  //the jth element in y is aligned to a gap in x if i==-1
1515  std::vector < numeric::xyzVector <core::Real> > const x,
1516  std::vector < numeric::xyzVector <core::Real> > const y,
1517  int const x_len,
1518  int const y_len,
1519  std::vector < int > & y2x0,
1520  std::vector < int > & y2x ) {
1521  //create score matrix for DP
1522  score_matrix_rmsd_sec(x, y, x_len, y_len, y2x0);
1523  double gap_open=-1.0;
1524  NWDP_TM(x_len, y_len, gap_open, y2x);
1525  }
1526 
1527 
1529  std::vector < numeric::xyzVector <core::Real> > const x,
1530  std::vector < int > const resno,
1531  int const len, int *start_max, int *end_max) {
1532  int r_min, fra_min=4; //minimum fragment for search
1533  double d;
1534  int start;
1535  int Lfr_max=0, flag;
1536 
1537  r_min= (int) (len*1.0/3.0); //minimum fragment, in case too small protein
1538  if(r_min > fra_min) r_min=fra_min;
1539 
1540  int inc=0;
1541  double dcu0_cut=dcu0*dcu0;;
1542  double dcu_cut=dcu0_cut;
1543 
1544  while(Lfr_max < r_min) {
1545  Lfr_max=0;
1546  int j=1; //number of residues at nf-fragment
1547  start=0;
1548  for(int i=1; i<len; i++) {
1549  d = dist(x[i-1], x[i]);
1550  flag=0;
1551  if(dcu_cut>dcu0_cut) {
1552  if(d<dcu_cut) {
1553  flag=1;
1554  }
1555  }
1556  else if(resno[i] == (resno[i-1]+1)) { //necessary??
1557  if(d<dcu_cut) {
1558  flag=1;
1559  }
1560  }
1561 
1562  if(flag==1) {
1563  j++;
1564 
1565  if(i==(len-1)) {
1566  if(j > Lfr_max) {
1567  Lfr_max=j;
1568  *start_max=start;
1569  *end_max=i;
1570  }
1571  j=1;
1572  }
1573  } else {
1574  if(j>Lfr_max) {
1575  Lfr_max=j;
1576  *start_max=start;
1577  *end_max=i-1;
1578  }
1579 
1580  j=1;
1581  start=i;
1582  }
1583  }// for i;
1584 
1585  if(Lfr_max < r_min) {
1586  inc++;
1587  double dinc=pow(1.1, (double) inc) * dcu0;
1588  dcu_cut= dinc*dinc;
1589  }
1590  }//while <;
1591  }
1592 
1593  //perform fragment gapless threading to find the best initial alignment
1594  //input: x, y, x_len, y_len
1595  //output: y2x0 stores the best alignment: e.g.,
1596  //y2x0[j]=i means:
1597  //the jth element in y is aligned to the ith element in x if i>=0
1598  //the jth element in y is aligned to a gap in x if i==-1
1600  std::vector < numeric::xyzVector < core::Real > > const x,
1601  std::vector < numeric::xyzVector < core::Real > > const y,
1602  int const x_len,
1603  int const y_len,
1604  vector < int > const xresno,
1605  vector < int > const yresno,
1606  vector < int > & y2x ) {
1607  int fra_min=4; //minimum fragment for search
1608  int fra_min1=fra_min-1; //cutoff for shift, save time
1609  int xstart=0, ystart=0, xend=0, yend=0;
1610 
1611  find_max_frag(x, xresno, x_len, &xstart, &xend);
1612  find_max_frag(y, yresno, y_len, &ystart, &yend);
1613 
1614  int Lx = xend-xstart+1;
1615  int Ly = yend-ystart+1;
1616  vector < int > ifr, y2x_;
1617  int L_fr=getmin(Lx, Ly);
1618  ifr.resize(L_fr);
1619  y2x_.resize(y_len+1);
1620 
1621  //select what piece will be used (this may araise ansysmetry, but
1622  //only when L1=L2 and Lfr1=Lfr2 and L1 ne Lfr1
1623  //if L1=Lfr1 and L2=Lfr2 (normal proteins), it will be the same as initial1
1624  if(Lx<Ly || (Lx==Ly && x_len<=y_len)) {
1625  for(int i=0; i<L_fr; i++) {
1626  ifr[i]=xstart+i;
1627  }
1628  } else if(Lx>Ly || (Lx==Ly && x_len>y_len)) {
1629  for(int i=0; i<L_fr; i++) {
1630  ifr[i]=ystart+i;
1631  }
1632  }
1633 
1634  int L0=getmin(x_len, y_len); //non-redundant to get_initial1
1635  if(L_fr==L0) {
1636  int n1= (int)(L0*0.1); //my index starts from 0
1637  int n2= (int)(L0*0.89);
1638 
1639  int j=0;
1640  for(int i=n1; i<= n2; i++) {
1641  ifr[j]=ifr[i];
1642  j++;
1643  }
1644  L_fr=j;
1645  }
1646 
1647  //gapless threading for the extracted fragment
1648  double tmscore, tmscore_max=-1;
1649 
1650  if(Lx<Ly || (Lx==Ly && x_len<=y_len)) {
1651  int L1=L_fr;
1652  int min_len=getmin(L1, y_len);
1653  int min_ali= (int) (min_len/2.5); //minimum size of considered fragment
1654  if(min_ali<=fra_min1) min_ali=fra_min1;
1655  int n1, n2;
1656  n1 = -y_len+min_ali;
1657  n2 = L1-min_ali;
1658 
1659  int i, j, k;
1660  for(k=n1; k<=n2; k++) {
1661  //get the map
1662  for(j=0; j<y_len; j++) {
1663  i=j+k;
1664  if(i>=0 && i<L1) {
1665  y2x_[j]=ifr[i];
1666  } else {
1667  y2x_[j]=-1;
1668  }
1669  }
1670 
1671  //evaluate the map quickly in three iterations
1672  tmscore=get_score_fast(x, y, x_len, y_len, y2x_);
1673  if(tmscore>=tmscore_max) {
1674  tmscore_max=tmscore;
1675  for(j=0; j<y_len; j++) {
1676  y2x[j]=y2x_[j];
1677  }
1678  }
1679  }
1680  } else {
1681  int L2=L_fr;
1682  int min_len=getmin(x_len, L2);
1683  int min_ali= (int) (min_len/2.5); //minimum size of considered fragment
1684  if(min_ali<=fra_min1) min_ali=fra_min1;
1685  int n1, n2;
1686  n1 = -L2+min_ali;
1687  n2 = x_len-min_ali;
1688 
1689  int i, j, k;
1690  for(k=n1; k<=n2; k++) {
1691  //get the map
1692  for(j=0; j<y_len; j++) {
1693  y2x_[j]=-1;
1694  }
1695 
1696  for(j=0; j<L2; j++) {
1697  i=j+k;
1698  if(i>=0 && i<x_len) {
1699  y2x_[ifr[j]]=i;
1700  }
1701  }
1702 
1703  //evaluate the map quickly in three iterations
1704  tmscore=get_score_fast(x, y, x_len, y_len, y2x_);
1705  if(tmscore>=tmscore_max) {
1706  tmscore_max=tmscore;
1707  for(j=0; j<y_len; j++) {
1708  y2x[j]=y2x_[j];
1709  }
1710  }
1711  }
1712  }
1713  return tmscore_max;
1714  }
1715 
1716 
1717  //heuristic run of dynamic programing iteratively to find the best alignment
1718  //input: initial rotation matrix t, u
1719  // vectors x and y, d0
1720  //output: best alignment that maximizes the TMscore, will be stored in invmap
1721  double DP_iter(
1722  vector < numeric::xyzVector < core::Real > > const x,
1723  vector < numeric::xyzVector < core::Real > > const y,
1724  int const x_len, int const y_len,
1727  vector < int > & invmap0,
1728  int const g1, int const g2, int const iteration_max ) {
1729  double gap_open[2]={-0.6, 0};
1730  double rmsd;
1731  vector < int > invmap(y_len+1);
1732  int iteration, i, j, k;
1733  double tmscore, tmscore_max, tmscore_old=0;
1734  int score_sum_method=8, simplify_step=40;
1735  tmscore_max=-1;
1736 
1737  double d02=d0*d0;
1738  for(int g=g1; g<g2; g++) {
1739  for(iteration=0; iteration<iteration_max; iteration++) {
1740  NWDP_TM(x, y, x_len, y_len, t, u, d02, gap_open[g], invmap);
1741 
1742  k=0;
1743  for(j=0; j<y_len; j++) {
1744  i=invmap[j];
1745 
1746  if(i>=0) { //aligned
1747  xtm[k]=x[i];
1748  ytm[k]=y[j];
1749  k++;
1750  }
1751  }
1752  tmscore=TMscore8_search(xtm, ytm, k, t, u, simplify_step, score_sum_method, &rmsd);
1753 
1754  if(tmscore>tmscore_max) {
1755  tmscore_max=tmscore;
1756  for(i=0; i<y_len; i++) {
1757  invmap0[i]=invmap[i];
1758  }
1759  }
1760 
1761  if(iteration>0) {
1762  if(fabs(tmscore_old-tmscore)<0.000001) {
1763  break;
1764  }
1765  }
1766  tmscore_old=tmscore;
1767  }// for iteration
1768  }//for gapopen
1769 
1770  return tmscore_max;
1771  }
1772 
1773 
1775  core::pose::Pose const & pose1,
1776  core::pose::Pose const & pose2,
1777  core::Size & n_mapped_residues,
1779  std::list <core::Size> residue_list1;
1780  std::list <core::Size> residue_list2;
1781  for ( Size ires=1; ires<= pose1.total_residue(); ++ires ) {
1782  if ( !pose1.residue(ires).is_protein() ) continue;
1783  residue_list1.push_back(ires);
1784  }
1785  for ( Size ires=1; ires<= pose2.total_residue(); ++ires ) {
1786  if ( !pose2.residue(ires).is_protein() ) continue;
1787  residue_list2.push_back(ires);
1788  }
1789 
1790  return alignment2AtomMap(pose1, pose2, residue_list1, residue_list2, n_mapped_residues, atom_map);
1791  }
1792 
1793 
1795  core::pose::Pose const & pose,
1796  core::pose::Pose const & ref_pose,
1797  std::list <core::Size> const & residue_list,
1798  std::list <core::Size> const & ref_residue_list,
1799  core::Size & n_mapped_residues,
1801  double seq_id;
1802  int k;
1803  double d;
1804  do_rotation(xa, xt, xlen, t, u);
1805  seq_id=0;
1806 
1807  n_mapped_residues = 0;
1808  for(k=0; k<n_ali8_; k++) {
1809  d=sqrt(dist(xt[m1_[k]], ya[m2_[k]]));
1810  if(d<d0_out_) {
1811  std::list<core::Size>::const_iterator it1 = residue_list.begin(); advance(it1, m1_[k]);
1812  core::Size ires = *it1;
1813  core::id::AtomID const id1( pose.residue_type(ires).atom_index("CA"), ires );
1814 
1815  std::list<core::Size>::const_iterator it2 = ref_residue_list.begin(); advance(it2, m2_[k]);
1816  core::Size jres = *it2;
1817  core::id::AtomID const id2( ref_pose.residue_type(jres).atom_index("CA"), jres );
1818 
1819  atom_map[ id1 ] = id2;
1820  ++n_mapped_residues;
1821  }
1822  }
1823  }
1824 
1826  string & seqxA,
1827  string & seqyA,
1828  string & seqM ) {
1829  double seq_id;
1830  int i, j, k;
1831  double d;
1832 
1833  int ali_len=xlen+ylen; //maximum length of alignment
1834  seqM.resize(ali_len);
1835  seqxA.resize(ali_len);
1836  seqyA.resize(ali_len);
1837 
1838  do_rotation(xa, xt, xlen, t, u);
1839 
1840  seq_id=0;
1841  int kk=0, i_old=0, j_old=0;
1842 
1843  for(k=0; k<n_ali8_; k++) {
1844  for(i=i_old; i<m1_[k]; i++) {
1845  //align x to gap
1846  seqxA[kk]=seqx[i];
1847  seqyA[kk]='-';
1848  seqM[kk]=' ';
1849  kk++;
1850  }
1851 
1852  for(j=j_old; j<m2_[k]; j++) {
1853  //align y to gap
1854  seqxA[kk]='-';
1855  seqyA[kk]=seqy[j];
1856  seqM[kk]=' ';
1857  kk++;
1858  }
1859 
1860  seqxA[kk]=seqx[m1_[k]];
1861  seqyA[kk]=seqy[m2_[k]];
1862  if(seqxA[kk]==seqyA[kk]) {
1863  seq_id++;
1864  }
1865  d = sqrt(dist(xt[m1_[k]], ya[m2_[k]]));
1866  if(d<d0_out_) {
1867  seqM[kk]=':';
1868  } else {
1869  seqM[kk]='.';
1870  }
1871  kk++;
1872  i_old=m1_[k]+1;
1873  j_old=m2_[k]+1;
1874  }
1875 
1876  //tail
1877  for(i=i_old; i<xlen; i++) {
1878  //align x to gap
1879  seqxA[kk]=seqx[i];
1880  seqyA[kk]='-';
1881  seqM[kk]=' ';
1882  kk++;
1883  }
1884  for(j=j_old; j<ylen; j++) {
1885  //align y to gap
1886  seqxA[kk]='-';
1887  seqyA[kk]=seqy[j];
1888  seqM[kk]=' ';
1889  kk++;
1890  }
1891 
1892  seqxA.resize(kk);
1893  seqyA.resize(kk);
1894  seqM.resize(kk);
1895  seq_id=seq_id/( n_ali8_+0.00000001); //what did by TMalign, but not reasonable, it should be n_ali8
1896  }
1897 
1898 
1899  void parameter_set4search(int xlen, int ylen) {
1900  //parameter initilization for searching: D0_MIN, Lnorm, d0, d0_search, score_d8
1901  D0_MIN=0.5;
1902  dcu0=4.25; //update 3.85-->4.25
1903  Lnorm=getmin(xlen, ylen); //normaliz TMscore by this in searching
1904  if(Lnorm<=19) { //update 15-->19
1905  d0=0.168; //update 0.5-->0.168
1906  } else {
1907  d0=(1.24*pow((Lnorm*1.0-15), 1.0/3)-1.8);
1908  }
1909  D0_MIN=d0+0.8; //this should be moved to above
1910  d0=D0_MIN; //update: best for search
1911 
1912  d0_search=d0;
1913  if(d0_search>8) d0_search=8;
1914  if(d0_search<4.5) d0_search=4.5;
1915 
1916  score_d8=1.5*pow(Lnorm*1.0, 0.3)+3.5; //remove pairs with dis>d8 during search & final
1917  }
1918 
1919  void parameter_set4final(double len) {
1920  D0_MIN=0.5;
1921 
1922  Lnorm=len; //normaliz TMscore by this in searching
1923  if(Lnorm<=21) {
1924  d0=0.5;
1925  } else {
1926  d0=(1.24*pow((Lnorm*1.0-15), 1.0/3)-1.8);
1927  }
1928  if(d0<D0_MIN) d0=D0_MIN;
1929 
1930  d0_search=d0;
1931  if(d0_search>8) d0_search=8;
1932  if(d0_search<4.5) d0_search=4.5;
1933  }
1934 
1935 
1936  void parameter_set4scale(int len, double d_s) {
1937  d0=d_s;
1938  Lnorm=len; //normaliz TMscore by this in searching
1939 
1940  d0_search=d0;
1941  if(d0_search>8) d0_search=8;
1942  if(d0_search<4.5) d0_search=4.5;
1943  }
1944 
1945 
1947  d0_out_=5.0;
1948  Size simplify_step=1;
1949  Size score_sum_method=0;
1950 
1951  //normalized by user assigned length
1952  parameter_set4final(length);
1953  d0A=d0;
1954  core::Real rmsd;
1955  return TMscore8_search(xtm, ytm, n_ali8_, t, u, simplify_step, score_sum_method, &rmsd);
1956  }
1957 
1958 
1959  int apply(core::pose::Pose const & pose1, core::pose::Pose const & pose2) {
1960  std::list <core::Size> residue_list1;
1961  std::list <core::Size> residue_list2;
1962  for ( Size ires=1; ires<= pose1.total_residue(); ++ires ) {
1963  if ( !pose1.residue(ires).is_protein() ) continue;
1964  residue_list1.push_back(ires);
1965  }
1966  for ( Size ires=1; ires<= pose2.total_residue(); ++ires ) {
1967  if ( !pose2.residue(ires).is_protein() ) continue;
1968  residue_list2.push_back(ires);
1969  }
1970 
1971  return apply(pose1, pose2, residue_list1, residue_list2);
1972  }
1973 
1974 
1975  int apply(core::pose::Pose const & pose1, core::pose::Pose const & pose2, std::list <core::Size> residue_list1, std::list <core::Size> residue_list2)
1976  {
1977  if (residue_list1.size() < 5 || residue_list2.size() < 5) {
1978  return 1;
1979  }
1980 
1981  // load data
1982  load_pose_allocate_memory(pose1, pose2, residue_list1, residue_list2);
1983 
1984  // parameter set
1985  parameter_set4search(xlen, ylen); //please set parameters in the function
1986  int simplify_step = 40; //for similified search engine
1987  int score_sum_method = 8; //for scoring method, whether only sum over pairs with dis<score_d8
1988 
1989  int i;
1990  vector < int > invmap0(ylen+1);
1991  vector < int > invmap(ylen+1);
1992  double TM, TMmax=-1;
1993  for(i=0; i<ylen; i++) {
1994  invmap0[i]=-1;
1995  }
1996 
1997  double ddcc=0.4;
1998  if(Lnorm <= 40) ddcc=0.1; //Lnorm was setted in parameter_set4search
1999 
2000  // get initial alignment with gapless threading
2001  get_initial(xa, ya, xlen, ylen, invmap0);
2002  //find the max TMscore for this initial alignment with the simplified search_engin
2003  TM=detailed_search(xa, ya, xlen, ylen, invmap0, t, u, simplify_step, score_sum_method);
2004  if(TM>TMmax) {
2005  TMmax=TM;
2006  }
2007  //run dynamic programing iteratively to find the best alignment
2008  TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
2009  if(TM>TMmax) {
2010  TMmax=TM;
2011  for(int i=0; i<ylen; i++) {
2012  invmap0[i]=invmap[i];
2013  }
2014  }
2015 
2016  // get initial alignment based on secondary structure
2017  get_initial_ss(xa, ya, xlen, ylen, invmap);
2018  TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
2019  if(TM>TMmax) {
2020  TMmax=TM;
2021  for(int i=0; i<ylen; i++) {
2022  invmap0[i]=invmap[i];
2023  }
2024  }
2025  if(TM > TMmax*0.2) {
2026  TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
2027  if(TM>TMmax) {
2028  TMmax=TM;
2029  for(int i=0; i<ylen; i++) {
2030  invmap0[i]=invmap[i];
2031  }
2032  }
2033  }
2034 
2035  // get initial alignment based on local superposition
2036  // =initial5 in original TM-align
2037  if(get_initial_local(xa, ya, xlen, ylen, invmap)){
2038  TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
2039  if(TM>TMmax){
2040  TMmax=TM;
2041  for(int i=0; i<ylen; i++){
2042  invmap0[i]=invmap[i];
2043  }
2044  }
2045  if(TM > TMmax*ddcc){
2046  TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 2);
2047  if(TM>TMmax){
2048  TMmax=TM;
2049  for(int i=0; i<ylen; i++){
2050  invmap0[i]=invmap[i];
2051  }
2052  }
2053  }
2054  }else{
2055  cout << endl << endl << "Warning: initial alignment from local superposition fail!" << endl << endl <<endl;
2056  }
2057 
2058 
2059  // get initial alignment based on previous alignment+secondary structure
2060  // =initial3 in original TM-align
2061  get_initial_ssplus(xa, ya, xlen, ylen, invmap0, invmap);
2062  TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
2063  if(TM>TMmax) {
2064  TMmax=TM;
2065  for(i=0; i<ylen; i++) {
2066  invmap0[i]=invmap[i];
2067  }
2068  }
2069  if(TM > TMmax*ddcc)
2070  {
2071  TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 0, 2, 30);
2072  if(TM>TMmax) {
2073  TMmax=TM;
2074  for(i=0; i<ylen; i++) {
2075  invmap0[i]=invmap[i];
2076  }
2077  }
2078  }
2079 
2080  // get initial alignment based on fragment gapless threading
2081  // =initial4 in original TM-align
2082  get_initial_fgt(xa, ya, xlen, ylen, xresno, yresno, invmap);
2083  TM=detailed_search(xa, ya, xlen, ylen, invmap, t, u, simplify_step, score_sum_method);
2084  if(TM>TMmax) {
2085  TMmax=TM;
2086  for(i=0; i<ylen; i++) {
2087  invmap0[i]=invmap[i];
2088  }
2089  }
2090  if(TM > TMmax*ddcc) {
2091  TM=DP_iter(xa, ya, xlen, ylen, t, u, invmap, 1, 2, 2);
2092  if(TM>TMmax) {
2093  TMmax=TM;
2094  for(i=0; i<ylen; i++) {
2095  invmap0[i]=invmap[i];
2096  }
2097  }
2098  }
2099 
2100  // The alignment will not be changed any more in the following
2101  //check if the initial alignment is generated approately
2102  bool flag=false;
2103  for(i=0; i<ylen; i++) {
2104  if(invmap0[i]>=0) {
2105  flag=true;
2106  break;
2107  }
2108  }
2109  if(!flag) {
2110  cout << "There is no alignment between the two proteins!" << endl;
2111  cout << "Program stop with no result!" << endl;
2112  return 1;
2113  }
2114 
2115  // Detailed TMscore search engine --> prepare for final TMscore
2116  // run detailed TMscore search engine for the best alignment, and
2117  // extract the best rotation matrix (t, u) for the best alginment
2118  simplify_step=1;
2119  score_sum_method=8;
2120  TM=detailed_search(xa, ya, xlen, ylen, invmap0, t, u, simplify_step, score_sum_method);
2121 
2122  //select pairs with dis<d8 for final TMscore computation and output alignment
2123  n_ali8_=0;
2124  int k=0;
2125  int n_ali=0;
2126  double d;
2127  m1_.resize(xlen); //alignd index in x
2128  m2_.resize(ylen); //alignd index in y
2129  do_rotation(xa, xt, xlen, t, u);
2130  k=0;
2131  for(int j=0; j<ylen; j++) {
2132  i=invmap0[j];
2133  if(i>=0) { //aligned
2134  n_ali++;
2135  d=sqrt(dist(xt[i], ya[j]));
2136  if(d <= score_d8) {
2137  m1_[k]=i;
2138  m2_[k]=j;
2139  xtm[k]=xa[i];
2140  ytm[k]=ya[j];
2141  k++;
2142  }
2143  }
2144  }
2145  n_ali8_=k;
2146 
2147  // Final TMscore
2148  double rmsd, TM1, TM2;
2149  d0_out_=5.0;
2150  simplify_step=1;
2151  score_sum_method=0;
2152 
2155  //double d0_0, TM_0;
2156  double Lnorm_0=ylen;
2157 
2158  //normalized by length of structure A
2159  parameter_set4final(Lnorm_0);
2160  d0A=d0;
2161  //d0_0=d0A; // set but never used ~Labonte
2162  TM1=TMscore8_search(xtm, ytm, n_ali8_, t0, u0, simplify_step, score_sum_method, &rmsd);
2163  //TM_0=TM1; // set but never used ~Labonte
2164 
2165  //normalized by length of structure B
2166  parameter_set4final(xlen+0.0);
2167  d0B=d0;
2168  TM2=TMscore8_search(xtm, ytm, n_ali8_, t, u, simplify_step, score_sum_method, &rmsd);
2169 
2170  return 0;
2171  }
2172 };
2173 
2174 } // namespace hybridization
2175 //} // //namespace comparative_modeling
2176 } // namespace protocols
2177 
2178 #endif