Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
superimpose.cc
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 protocols/jd2/Job.hh
11 /// @brief header file for ThreadingJob classes, part of August 2008 job distributor as planned at RosettaCon08. This file is responsible for three ideas: "inner" jobs, "outer" jobs (with which the job distributor works) and job container (currently just typdefed in the .fwd.hh)
12 /// @author Steven Lewis smlewi@gmail.com
13 
14 #if (defined _WIN32) && (!defined WIN_PYROSETTA)
15 #define ZLIB_WINAPI // REQUIRED FOR WINDOWS
16 #endif
17 
19 #include <core/pose/Pose.hh>
20 
21 #include <core/types.hh>
22 // AUTO-REMOVED #include <ObjexxFCL/FArray3D.hh>
23 #include <ObjexxFCL/FArray2D.hh>
24 
25 // ObjexxFCL Headers
26 
27 // Utility headers
28 #include <basic/Tracer.hh>
30 // AUTO-REMOVED #include <utility/io/izstream.hh>
31 #include <utility/io/ozstream.hh>
32 #include <utility/exit.hh>
33 // AUTO-REMOVED #include <numeric/model_quality/rms.hh>
34 // AUTO-REMOVED #include <numeric/model_quality/maxsub.hh>
35 // AUTO-REMOVED #include <numeric/gmx_functions.hh>
36 #include <numeric/xyz.functions.hh>
37 //// C++ headers
38 #include <string>
39 #include <iostream>
40 
41 #include <core/id/AtomID.hh>
42 #include <core/id/NamedAtomID.hh>
43 #include <utility/vector1.hh>
44 #include <numeric/model_quality/RmsData.hh>
45 
46 
47 namespace protocols {
48 namespace toolbox {
49 
50 using namespace ObjexxFCL;
51 
52 static basic::Tracer tr("protocols.evaluation.PCA",basic::t_info);
53 
54 using namespace core;
55 using namespace numeric::model_quality; //for rms functions
56 
57 typedef core::Real matrix[3][3];
58 typedef core::Real rvec[3];
59 
60 
61 void fill_CA_coords( core::pose::Pose const& pose, FArray2_double& coords ) { // fill coords
62  fill_CA_coords( pose, pose.total_residue(), coords );
63 }
64 
65 //coords needs to be a 3 x total_residues array
66 void fill_CA_coords( core::pose::Pose const& pose, Size n_atoms, FArray2_double& coords ) { // fill coords
67  for ( core::Size i = 1; i <= n_atoms; i++ ) {
68  id::NamedAtomID idCA( "CA", i );
69  PointPosition const& xyz = pose.xyz( idCA );
70  for ( core::Size d = 1; d<=3; ++d ) {
71  coords( d, i ) = xyz[ d-1 ];
72  }
73  }
74 }
75 
76 void CA_superimpose( FArray1_double const& weights, core::pose::Pose const& ref_pose, core::pose::Pose& fit_pose ) {
77  //count residues with CA
78  Size nres=0;
79  for ( core::Size i = 1; i <= fit_pose.total_residue(); i++ ) {
80  if ( !fit_pose.residue_type( i ).is_protein() ) break;
81  ++nres;
82  }
83  Size const natoms( nres );
84 
85  FArray2D_double coords( 3, natoms, 0.0 );
86  FArray2D_double ref_coords( 3, natoms, 0.0 );
87  fill_CA_coords( ref_pose, natoms, ref_coords );
88  fill_CA_coords( fit_pose, natoms, coords );
89 
90  FArray1D_double transvec( 3 );
91  FArray1D_double ref_transvec( 3 );
92  reset_x( natoms, coords, weights, transvec );
93  reset_x( natoms, ref_coords, weights, ref_transvec );
94 
95  Matrix R;
96  fit_centered_coords( natoms, weights, ref_coords, coords, R );
97 
98  //now apply transvecs and R to pose, via root!
99 // //ASSUME FOR NOW root is first N
100 // id::NamedAtomID idROOT( "N", 1 );
101 // Vector root_xyz( fit_pose.xyz( idROOT ) );
102 // root_xyz += ;// - Vector( ref_transvec( 1 ), ref_transvec( 2 ), ref_transvec( 3 ));
103 // fit_pose.set_xyz( idROOT, root_xyz );
104 
105  Vector toCenter( transvec( 1 ), transvec( 2 ), transvec( 3 ));
106  Vector toFitCenter( ref_transvec( 1 ), ref_transvec( 2 ), ref_transvec( 3 ));
107  { // translate xx2 by COM and fill in the new ref_pose coordinates
108  Size atomno(0);
109  Vector x2;
110  for ( Size i=1; i<= fit_pose.total_residue(); ++i ) {
111  for ( Size j=1; j<= fit_pose.residue_type(i).natoms(); ++j ) { // use residue_type to prevent internal coord update
112  ++atomno;
113  fit_pose.set_xyz( id::AtomID( j,i), R * ( fit_pose.xyz( id::AtomID( j, i) ) + toCenter ) - toFitCenter );
114  }
115  }
116  }
117 
118  if ( tr.Trace.visible() ) {
119  FArray2D_double pose_coords( 3, natoms );
120  fill_CA_coords( fit_pose, natoms, pose_coords );
121  for ( Size pos = 1; pos <= natoms; ++pos ) {
122  tr.Trace << " fit_coords vs pose_coords: ";
123  for ( Size d = 1; d <= 3; ++d ) tr.Trace << coords( d, pos ) << " ";
124  for ( Size d = 1; d <= 3; ++d ) tr.Trace << pose_coords( d, pos ) << " ";
125  tr.Trace << std::endl;
126  }
127  }
128 }
129 
130 /// @brief compute projections for given pose
131 void superimpose( Size natoms, FArray1_double const& weights, FArray2_double& ref_coords, FArray2_double& coords ) {
132  //fill Farray for fit
133 
134  FArray1D_double transvec( 3 );
135  reset_x( natoms, ref_coords, weights, transvec );
136  reset_x( natoms, coords, weights, transvec );
137  Matrix R; //to return rotation matrix... but we don't care.
138  fit_centered_coords( natoms, weights, ref_coords, coords, R );
139 }
140 
141 /// @brief compute projections for given pose
142 void superimpose( Size natoms, FArray1_double const& weights, FArray2_double& ref_coords, FArray2_double& coords, Matrix &R ) {
143  //fill Farray for fit
144  FArray1D_double transvec( 3 );
145  reset_x( natoms, ref_coords, weights, transvec );
146  reset_x( natoms, coords, weights, transvec );
147  fit_centered_coords( natoms, weights, ref_coords, coords, R );
148 }
149 
150 
151 void CA_superimpose( core::pose::Pose const& ref_pose, core::pose::Pose& fit_pose ) {
152  FArray1D_double weights( ref_pose.total_residue(), 1.0 );
153  CA_superimpose( weights, ref_pose, fit_pose );
154 }
155 
156 
157 void calc_fit_R(int natoms, Real const* weights, rvec const* xp,rvec const*x, matrix R );
158 void jacobi(double a[6][6],double d[],double v[6][6],int *nrot);
159 
160 /// @brief A function (not a macro) that will not print a square matrix to tr.Debug
161 template< class T > void dump_matrix( Size, T const &, basic::Tracer & ) {}
162 
163 /// @brief A function (not a macro) that will print a square matrix to tr.Debug
164 template< class T > void dump_matrix_no( Size nr, T const & a, basic::Tracer & tr)
165 {
166  Size i,k;
167  for ( i =0 ; i<nr; ++i ) {
168  for ( k =0 ; k<nr; ++k )
169  tr.Debug << a[i][k] << " ";
170  tr.Debug << "\n";
171  }
172 }
173 
174 // Evil, unnecessary macros that could just be functions
175 // Replaced by code above.
176 //
177 ///#define dump_matrix( nr, a ) {}
178 //#define dump_matrix_no( nr, a )
179 // { int i,k;
180 // for ( i =0 ; i<nr; i++ ) {
181 // for ( k =0 ; k<nr; k++ )
182 // tr.Debug << a[i][k] << " ";
183 // tr.Debug << "\n";
184 // }
185 //}
186 
187 /// some low-level helper routines
188 
189 #define DIM 3
190 
191 
192 void rotate_vec(int natoms,rvec *x,matrix R)
193 {
194  int j,r,c,m;
195  rvec x_old;
196 
197  /*rotate X*/
198  for(j=0; j<natoms; j++) {
199  for(m=0; m<DIM; m++)
200  x_old[m]=x[j][m];
201  for(r=0; r<DIM; r++) {
202  x[j][r]=0;
203  for(c=0; c<DIM; c++)
204  x[j][r]+=R[r][c]*x_old[c];
205  }
206  }
207 }
208 
209 void add_vec( int natoms, rvec *x, rvec transvec ) {
210  for ( int i=0; i<natoms; i++ ) {
211  for ( int j = 0; j< DIM; j++ ) {
212  x[i][j]+=transvec[j];
213  }
214  }
215 }
216 
217 void reset_x( Size n, FArray2_double& x, FArray1_double const& wts, FArray1_double& transvec ) {
218  Size const dim( 3 );
219  Real mass( 0.0 );
220  transvec = FArray1D_double( 3, 0.0 );
221 
222  for ( Size j = 1; j <= n; ++j ) {
223  mass += wts( j );
224  // align center of mass to origin
225  for ( Size d = 1; d <= dim; ++d ) {
226  transvec( d ) += x( d, j )*wts( j );
227  }
228  }
229  for ( Size d = 1; d <= dim; ++d ) {
230  transvec( d ) = -transvec( d )/mass;
231  }
232  for ( Size j = 1; j <= n; ++j ) {
233  for ( Size d = 1; d<= dim; ++d ) {
234  x( d, j ) += transvec( d );
235  }
236  }
237 }
238 
239 
240 void dump_as_pdb( std::string filename, Size n, FArray2_double& x, FArray1D_double transvec ) {
241  utility::io::ozstream out( filename );
242  for ( Size i = 1; i <= n; ++i ) {
243  char buf[400];
244  sprintf(buf, "ATOM %5d %-4s%-3s %4d %8.3f%8.3f%8.3f%6.2f%6.2f", (int) i, "CA", "ALA", (int) i,
245  x( 1, i ) + transvec( 1 ),
246  x( 2, i ) + transvec( 2 ),
247  x( 3, i ) + transvec( 3 ), 1.0, 1.0 );
248  out << buf << std::endl;
249  }
250 
251 }
252 
253 
254 void fit_centered_coords( Size natoms, FArray1_double const& weights, FArray2_double const& ref_coords, FArray2_double& coords, Matrix &R ) {
255  rvec* xgmx;
256  rvec* xrefgmx;
257  Real* weights_gmx;
258 
259  xgmx = new rvec[ natoms ];
260  xrefgmx = new rvec[ natoms ];
261  weights_gmx = new Real[ natoms ];
262  matrix Rot;
263 
264  //transfer into C-style arrays
265  for ( Size i = 1; i<=natoms ; i++) {
266  weights_gmx[i-1] = weights( i );
267  for ( Size d = 1; d<=3; d++ ) {
268  xgmx[i-1][d-1]= coords(d, i);
269  xrefgmx[i-1][d-1]=ref_coords(d,i);
270  }
271  }
272 
273  //compute rotation matrix
274  calc_fit_R( natoms, weights_gmx, xrefgmx, xgmx, Rot );
275 
276  R.row_x( Vector( Rot[ 0 ][ 0 ], Rot[ 0 ][ 1 ], Rot[ 0 ][ 2 ] ) );
277  R.row_y( Vector( Rot[ 1 ][ 0 ], Rot[ 1 ][ 1 ], Rot[ 1 ][ 2 ] ) );
278  R.row_z( Vector( Rot[ 2 ][ 0 ], Rot[ 2 ][ 1 ], Rot[ 2 ][ 2 ] ) );
279 
280  for ( Size i = 1; i<=natoms ; i++) {
281  Vector x( coords( 1, i ), coords( 2, i), coords( 3, i ) );
282  x = R * x;
283  coords( 1, i ) = x( 1 );
284  coords( 2, i ) = x( 2 );
285  coords( 3, i ) = x( 3 );
286  }
287 
288  delete[] xgmx;
289  delete[] xrefgmx;
290  delete[] weights_gmx;
291 }
292 
293 #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau); \
294  a[k][l]=h+s*(g-h*tau);
295 #define DIM6 6
296 #define XX 0
297 #define YY 1
298 #define ZZ 2
299 
300 void oprod(const rvec a,const rvec b,rvec c)
301 {
302  c[XX]=a[YY]*b[ZZ]-a[ZZ]*b[YY];
303  c[YY]=a[ZZ]*b[XX]-a[XX]*b[ZZ];
304  c[ZZ]=a[XX]*b[YY]-a[YY]*b[XX];
305 }
306 
307 
308 
309 void calc_fit_R(int natoms, Real const* weights, rvec const* xref, rvec const*x, matrix R)
310 {
311 
312  int c,r,n,j,i,irot;
313  double omega[ DIM6 ][ DIM6 ];
314  double om[ DIM6 ] [ DIM6 ];
315  double d[ DIM6 ],xnr,xpc;
316  matrix vh,vk,u;
317  Real mn;
318  int index;
319  Real max_d;
320 
321  for(i=0; i<DIM6; i++) {
322  d[i]=0;
323  for(j=0; j<DIM6; j++) {
324  omega[i][j]=0;
325  om[i][j]=0;
326  }
327  }
328 
329  /* clear matrix U */
330  for ( int i=0; i<DIM;i++) {
331  for ( int j=0; j<DIM; j++) u[i][j]=0;
332  }
333 
334  /*calculate the matrix U*/
335  for ( n=0; n<natoms; n++ ) {
336  if ( (mn = weights[ n ]) != 0.0 ) {
337  for ( c=0; c<DIM; c++) {
338  xpc=xref[n][c];
339  for(r=0; (r<DIM); r++) {
340  xnr=x[n][r];
341  u[c][r]+=mn*xnr*xpc;
342  }
343  }
344  }
345  }
346  dump_matrix(DIM, u, tr);
347  /*construct omega*/
348  /*omega is symmetric -> omega==omega' */
349  for(r=0; r<DIM6; r++) {
350  for(c=0; c<=r; c++) {
351  if (r>=DIM && c<DIM) {
352  omega[r][c]=u[r-DIM][c];
353  omega[c][r]=u[r-DIM][c];
354  } else {
355  omega[r][c]=0;
356  omega[c][r]=0;
357  }
358  }
359  }
360  dump_matrix(DIM6, omega, tr);
361  /*determine h and k*/
362  jacobi( omega,d,om,&irot);
363  /*real **omega = input matrix a[0..n-1][0..n-1] must be symmetric
364  *int natoms = number of rows and columns
365  *real NULL = d[0]..d[n-1] are the eigenvalues of a[][]
366  *real **v = v[0..n-1][0..n-1] contains the vectors in columns
367  *int *irot = number of jacobi rotations
368  */
369  dump_matrix( 2*DIM, omega, tr );
370  dump_matrix ( 2*DIM, om, tr );
371  index=0; /* For the compiler only */
372 
373  /* Copy only the first two eigenvectors */
374  for(j=0; j<2; j++) {
375  max_d=-1000;
376  for(i=0; i<DIM6; i++)
377  if (d[i]>max_d) {
378  max_d=d[i];
379  index=i;
380  }
381  d[index]=-10000;
382  for(i=0; i<DIM; i++) {
383  vh[j][i]=sqrt(2.0)*om[i][index];
384  vk[j][i]=sqrt(2.0)*om[i+DIM][index];
385  }
386  }
387  /* Calculate the last eigenvector as the outer-product of the first two.
388  * This insures that the conformation is not mirrored and
389  * prevents problems with completely flat reference structures.
390  */
391 
392  dump_matrix( DIM, vh, tr );
393  dump_matrix( DIM, vk, tr );
394  oprod(vh[0],vh[1],vh[2]);
395  oprod(vk[0],vk[1],vk[2]);
396  dump_matrix( DIM, vh, tr );
397  dump_matrix( DIM, vk, tr );
398 
399  /*determine R*/
400  for(r=0; r<DIM; r++)
401  for(c=0; c<DIM; c++)
402  R[r][c] = vk[0][r]*vh[0][c] +
403  vk[1][r]*vh[1][c] +
404  vk[2][r]*vh[2][c];
405  dump_matrix( DIM, R, tr );
406 }
407 
408 #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau); \
409  a[k][l]=h+s*(g-h*tau);
410 #define DIM6 6
411 #define XX 0
412 #define YY 1
413 #define ZZ 2
414 
415 void jacobi(double a[6][6],double d[],double v[6][6],int *nrot)
416 {
417  int j,i;
418  int iq,ip;
419  double tresh,theta,tau,t,sm,s,h,g,c;
420  double b[DIM6];
421  double z[DIM6];
422  int const n( DIM6 );
423  for (ip=0; ip<n; ip++) {
424  for (iq=0; iq<n; iq++) v[ip][iq]=0.0;
425  v[ip][ip]=1.0;
426  }
427  for (ip=0; ip<n;ip++) {
428  b[ip]=d[ip]=a[ip][ip];
429  z[ip]=0.0;
430  }
431  *nrot=0;
432  for (i=1; i<=50; i++) {
433  sm=0.0;
434  for (ip=0; ip<n-1; ip++) {
435  for (iq=ip+1; iq<n; iq++)
436  sm += fabs(a[ip][iq]);
437  }
438  if (sm == 0.0) {
439  return;
440  }
441  if (i < 4)
442  tresh=0.2*sm/(n*n);
443  else
444  tresh=0.0;
445  for (ip=0; ip<n-1; ip++) {
446  for (iq=ip+1; iq<n; iq++) {
447  g=100.0*fabs(a[ip][iq]);
448  if (i > 4 && fabs(d[ip])+g == fabs(d[ip])
449  && fabs(d[iq])+g == fabs(d[iq]))
450  a[ip][iq]=0.0;
451  else if (fabs(a[ip][iq]) > tresh) {
452  h=d[iq]-d[ip];
453  if (fabs(h)+g == fabs(h))
454  t=(a[ip][iq])/h;
455  else {
456  theta=0.5*h/(a[ip][iq]);
457  t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
458  if (theta < 0.0) t = -t;
459  }
460  c=1.0/sqrt(1+t*t);
461  s=t*c;
462  tau=s/(1.0+c);
463  h=t*a[ip][iq];
464  z[ip] -= h;
465  z[iq] += h;
466  d[ip] -= h;
467  d[iq] += h;
468  a[ip][iq]=0.0;
469  for (j=0; j<ip; j++) {
470  ROTATE(a,j,ip,j,iq)
471  }
472  for (j=ip+1; j<iq; j++) {
473  ROTATE(a,ip,j,j,iq)
474  }
475  for (j=iq+1; j<n; j++) {
476  ROTATE(a,ip,j,iq,j)
477  }
478  for (j=0; j<n; j++) {
479  ROTATE(v,j,ip,j,iq)
480  }
481  ++(*nrot);
482  }
483  }
484  }
485  for (ip=0; ip<n; ip++) {
486  b[ip] += z[ip];
487  d[ip] = b[ip];
488  z[ip] = 0.0;
489  }
490  }
491  runtime_assert(0);
492 }
493 
494 
495 }
496 }