1 // $Id: sup_pairwise.cpp $
2 //  =================================================================
3 //
4 //   SUPERPOSE: Protein structure superposition based on SSM
5 //   algorithm. Please cite:
6 //
7 //   For pairwise alignment:
8 //     E. Krissinel & K. Henrick (2004) Acta Cryst. D60, 2256-2268.
9 //
10 //   For multiple alignment:
11 //     Krissinel, E. and Henrick, K.
12 //     Multiple Alignment of Protein Structures in Three Dimensions.
13 //     Computational Life Sciences, First International Symposium,
14 //     CompLife 2005, Konstanz, Germany, September 25-27, 2005, 67-78.
15 //     Proceedings Editors: Michael R. Berthold, Robert C. Glen,
16 //     Kay Diederichs, Oliver Kohlbacher, Ingrid Fischer.
17 //     ISBN: 978-3-540-29104-6 (Print) 978-3-540-31726-5
18 //
19 //   Copyright (C) Eugene Krissinel 2002-2013.
20 //
21 //   This library is free software: you can redistribute it and/or
22 //   modify it under the terms of the GNU Lesser General Public
23 //   License version 3, modified in accordance with the provisions
24 //   of the license to address the requirements of UK law.
25 //
26 //   You should have received a copy of the modified GNU Lesser
27 //   General Public License along with this library. If not, copies
28 //   may be downloaded from http://www.ccp4.ac.uk/ccp4license.php
29 //
30 //   This program is distributed in the hope that it will be useful,
31 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
32 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33 //   GNU Lesser General Public License for more details.
34 //
35 // =================================================================
36 //
37 //    18.09.13   <--  Date of Last Modification.
38 //                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 //  ----------------------------------------------------------------
40 //
41 //  **** Module  :  SUP_Pairwise <implementation>
42 //       ~~~~~~~~~
43 //  **** Project :  SUPERPOSE
44 //       ~~~~~~~~~
45 //  **** Functions:  pairwise_superposition
46 //       ~~~~~~~~~~  printFracAnalysis
47 //
48 //  E. Krissinel, 2003-2013
49 //
50 // =================================================================
51 //
52 
53 #include <string.h>
54 
55 #include "sup_pairwise.h"
56 #include "ssm/ssm_align.h"
57 
58 
printccp4rot(mmdb::mat44 m)59 void printccp4rot ( mmdb::mat44 m )  {
60 double w_, x_, y_, z_;
61 double d = 180.0/3.14159265359;
62 double tr = m[0][0] + m[1][1] + m[2][2] + 1.0;
63 
64   // check the diagonal
65   if ( tr > 1.0e-8 ) {
66     double s( sqrt(tr) );
67     w_ = s * 0.5;
68     s = 0.5 / s;
69     x_ = s * ( m[2][1] - m[1][2] );
70     y_ = s * ( m[0][2] - m[2][0] );
71     z_ = s * ( m[1][0] - m[0][1] );
72   } else {
73     if ( m[0][0] > m[1][1] && m[0][0] > m[2][2] ) {
74       double s( sqrt(1.0 + m[0][0] - m[1][1] - m[2][2] ) );
75       x_ = 0.5 * s;
76       if ( s != 0.0 ) s = 0.5 / s;
77       w_ = s * ( m[2][1] - m[1][2] );
78       y_ = s * ( m[0][1] + m[1][0] );
79       z_ = s * ( m[0][2] + m[2][0] );
80     } else if ( m[1][1] > m[2][2] ) {
81       double s( sqrt(1.0 + m[1][1] - m[2][2] - m[0][0] ) );
82       y_ = 0.5 * s;
83       if ( s != 0.0 ) s = 0.5 / s;
84       w_ = s * ( m[0][2] - m[2][0] );
85       z_ = s * ( m[1][2] + m[2][1] );
86       x_ = s * ( m[1][0] + m[0][1] );
87     } else {
88       double s( sqrt(1.0 + m[2][2] - m[0][0] - m[1][1] ) );
89       z_ = 0.5 * s;
90       if ( s != 0.0 ) s = 0.5 / s;
91       w_ = s * ( m[1][0] - m[0][1] );
92       x_ = s * ( m[2][0] + m[0][2] );
93       y_ = s * ( m[2][1] + m[1][2] );
94     }
95   }
96   double om, ph, ka, al, be, ga;
97   om = ph = ka = 0.0;
98   if ( fabs(w_) < 0.999999 ) {
99     double r = sqrt( x_*x_ + y_*y_ );
100     om = d*atan2( r, z_ );
101     if ( r > 0.000001 ) ph = d*atan2( y_, x_ );
102     ka = d*2.0*acos( w_ );
103   }
104   double ca, cb, cg, sa, sb, sg;
105   cb = 1.0 - 2.0 * (x_*x_ + y_*y_);
106   sb = 2.0 * sqrt( (x_*x_ + y_*y_) * (w_*w_ + z_*z_) );
107   if ( sb > 0.0001 ) {
108     ca = 2.0 * (x_*z_ + w_*y_);
109     sa = 2.0 * (y_*z_ - w_*x_);
110     cg = 2.0 * (w_*y_ - x_*z_);
111     sg = 2.0 * (y_*z_ + w_*x_);
112   } else {
113     ca = 1.0;
114     sa = 0.0;
115     cg = cb;
116     sg = 2.0*(y_*z_ + w_*x_);
117   }
118   al = d*atan2(sa,ca);
119   be = d*atan2(sb,cb);
120   ga = d*atan2(sg,cg);
121 
122 #ifdef _ccp4_
123   printf ( "\n\n$TEXT:CCP4 rotation-translational operator: $$ $$\n" );
124 #else
125   printf ( " CCP4 format rotation-translation operator\n" );
126 #endif
127 
128   printf ( " Polar angles (omega,phi,kappa) : %9.3f %9.3f %9.3f\n",
129            om,ph,ka );
130   printf ( " Euler angles (alpha,beta,gamma): %9.3f %9.3f %9.3f\n",
131            al,be,ga );
132   printf ( " Orthogonal translation (/Angst): %9.3f %9.3f %9.3f\n",
133            m[0][3],m[1][3],m[2][3] );
134 
135 #ifdef _ccp4_
136   printf ( "$$\n" );
137 #endif
138 
139 }
140 
141 
printFracAnalysis(mmdb::mat44 & T,mmdb::cpstr name,mmdb::PManager M)142 void printFracAnalysis ( mmdb::mat44 & T, mmdb::cpstr name,
143                          mmdb::PManager M )   {
144 mmdb::mat44 TF;
145 
146   if (M->CrystReady()!=mmdb::CRRDY_NoTransfMatrices)  {
147 
148     if (M->Orth2Frac(T,TF))
149       printf ( "\n"
150         "      in fractional coordinates of %s:\n\n"
151         "        Rx         Ry         Rz           T\n"
152         " %10.3f %10.3f %10.3f   %10.3f\n"
153         " %10.3f %10.3f %10.3f   %10.3f\n"
154         " %10.3f %10.3f %10.3f   %10.3f\n",
155         name,
156         TF[0][0],TF[0][1],TF[0][2],TF[0][3],
157         TF[1][0],TF[1][1],TF[1][2],TF[1][3],
158         TF[2][0],TF[2][1],TF[2][2],TF[2][3] );
159     else
160       printf ( "\n"
161         " *** orthogonal-fractional transformations failed for structure\n"
162         " %s\n",name );
163 
164   }
165   /* else  {
166     printf (
167       " Orthogonal-fractional transformations were not calculated\n"
168       " structure %s.\n"
169       " Possibly, cell parameters were not supplied.\n",
170       name,M->CrystReady() );
171   }*/
172 
173 }
174 
pairwise_superposition(mmdb::PPManager M,mmdb::psvector name,mmdb::ivector selHnd,mmdb::pstr fileout)175 int pairwise_superposition ( mmdb::PPManager M,
176                              mmdb::psvector  name,
177                              mmdb::ivector   selHnd,
178                              mmdb::pstr      fileout  )  {
179 mmdb::io::File f;
180 ssm::PAlign    SSMAlign;
181 int            rc;
182 
183   printf ( "\n Performing Multiple Structure Alignment"
184            "\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n" );
185 
186   SSMAlign = new ssm::Align();
187   rc = SSMAlign->align ( M[0],M[1],
188                          ssm::PREC_Normal,ssm::CONNECT_Flexible,
189                          selHnd[0],selHnd[1] );
190 
191   if (rc)  {
192 #ifdef _ccp4_
193     printf ( "$TEXT:Warning: $$Superposition was not achieved$$\n" );
194 #endif
195     switch (rc)  {
196       case ssm::RC_NoHits :
197          printf ( " *** secondary structure does not match.\n" );
198          break;
199       case ssm::RC_NoSuperposition :
200          printf ( " *** structures are too remote.\n" );
201          break;
202       case ssm::RC_NoGraph :
203          printf ( " *** can't make graph for %s.\n",name[0] );
204          break;
205       case ssm::RC_NoVertices :
206          printf ( " *** empty graph for %s.\n",name[0] );
207          break;
208       case ssm::RC_NoGraph2 :
209          printf ( " *** can't make graph for %s.\n",name[1] );
210          break;
211       case ssm::RC_NoVertices2 :
212          printf ( " *** empty graph for %s.\n",name[1] );
213          break;
214       default :
215         printf ( " *** undocumented return code %i.\n",rc );
216     }
217 #ifdef _ccp4_
218     printf ( "$$\n" );
219 #endif
220   } else  {
221 
222 #ifdef _ccp4_
223     printf ( "$TEXT:Alignment results: $$ $$\n" );
224 #endif
225 
226     printf (
227       " Query      %s\n"
228       " and Target %s\n"
229       "\n"
230       " have been superposed. Superposition matrix (to be applied\n"
231       " to %s) is\n\n"
232       "        Rx         Ry         Rz           T\n"
233       " %10.3f %10.3f %10.3f   %10.3f\n"
234       " %10.3f %10.3f %10.3f   %10.3f\n"
235       " %10.3f %10.3f %10.3f   %10.3f\n",
236       name[0],name[1],name[0],
237       SSMAlign->TMatrix[0][0],SSMAlign->TMatrix[0][1],
238       SSMAlign->TMatrix[0][2],SSMAlign->TMatrix[0][3],
239       SSMAlign->TMatrix[1][0],SSMAlign->TMatrix[1][1],
240       SSMAlign->TMatrix[1][2],SSMAlign->TMatrix[1][3],
241       SSMAlign->TMatrix[2][0],SSMAlign->TMatrix[2][1],
242       SSMAlign->TMatrix[2][2],SSMAlign->TMatrix[2][3] );
243 
244     printFracAnalysis ( SSMAlign->TMatrix,name[0],M[0] );
245     printFracAnalysis ( SSMAlign->TMatrix,name[1],M[1] );
246 
247     printf ( "\n"
248       " ===== Scores achieved:\n"
249       "\n"
250        "   quality Q:  %-7.4f (normalised to [0...1])\n"
251        "     r.m.s.d:  %-7.4f (A)\n"
252        "      Nalign:  %-6i  (residues)\n",
253        SSMAlign->Qscore,SSMAlign->rmsd,SSMAlign->nalgn );
254 
255 #ifdef _ccp4_
256     printf ( "$$\n\n" );
257     printf ( "$TEXT:Residue alignment: $$ $$\n" );
258 #else
259     printf ( "\n"
260       " ===== Residue alignment:\n" );
261 #endif
262 
263     f.assign ( "stdout" );
264     f.rewrite();
265 
266     ssm::PrintAlignTable ( f,M[0],M[1],SSMAlign );
267 
268 #ifdef _ccp4_
269     f.Write ( "$$\n" );
270 #endif
271 
272 /*
273 char S[200];
274 int  i;
275     f.WriteLine ( " \n\n Test output for Paul Emsley:\n\n"
276                   "   i    Ca1[i]   dist1[i]" );
277     for (i=0;i<SSMAlign->nres1;i++)  {
278       sprintf ( S," %5i %5i %10.3f",i,SSMAlign->Ca1[i],
279                                       SSMAlign->dist1[i] );
280       f.WriteLine ( S );
281     }
282     f.WriteLine ( "\n\n   i    Ca2[i]" );
283     for (i=0;i<SSMAlign->nres2;i++)  {
284       sprintf ( S," %5i %5i",i,SSMAlign->Ca2[i] );
285       f.WriteLine ( S );
286     }
287 */
288 
289     f.shut();
290 
291     // if output file requested, apply transform to first
292     // input file (NB all file, not just requested selection)
293     // and output
294     if ( fileout ) {
295       M[0]->ApplyTransform ( SSMAlign->TMatrix );
296       M[0]->WritePDBASCII ( fileout );
297     }
298 
299 #ifndef _ccp4_
300     printf ( "\n"
301   " ----------------------------------------------------------------\n"
302              "\n" );
303 #endif
304     printccp4rot ( SSMAlign->TMatrix );
305 
306   }
307 
308   return 0;
309 
310 }
311 
312