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