| Bsoft 2.0.5 Bernard's software package

mol_symmetry.cpp
Go to the documentation of this file.
1
9 #include "rwmolecule.h"
10 #include "rwatomprop.h"
11 #include "rwresprop.h"
12 #include "mol_compare.h"
13 #include "mol_symmetry.h"
14 #include "mol_transform.h"
15 #include "mol_util.h"
16 #include "seq_align.h"
17 #include "Matrix3.h"
18 #include "matrix_linear.h"
19 #include "symmetry.h"
20 #include "random_numbers.h"
21 #include "utilities.h"
22 #include <fstream>
23
24 // Declaration of global variables
25 extern int verbose; // Level of output to the screen
26
34 int molgroup_apply_point_group(Bmolgroup* molgroup, Bsymmetry* sym, View ref_view)
35 {
36 int i, j;
37 int nunits = 1, nmol;
38 for ( i=0; i<sym->n; i++ ) nunits *= sym->op[i].order;
39
40 if ( ref_view.vector_size() < 1e-10 ) ref_view = View(0, 0, 1, 0);
41
42 if ( verbose & VERB_PROCESS ) {
43 cout << endl << "Applying symmetry " << sym->label << ":" << endl;
44 cout << "Number of asymmetric units: " << nunits << endl;
45 cout << "Reference symmetry axis: {" <<
46 ref_view[0] << "," << ref_view[1] << "," << ref_view[2] << "}" << endl;
47 cout << "Reference rotation angle: " <<
48 ref_view.angle()*180/M_PI << endl << endl;
49 } else if ( verbose & VERB_LABEL )
50 cout << endl << "Applying symmetry " << sym->label << endl << endl;
51
52 // if ( verbose & VERB_FULL )
53 // sym_show_matrices(sym);
54
55 Bmolgroup* new_molgroup = molgroup;
56 Bmolecule *mol;
57 Bresidue *res;
58 Batom *atom;
59 Bbond* bond;
60 Bangle* angle;
61
62 // Initial user-specified rotation to get the map in a standard orientation
63 // if ( fabs(ref_view.a) > 1e-30 )
64 // molgroup_coor_rotate(molgroup, ref_view, shift);
65
66 Matrix3 ref_mat = ref_view.matrix();
67 Matrix3 mat(1);
68 Vector3<double> new_axis;
69
70 nmol = 0;
71 for ( mol = molgroup->mol; mol; mol = mol->next ) nmol++;
72
73 for ( i=0; i<sym->n; i++ ) {
74 new_axis = ref_mat * sym->op[i].axis;
75 for ( j=1; j<sym->op[i].order; j++ ) {
76 mat = Matrix3(new_axis, j*TWOPI*1.0L/sym->op[i].order);
77 if ( verbose & VERB_FULL )
78 matrix3_show_hp(mat);
79 new_molgroup->next = molgroup_copy(molgroup);
80 new_molgroup = new_molgroup->next;
81 for ( mol = new_molgroup->mol; mol; mol = mol->next ) {
82 for( res = mol->res; res; res = res->next ) {
83 for ( atom = res->atom; atom; atom = atom->next ) {
84 atom->coord = mat * atom->coord;
85 }
86 }
87 }
88 }
89 mol = molgroup->mol;
90 bond = molgroup->bond;
91 angle = molgroup->angle;
92 for ( new_molgroup = molgroup->next; new_molgroup; new_molgroup = new_molgroup->next ) {
93 if ( mol ) {
94 for ( ; mol->next; mol = mol->next ) ;
95 mol->next = new_molgroup->mol;
96 } else {
97 mol = molgroup->mol = new_molgroup->mol;
98 }
99 new_molgroup->mol = NULL;
100 if ( bond ) {
101 for ( ; bond->next; bond = bond->next ) ;
102 bond->next = new_molgroup->bond;
103 } else {
104 bond = molgroup->bond = new_molgroup->bond;
105 }
106 new_molgroup->bond = NULL;
107 if ( angle ) {
108 for ( ; angle->next; angle = angle->next ) ;
109 angle->next = new_molgroup->angle;
110 } else {
111 angle = molgroup->angle = new_molgroup->angle;
112 }
113 new_molgroup->angle = NULL;
114 }
115 molgroup_list_kill(molgroup->next);
116 molgroup->next = NULL;
117 new_molgroup = molgroup;
118 molgroup_atom_renumber(molgroup, 1);
119 nmol *= sym->op[i].order;
120 }
121
122 return 0;
123 }
124
135 int molgroup_generate_helix(Bmolgroup* molgroup, View ref_view,
136 double helix_rise, double helix_angle, int gen_down, int gen_up)
137 {
138 int i;
139
140 if ( ref_view.vector_size() < 1e-10 ) ref_view = View(0, 0, 1, 0);
141
142 if ( gen_down < 0 ) gen_down = 0;
143 if ( gen_up < 0 ) gen_up = 0;
144
145 if ( verbose & VERB_PROCESS ) {
146 cout << endl << "Applying helical symmetry:" << endl;
147 cout << "Number of asymmetric units: " << gen_down + 1 + gen_up << endl;
148 cout << "Helical rise: " << helix_rise << endl;
149 cout << "Helical rotation angle: " << helix_angle*180/M_PI << endl;
150 cout << "Reference symmetry axis: {" <<
151 ref_view[0] << "," << ref_view[1] << "," << ref_view[2] << "}" << endl << endl;
152 } else if ( verbose & VERB_LABEL )
153 cout << endl << "Applying helical symmetry" << endl << endl;
154
155 Bmolgroup* mg = NULL;
156 Bmolecule *mol;
157 Bresidue *res;
158 Batom *atom;
159
160 // Initial user-specified rotation to get the map in a standard orientation
161 // if ( fabs(ref_view.a) > 1e-30 )
162 // molgroup_coor_rotate(molgroup, ref_view, shift);
163
164 // Matrix3 ref_mat = ref_view.matrix();
165 Matrix3 mat(1);
166 Vector3<double> axis(ref_view[0], ref_view[1], ref_view[2]);
167 Vector3<double> shift;
168
169 for ( mg = molgroup, i=-gen_down; i<gen_up; i++, mg = mg->next )
170 mg->next = molgroup_copy(molgroup);
171
172 for ( mg = molgroup, i=-gen_down; i<=gen_up; i++, mg = mg->next ) {
173 shift[2] = i*helix_rise;
174 mat = Matrix3(axis, i*helix_angle);
175 if ( verbose & VERB_FULL )
176 matrix3_show_hp(mat);
177 for ( mol = mg->mol; mol; mol = mol->next ) {
178 for( res = mol->res; res; res = res->next ) {
179 for ( atom = res->atom; atom; atom = atom->next ) {
180 atom->coord = mat * atom->coord;
181 atom->coord += shift;
182 }
183 }
184 }
185 }
186
187 return 0;
188 }
189
190
200 int molgroup_apply_symmetry_from_pdb(Bmolgroup* molgroup, Bstring& filename)
201 {
202 if ( !filename.contains(".pdb") && !filename.contains(".PDB") &&
203 !filename.contains(".ent") && !filename.contains(".ENT") )
204 return -1;
205
206 ifstream fpdb(filename.c_str());
207 if ( fpdb.fail() ) return -1;
208
209 Matrix3 mat[1000];
210 Vector3<double> trans[1000];
211 char aline[100], tag1[12], tag2[12], tag3[12], tag4[12];
212 int n(0), i(0);
213
214 while ( fpdb.getline(aline, 100) && fpdb.good() ) {
215 if ( strncmp(aline, "REMARK 290 SMTRY", 18) == 0 ) {
216 if ( i==0 ) sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
217 tag1, tag2, tag3, tag4, &mat[n][0][0], &mat[n][0][1], &mat[n][0][2], &trans[n][0]);
218 else if ( i==1 ) sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
219 tag1, tag2, tag3, tag4, &mat[n][1][0], &mat[n][1][1], &mat[n][1][2], &trans[n][1]);
220 else sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
221 tag1, tag2, tag3, tag4, &mat[n][2][0], &mat[n][2][1], &mat[n][2][2], &trans[n][2]);
222 i++;
223 if ( strstr(aline, "SMTRY3") ) {
224 n++;
225 i = 0;
226 }
227 }
228 }
229
230 fpdb.close();
231
232 Bmolecule *mol, *new_mol;
233 Bresidue *res;
234 Batom *atom;
235 int nmol(0), m;
236 for ( mol = molgroup->mol; mol; mol = mol->next ) nmol++;
237
238 if ( verbose & VERB_PROCESS )
239 cout << "Extracting " << n << " matrices from " << filename << " and applying:" << endl;
240
241 for ( i=1; i<n; i++ ) {
242 if ( verbose & VERB_PROCESS ) {
243 cout << "Matrix " << i+1 << ":" << endl;
244 cout << mat[i] << endl;
245 cout << "Shift: " << trans[i] << endl;
246 }
247 for ( m=0, mol = molgroup->mol; m<nmol; mol = mol->next, m++ ) {
248 new_mol = mol_copy_and_add_to_molgroup(molgroup, mol);
249 for( res = new_mol->res; res; res = res->next ) {
250 for ( atom = res->atom; atom; atom = atom->next ) {
251 atom->coord = mat[i] * atom->coord;
252 atom->coord += trans[i];
253 }
254 }
255 }
256 }
257
258 return 0;
259 }
260
270 int molgroup_apply_matrices_from_pdb(Bmolgroup* molgroup, Bstring& filename)
271 {
272 if ( !filename.contains(".pdb") && !filename.contains(".PDB") &&
273 !filename.contains(".ent") && !filename.contains(".ENT") )
274 return -1;
275
276 ifstream fpdb(filename.c_str());
277 if ( fpdb.fail() ) return -1;
278
279 Matrix3 mat[1000];
280 Vector3<double> trans[1000];
281 char aline[100], tag1[12], tag2[12], tag3[12], tag4[12];
282 int n(0), i(0);
283
284 while ( fpdb.getline(aline, 100) && fpdb.good() ) {
285 if ( strncmp(aline, "REMARK 350 BIOMT", 18) == 0 ) {
286 if ( i==0 ) sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
287 tag1, tag2, tag3, tag4, &mat[n][0][0], &mat[n][0][1], &mat[n][0][2], &trans[n][0]);
288 else if ( i==1 ) sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
289 tag1, tag2, tag3, tag4, &mat[n][1][0], &mat[n][1][1], &mat[n][1][2], &trans[n][1]);
290 else sscanf(aline, "%s %s %s %s %lf %lf %lf %lf",
291 tag1, tag2, tag3, tag4, &mat[n][2][0], &mat[n][2][1], &mat[n][2][2], &trans[n][2]);
292 i++;
293 if ( strstr(aline, "BIOMT3") ) {
294 n++;
295 i = 0;
296 }
297 }
298 }
299
300 fpdb.close();
301
302 Bmolecule *mol, *new_mol;
303 Bresidue *res;
304 Batom *atom;
305 int nmol(0), m;
306 for ( mol = molgroup->mol; mol; mol = mol->next ) nmol++;
307
308 if ( verbose & VERB_PROCESS )
309 cout << "Extracting " << n << " matrices from " << filename << " and applying:" << endl;
310
311 for ( i=1; i<n; i++ ) {
312 if ( verbose & VERB_PROCESS ) {
313 cout << "Matrix " << i+1 << ":" << endl;
314 cout << mat[i] << endl;
315 cout << "Shift: " << trans[i] << endl;
316 }
317 for ( m=0, mol = molgroup->mol; m<nmol; mol = mol->next, m++ ) {
318 new_mol = mol_copy_and_add_to_molgroup(molgroup, mol);
319 for( res = new_mol->res; res; res = res->next ) {
320 for ( atom = res->atom; atom; atom = atom->next ) {
321 atom->coord = mat[i] * atom->coord;
322 atom->coord += trans[i];
323 }
324 }
325 }
326 }
327
328 return 0;
329 }
330
331 struct MassCOM {
332 double mass;
333 Vector3<double> com;
334 } ;
335
336 static int QsortMassCOM(const void *x, const void *y)
337 {
338 MassCOM* c1 = (MassCOM *) x;
339 MassCOM* c2 = (MassCOM *) y;
340
341 if ( fabs((c1->mass - c2->mass)/(c1->mass + c2->mass)) > 0.1 ) {
342 if ( c1->mass < c2->mass ) return 1;
343 else return -1;
344 } else {
345 if ( c1->com.length() < c2->com.length() ) return 1;
346 else return -1; // Sort from high to low
347 }
348 }
349
366 int molgroup_find_standard_view(Bmolgroup* molgroup, Bsymmetry* sym, View ref_view)
367 {
368 molgroup_shift_to_center_of_mass(molgroup);
369
370 int g, i, j, k, nmol, nunits, nmassif;
371 Bmolecule* mol;
372 Bresidue* res;
373 Batom* atom;
374
375 for ( nunits = 1, i=0; i<sym->n; i++ ) nunits *= sym->op[i].order;
376 for ( nmol = 0, mol = molgroup->mol; mol; mol = mol->next ) nmol++;
377
378 if ( nmol < nunits ) {
379 cerr << "Error: Not enough molecules (" << nmol << ") to fit into " << nunits << " asymmetric units!" << endl << endl;
380 return -1;
381 }
382
383 // Get all chains' centers of mass and weight
384 double themass, themass2, maxmass(0);
385 MassCOM* c = new MassCOM[nmol];
386 for ( i=0; i<nmol; i++ ) c[i].com = c[i].mass = 0;
387
388 nmassif = 0;
389 for ( i=0, mol = molgroup->mol; mol; mol = mol->next, i++ ) {
390 for( res = mol->res; res; res = res->next ) {
391 for ( atom = res->atom; atom; atom = atom->next ) {
392 c[i].com += atom->coord * atom->mass;
393 c[i].mass += atom->mass;
394 }
395 }
396 if ( c[i].mass ) {
397 c[i].com /= c[i].mass;
398 nmassif++;
399 }
400 if ( maxmass < c[i].mass ) maxmass = c[i].mass;
401 }
402
403 // Sort the chains based on weight and distance from COM
404 qsort((void *) c, nmol, sizeof(MassCOM), (int (*)(const void *, const void *)) QsortMassCOM);
405
406 if ( verbose & VERB_FULL ) {
407 cout << endl << "Ordered list of centers-of-mass:" << endl;
408 cout << " x\t y\t z\tMass (Da)" << endl;
409 for ( i=0; i<nmol; i++ )
410 cout << c[i].com[0] << tab << c[i].com[1] << tab << c[i].com[2] << tab << c[i].mass << endl;
411 cout << endl << endl;
412 }
413
414 // Determine the number of groups of chains, each group likely symmetry-related
415 // A group is defined as a set of chains (number = symmetry order),
416 // that differ little in weight (stdev < 5%)
417 int ngroup(0);
418 Vector3<double> com, translate;
419
420 if ( verbose & VERB_FULL )
421 cout << endl << "Group\tMass\tStDev" << endl;
422 for ( i=0; i<nmol-nunits+1; i+=nunits ) { // Loop over all groups of size defined by symmetry
423 themass = themass2 = 0;
424 com = 0;
425 for ( j=i; j<i+nunits; j++ ) {
426 themass += c[j].mass;
427 themass2 += c[j].mass*c[j].mass;
428 com += c[j].com; // Center of group on symmetry axis
429 }
430 themass /= nunits;
431 themass2 = themass2/nunits - themass*themass;
432 if ( themass2 > 0 ) themass2 = sqrt(themass2);
433 else themass2 = 0;
434 if ( themass > 100 && themass2/themass < 0.05 ) {
435 ngroup++;
436 com *= -1.0/nunits; // Translation to symmetry axis
437 translate += com;
438 }
439 if ( verbose & VERB_FULL )
440 cout << ngroup << tab << themass << tab << themass2 << endl;
441 }
442 translate /= ngroup;
443
444 // Subtract the global center-of-mass from the chain COM's
445 com = 0;
446 for ( i=0; i<nmassif; i++ ) com += c[i].com;
447 com /= nmassif;
448 for ( i=0; i<nmassif; i++ ) c[i].com -= com;
449
450 // Generate pairs of vectors and calculate normals
451 int n(0), nvec = (ngroup*nunits*(nunits-1)*(nunits-2))/6;
452 double a;
453 Vector3<double> axis, v1, v2, d;
454 Vector3<double>* v = new Vector3<double>[nvec];
455
456 if ( verbose & VERB_FULL )
457 cout << endl << "Group\tv1\tv2\tv3\tx\ty\tz" << endl;
458 for ( g=0; g<ngroup; g++ ) {
459 // Calculate normal vectors
460 for ( i=2+nunits*g; i<nunits*(g+1); i++ ) {
461 for ( j=1+nunits*g; j<i; j++ ) {
462 v1 = c[i].com - c[j].com;
463 for ( k=nunits*g; k<j; k++ ) {
464 v2 = c[i].com - c[k].com;
465 // v[n] = v1.cross(v2) * c[i].mass;
466 v[n] = v1.cross(v2);
467 v[n].normalize();
468 if ( verbose & VERB_FULL )
469 cout << g << tab << k << tab << j << tab << i << tab
470 << v[n][0] << tab << v[n][1] << tab << v[n][2] << endl;
471 n++;
472 }
473 }
474 }
475 }
476
477 if ( verbose & VERB_DEBUG )
478 cout << "DEBUG molgroup_find_standard_view: nvec=" << nvec << " n=" << n << endl;
479
480 // Find a common normal when comparing pairs of vectors and assign it as the major axis
481 int vbest = -1, m = 100;
482 int nx = 2*m, ny = 2*m, nz = 2;
483 int sv = nx * ny * nz;
484 int* nv = new int[sv];
485 for ( i=0; i<sv; i++ ) nv[i] = 0;
486
487 for ( i=1; i<n; i++ ) {
488 for ( j=0; j<i; j++ ) {
489 v1 = v[i];
490 v1.normalize();
491 a = fabs(v[i].angle(v[j]));
492 if ( a > M_PI_2 ) {
493 a = M_PI - a;
494 v1 = -v1;
495 }
496 v1 *= m;
497 if ( a < 0.05 ) {
498 k = (int) (nx*(v1[1]+m)) + (int) (v1[0]+m);
499 if ( k > nx*ny ) k = 0;
500 if ( v1[2] > 0 ) k += nx*ny;
501 nv[k]++;
502 if ( vbest < nv[k] ) {
503 vbest = nv[k];
504 axis = v1;
505 }
506 }
507 }
508 }
509 delete[] nv;
510
511 for ( i=0; i<n; i++ ) {
512 a = fabs(axis.angle(v[i]));
513 if ( a > M_PI_2 ) {
514 a = M_PI - a;
515 v[i] = -v[i];
516 }
517 if ( a < 0.05 ) axis += v[i];
518 }
519
520 axis.normalize();
521
522 // Find the 2-fold on the x-axis as the sum vector of two COM's
523 // that has a difference vector that is most parallel with the major axis
524 double ang(0), ang_min = 1000;
525 if ( sym->point > 200 ) {
526 for ( i=1; i<nunits; i++ ) {
527 for ( j=0; j<i; j++ ) {
528 d = c[i].com - c[j].com;
529 ang = axis.angle(d);
530 if ( fabs(ang_min) > fabs(ang) ) {
531 ang_min = ang;
532 v2 = c[i].com + c[j].com;
533 v2.normalize();
534 }
535 }
536 }
537 }
538
539 delete[] c;
540 delete[] v;
541
542 if ( verbose & VERB_DEBUG ) {
543 cout << "Angle with major axis: " << ang_min*180/M_PI << endl;
544 cout << "Dihedral axis: " << v2 << endl;
545 cout << "Angle between axes: " << (axis.angle(v2))*180/M_PI << endl;
546 }
547
548 if ( verbose & VERB_LABEL ) {
549 cout << "Translate: " << translate << endl;
550 cout << "Major symmetry axis: " << axis << endl;
551 if ( sym->point > 200 )
552 cout << "Minor symmetry axis: " << v2 << endl;
553 cout << endl;
554 }
555
556 // The first matrix rotates it to the major symmetry axis
557 // The second does the in-plane rotation
558 View view(-axis[0], -axis[1], axis[2], 0);
559 Matrix3 mat = view.matrix();
560 if ( sym->point > 200 ) {
561 v1 = 0;
562 v1[0] = 1;
563 v2 = mat * v2;
564 ang = fmod(v1.angle(v2), M_PI*2.0/sym->op[0].order);
565 view= View(0, 0, 1, ang);
566 mat = view.matrix() * mat;
567 }
568
569 if ( verbose & VERB_DEBUG ) {
570 cout << "Dihedral axis: " << v2 << endl;
571 cout << "Angle: " << ang*180.0/M_PI << endl;
572 }
573
574 for ( mol = molgroup->mol; mol; mol = mol->next ) {
575 for( res = mol->res; res; res = res->next ) {
576 for ( atom = res->atom; atom; atom = atom->next ) {
577 atom->coord += translate;
578 atom->coord = mat * atom->coord;
579 }
580 }
581 }
582
583 return 0;
584 }
585
608 int molgroup_orient_to_standard_view(Bmolgroup* molgroup, Bsymmetry* sym,
609 View ref_view, Bresidue_matrix* simat)
610 {
611 random_seed();
612
613 if ( sym->point < 102 ) {
614 kill_symmetry(sym);
615 return 0;
616 }
617
618 long i, j, k, m, nmol, nres_cut, cut_max(30), nunit, ngroup, nid, n2=0, nn=0, no;
619 Vector3<double> a2[1000], an[1000];
620 Bmolecule* mol, *mol2, *symmol;
621 Bresidue* res;
622 Batom* atom;
623
624 for ( nunit = 1, i=m=0; i<sym->n; i++ ) {
625 nunit *= sym->op[i].order;
626 if ( m < sym->op[i].order ) m = sym->op[i].order;
627 }
628
629 double a, refang = TWOPI/m;
630
631 for ( nmol = 0, mol = molgroup->mol; mol; mol = mol->next ) nmol++;
632 ngroup = nmol/nunit;
633
634 if ( ngroup < 1 ) {
635 cerr << "Error: Not enough molecules (" << nmol << ") to fit into " << nunit << " asymmetric units!" << endl << endl;
636 return -1;
637 }
638
639 molgroup_shift_to_center_of_mass(molgroup);
640
641 if ( verbose & VERB_PROCESS ) {
642 cout << "Orienting to the standard view for symmetry " << sym->label << endl;
643 cout << "Number of molecules: " << nmol << endl;
644 cout << "Number of groups: " << ngroup << endl;
645 }
646
647 int* g = new int[nmol]; // Group indices
648 for ( i=0; i<nmol; i++ ) g[i] = 0;
649
650 Transform t;
651 int offset, notfound;
652
653 // Calculate a matrix of rotations between pairs of molecules
654 for ( k=0, i=1; k<nmol; k++, i++, i=(i>ngroup)?1:i ) g[k] = i;
655 for ( i=0, mol = molgroup->mol; mol->next; mol = mol->next, i++ ) {
656 nres_cut = mol->nres/2;
657 if ( nres_cut > cut_max ) for ( j=i+1, mol2 = mol->next; mol2; mol2 = mol2->next, j++ ) {
658 // if two sequences can be aligned, find the transformation to superimpose them
659 offset = seq_find_best_offset(mol, mol2, nid, simat);
660 if ( nid > cut_max || nid >= nres_cut ) {
661 g[j] = g[i];
662 t = mol_find_transformation(mol, mol2, offset);
663 symmol = molecule_copy(mol);
664 mol_coor_rotate(symmol, t);
665 t.fom = mol_calculate_rmsd(mol2, symmol);
666 molecule_kill(symmol);
667 angle_set_negPI_to_PI(t.angle);
668 a = t.angle/refang;
669 no = (long) (a + 0.5);
670 if ( fabs(t.angle - M_PI) < 0.1 ) {
671 for ( k=0, notfound=1; k<n2 && notfound; k++ ) {
672 if ( a2[k].angle(t.axis) < 0.1 ) {
673 a2[k] += t.axis;
674 notfound = 0;
675 }
676 }
677 if ( notfound ) {
678 a2[n2] = t.axis;
679 n2++;
680 }
681 }
682 if ( fabs(a - no) < 0.03 ) {
683 for ( k=0, notfound=1; k<nn && notfound; k++ ) {
684 if ( an[k].angle(t.axis) < 0.1 ) {
685 an[k] += t.axis;
686 notfound = 0;
687 }
688 }
689 if ( notfound ) {
690 an[nn] = t.axis;
691 nn++;
692 }
693 }
694 m++;
695 }
696 }
697 }
698
699 if ( verbose & VERB_PROCESS ) {
700 cout << "Num\tMol\tGroup\tLength" << endl;
701 for ( i=0, mol = molgroup->mol; mol; mol = mol->next, i++ )
702 cout << i+1 << tab << mol->id << tab << g[i] << tab << mol->nres << endl;
703 cout << endl;
704 }
705
706 delete[] g;
707
708 double d, dm;
709 Vector3<double> axis1, axis2;
710
711 if ( sym->point == 202 || sym->point == 320 || sym->point == 532 ) {
712 // Pick the longest 2-fold axis
713 for ( k=0, dm=0; k<n2; k++ ) {
714 d = a2[k].length();
715 if ( dm < d ) {
716 dm = d;
717 axis1 = a2[k];
718 }
719 }
720 // Pick the longest perpendicular 2-fold axis
721 for ( k=0, dm=0; k<n2; k++ ) {
722 a = axis1.angle(a2[k]);
723 if ( fabs(a - M_PI_2) < 0.1 ) {
724 d = a2[k].length();
725 if ( dm < d ) {
726 dm = d;
727 axis2 = a2[k];
728 }
729 }
730 }
731 } else if ( sym->point == 432 ) {
732 // Pick the longest 4-fold axis
733 for ( k=0, dm=0; k<nn; k++ ) {
734 d = an[k].length();
735 if ( dm < d ) {
736 dm = d;
737 axis1 = an[k];
738 }
739 }
740 // Pick the longest perpendicular 4-fold axis
741 for ( k=0, dm=0; k<nn; k++ ) {
742 a = axis1.angle(an[k]);
743 if ( fabs(a - M_PI_2) < 0.1 ) {
744 d = an[k].length();
745 if ( dm < d ) {
746 dm = d;
747 axis2 = an[k];
748 }
749 }
750 }
751 } else {
752 // Pick the longest n-fold axis
753 for ( k=0, dm=0; k<nn; k++ ) {
754 d = an[k].length();
755 if ( dm < d ) {
756 dm = d;
757 axis1 = an[k];
758 }
759 }
760 // Pick the longest perpendicular 2-fold axis
761 for ( k=0, dm=0; k<n2; k++ ) {
762 a = axis1.angle(a2[k]);
763 if ( fabs(a - M_PI_2) < 0.1 ) {
764 d = a2[k].length();
765 if ( dm < d ) {
766 dm = d;
767 axis2 = a2[k];
768 }
769 }
770 }
771 }
772
773 if ( axis1.length() < 0.9 ) {
774 cerr << "Error: Major axis not found!" << endl;
775 }
776
777 if ( sym->point > 200 && axis2.length() < 0.9 ) {
778 cerr << "Error: Minor axis not found!" << endl;
779 }
780
781 axis1.normalize();
782 axis2.normalize();
783
784
785 // Translation required is the negative of the COM
786 // Vector3<double> translate = -(molgroup_center_of_mass(molgroup));
787
788 if ( verbose & VERB_LABEL ) {
789 if ( sym->point < 200 ) {
790 cout << "Symmetry axis: " << axis1 << endl;
791 } else {
792 cout << "Major symmetry axis: " << axis1 << endl;
793 cout << "Minor symmetry axis: " << axis2 << endl;
794 }
795 }
796
797 // The first matrix rotates it to the major symmetry axis
798 // The second does the in-plane rotation
799 Vector3<double> v1(0,0,1), v2(1,0,0);
800 Matrix3 mat = Matrix3(axis1, v1);
801 if ( sym->point > 200 ) {
802 v1 = mat * axis2;
803 mat = Matrix3(v1, v2) * mat;
804 }
805
806 for ( mol = molgroup->mol; mol; mol = mol->next ) {
807 for( res = mol->res; res; res = res->next ) {
808 for ( atom = res->atom; atom; atom = atom->next ) {
809 // atom->coord += translate;
810 atom->coord = mat * atom->coord;
811 }
812 }
813 }
814
815 return 0;
816 }
817
830 double molgroup_symmetry_RMSD(Bmolgroup* molgroup, Bsymmetry* sym)
831 {
832 int i, j, k, l, n, nmol;
833 double d, mind, R(0);
834 Vector3<double> coms;
835 Matrix3 mat(1);
836
837 Bmolecule* mol;
838
839 for ( nmol=0, mol=molgroup->mol; mol; mol=mol->next ) nmol++;
840
841 Vector3<double>* com = new Vector3<double>[nmol];
842
843 for ( i=0, mol=molgroup->mol; mol; mol=mol->next, i++ )
844 com[i] = mol_center_of_mass(mol);
845
846 for ( i=n=0; i<sym->n; i++ ) {
847 for ( j=1; j<sym->op[i].order; j++ ) {
848 mat = Matrix3(sym->op[i].axis, j*TWOPI/sym->op[i].order);
849 for ( k=0; k<nmol; k++ ) {
850 coms = mat * com[k];
851 for ( mind=1e30, l=0; l<nmol; l++ ) {
852 d = coms.distance(com[l]);
853 if ( mind > d ) mind = d;
854 }
855 R += mind*mind;
856 n++;
857 }
858 }
859 }
860
861 R = sqrt(R/n);
862
863 if ( verbose )
864 cout << "Symmetry RMSD: " << R << " A (" << n << ")" << endl << endl;
865
866 delete[] com;
867
868 return R;
869 }
870
883 double molgroup_symmetry_B(Bmolgroup* molgroup, Bsymmetry* sym)
884 {
885 long i, j, nmol(0), nsym(0);
886 double d, mind, R(0);
887 Vector3<double> coms, coor;
888 Matrix3 m(1);
889
890 Bmolecule* mol, *molr;
891 Bresidue* res, *resr;
892 Batom* atom, *atomr;
893
894 for ( nmol=0, mol=molgroup->mol; mol; mol=mol->next ) nmol++;
895
896 if ( verbose )
897 cout << "Calculating B-factors for symmetry " << sym->label << endl;
898
899 Vector3<double>* com = new Vector3<double>[nmol];
900 Matrix3* mat = symmetry_get_all_matrices(sym, nsym);
901
902 for ( i=0, mol=molgroup->mol; mol; mol=mol->next, i++ ) {
903 com[i] = mol_center_of_mass(mol);
904 for ( mind=1e30, j=0; j<nsym; j++ ) {
905 coms = mat[j] * com[i];
906 d = com[0].distance(coms);
907 if ( mind > d ) {
908 mind = d;
909 mol->sel = j;
910 }
911 }
912 cout << mol->id << endl << mat[mol->sel] << endl;
913 }
914
915 // Initialize the vectors for the first molecule
916 molr = molgroup->mol;
917 for( res = molr->res; res; res = res->next )
918 for ( atom = res->atom; atom; atom = atom->next ) {
919 atom->b = 0;
920 atom->vel = Vector3<double>(0,0,0);
921 }
922
923 // Accumulate the sums and square sums in the first molecule atoms
924 for ( i=0, mol=molgroup->mol; mol; mol=mol->next, i++ ) {
925 for( res = mol->res, resr = molr->res; res; res = res->next, resr = resr->next ) {
926 for ( atom = res->atom, atomr = resr->atom; atom; atom = atom->next, atomr = atomr->next ) {
927 // m = mat[i].transpose();
928 coor = mat[mol->sel] * atom->coord;
929 atomr->vel += coor;
930 atomr->b += coor.length2();
931 }
932 }
933 }
934
935 // Calculate the B factors in the first molecule
936 for( res = molr->res; res; res = res->next )
937 for ( atom = res->atom; atom; atom = atom->next )
938 atom->b = (atom->b - atom->vel.length2()/nmol)/nmol;
939
940 // Distribute the B factors to all molecules
941 for ( mol=molgroup->mol->next; mol; mol=mol->next )
942 for( res = mol->res, resr = molr->res; res; res = res->next, resr = resr->next )
943 for ( atom = res->atom, atomr = resr->atom; atom; atom = atom->next, atomr = atomr->next )
944 atom->b = atomr->b;
945
946 delete[] com;
947 delete[] mat;
948
949 return R;
950 }
951
963 int molgroup_generate_crystal(Bmolgroup* molgroup, UnitCell uc, Vector3<int> number)
964 {
965 if ( number.volume() < 2 ) return 0;
966
967 if ( !uc.check() ) {
968 cerr << "Error: Please specify the unit cell!" << endl;
969 return -1;
970 }
971
972 int i, x, y, z, nmol(0);
973 Vector3<double> d;
974 Matrix3 mat(uc.a(), uc.b()*cos(uc.gamma()), uc.c()*cos(uc.beta()),
975 0, uc.b()*sin(uc.gamma()), uc.c()*(cos(uc.alpha()) - cos(uc.beta())*cos(uc.gamma()))/sin(uc.gamma()),
976 0, 0, uc.volume()/(uc.a()*uc.b()*sin(uc.gamma())));
977 Bmolecule *mol, *newmol;
978 Bresidue *res, *newres;
979 Batom *atom, *newatom;
980
981 for ( nmol=0, mol = molgroup->mol; mol; mol = mol->next ) nmol++;
982
983 if ( verbose ) {
984 cout << "Generating new unit cells for " << nmol << " molecules:" << endl;
985 cout << "Number: " << number << " = " << (int)number.volume() << endl;
986 }
987
988 for ( z=0; z<number[2]; z++ ) {
989 for ( y=0; y<number[1]; y++ ) {
990 for ( x=0; x<number[0]; x++ ) {
991 if ( verbose )
992 cout << "Generating unit cell: " << x << " " << y << " " << z << endl;
993 d = Vector3<double>(x,y,z);
994 d = mat * d;
995 if ( x+y+z > 0 ) for ( i=0, mol = molgroup->mol; i<nmol; mol = mol->next, i++ ) {
996 newmol = mol_copy_and_add_to_molgroup(molgroup, mol);
997 for ( res = mol->res, newres = newmol->res; res; res = res->next, newres = newres->next ) {
998 for ( atom = res->atom, newatom = newres->atom; atom; atom = atom->next, newatom = newatom->next ) {
999 newatom->coord = atom->coord + d;
1000 }
1001 }
1002 }
1003 }
1004 }
1005 }
1006
1007 return 0;
1008 }
1009
seq_align.h
Header file for functions to generate and analyze dot plots.
Bmolgroup::angle
Bangle * angle
Definition: rwmolecule.h:191
Bmolecule::id
Bstring id
Definition: rwmolecule.h:110
M_PI_2
#define M_PI_2
Definition: utilities.h:62
UnitCell
Definition: UnitCell.h:22
Bmolgroup::mol
Bmolecule * mol
Definition: rwmolecule.h:189
Vector3::cross
Vector3 cross(const Vector3 &v)
Definition: Vector3.h:250
rwresprop.h
Header file for reading residue property files.
Vector3::normalize
double normalize()
Definition: Vector3.h:236
random_seed
long random_seed()
Gets a random seed and sets the flag.
Definition: random_numbers.cpp:41
Vector3::length
double length()
Definition: Vector3.h:222
Bsymmetry::n
int n
Definition: symmetry.h:42
Bmolecule::nres
long nres
Definition: rwmolecule.h:111
UnitCell::volume
double volume()
Definition: UnitCell.h:56
UnitCell::gamma
void gamma(double d)
Definition: UnitCell.h:41
symmetry.h
Header file for general symmetry functions.
molgroup_symmetry_B
double molgroup_symmetry_B(Bmolgroup *molgroup, Bsymmetry *sym)
Calculates the B factors from symmetry-related molecules.
Definition: mol_symmetry.cpp:883
utilities.h
Header file for general utilities.
molecule_kill
int molecule_kill(Bmolecule *mol)
Destroys a molecule.
Definition: rwmolecule.cpp:417
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
Bmolecule::res
Bresidue * res
Definition: rwmolecule.h:122
angle_set_negPI_to_PI
double angle_set_negPI_to_PI(double angle)
Returns an angle between -PI and PI.
Definition: utilities.cpp:594
UnitCell::beta
void beta(double d)
Definition: UnitCell.h:40
Transform::angle
double angle
Definition: Transform.h:29
molgroup_symmetry_RMSD
double molgroup_symmetry_RMSD(Bmolgroup *molgroup, Bsymmetry *sym)
Calculates the RMSD for symmetry in the standard orientation.
Definition: mol_symmetry.cpp:830
Bangle::next
Bangle * next
Definition: rwmolecule.h:151
Transform::fom
double fom
Definition: Transform.h:32
Matrix3
Definition: Matrix3.h:17
mol_transform.h
Library routines used for atomic coordinate transformations.
molgroup_orient_to_standard_view
int molgroup_orient_to_standard_view(Bmolgroup *molgroup, Bsymmetry *sym, View ref_view, Bresidue_matrix *simat)
Searches for the standard view based on point group symmetry.
Definition: mol_symmetry.cpp:608
kill_symmetry
int kill_symmetry(Bsymmetry *sym)
Deallocates a symmetry structure.
Definition: symmetry.cpp:207
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
UnitCell::a
void a(double d)
Definition: UnitCell.h:36
molecule_copy
Bmolecule * molecule_copy(Bmolecule *mol)
Copies a molecule.
Definition: rwmolecule.cpp:599
seq_find_best_offset
int seq_find_best_offset(Bmolecule *mol1, Bmolecule *mol2, long &nres, Bresidue_matrix *simat)
Finds the best offset for aligning two sequences without gaps.
Definition: seq_align.cpp:94
Vector3::distance
double distance(const Vector3 &v)
Definition: Vector3.h:227
Bangle
Definition: rwmolecule.h:150
mol_find_transformation
Transform mol_find_transformation(Bmolecule *mol1, Bmolecule *mol2, int offset)
Determines the transformation between two identical molecules.
Definition: mol_compare.cpp:139
mol_symmetry.h
Library routines used for symmetry operations on atomic coordinates.
View::vector_size
double vector_size()
Definition: View.h:103
Matrix3.h
3x3 Matrix manipulation functions
mol_util.h
Library routines used for atomic coordinates.
MassCOM::com
Vector3< double > com
Definition: mol_symmetry.cpp:333
Bstring::contains
bool contains(const Bstring &s)
Definition: Bstring.cpp:584
Transform
Definition: Transform.h:24
M_PI
#define M_PI
Definition: utilities.h:59
rwmolecule.h
Header file for reading reflection files.
molgroup_generate_helix
int molgroup_generate_helix(Bmolgroup *molgroup, View ref_view, double helix_rise, double helix_angle, int gen_down, int gen_up)
Generates a helix from the given parameters.
Definition: mol_symmetry.cpp:135
Bmolgroup
Definition: rwmolecule.h:170
Bsymmetry::point
int point
Definition: symmetry.h:39
mol_calculate_rmsd
double mol_calculate_rmsd(Bmolecule *mol1, Bmolecule *mol2)
Calculates the RMSD between two molecules.
Definition: mol_compare.cpp:270
molgroup_copy
Bmolgroup * molgroup_copy(Bmolgroup *molgroup)
Copies a molecule group.
Definition: rwmolecule.cpp:547
symmetry_get_all_matrices
Matrix3 * symmetry_get_all_matrices(Bsymmetry *sym, long &nsym)
Get all symmetry-related views of one given view.
Definition: symmetry.cpp:520
Vector3::angle
double angle(Vector3< T2 > &v)
Definition: Vector3.h:257
matrix3_show_hp
int matrix3_show_hp(Matrix3 &mat)
Print out a matrix.
Definition: Matrix3.cpp:31
rwatomprop.h
Header file for reading atom property files.
molgroup_apply_symmetry_from_pdb
int molgroup_apply_symmetry_from_pdb(Bmolgroup *molgroup, Bstring &filename)
Generates all symmetry-related coordinates using PDB file matrices.
Definition: mol_symmetry.cpp:200
UnitCell::b
void b(double d)
Definition: UnitCell.h:37
Bmolecule::next
Bmolecule * next
Definition: rwmolecule.h:108
molgroup_apply_matrices_from_pdb
int molgroup_apply_matrices_from_pdb(Bmolgroup *molgroup, Bstring &filename)
Generates all symmetry-related coordinates using PDB file matrices.
Definition: mol_symmetry.cpp:270
Batom::b
double b
Definition: rwmolecule.h:31
Bsymop::order
int order
Definition: symmetry.h:26
molgroup_find_standard_view
int molgroup_find_standard_view(Bmolgroup *molgroup, Bsymmetry *sym, View ref_view)
Searches for the standard view based on point group symmetry.
Definition: mol_symmetry.cpp:366
molgroup_shift_to_center_of_mass
int molgroup_shift_to_center_of_mass(Bmolgroup *molgroup)
Translates a set of coordinates to the center of mass.
Definition: mol_transform.cpp:625
Bmolgroup::next
Bmolgroup * next
Definition: rwmolecule.h:171
Bresidue_matrix
Definition: rwresprop.h:44
Vector3::length2
double length2()
Definition: Vector3.h:221
Bresidue::atom
Batom * atom
Definition: rwmolecule.h:54
Bstring::c_str
const char * c_str()
Definition: Bstring.h:70
Bmolecule
Definition: rwmolecule.h:107
mol_coor_rotate
int mol_coor_rotate(Bmolecule *mol, Transform t)
Rotates and translates a molecule.
Definition: mol_transform.cpp:131
Bsymmetry::label
Bstring label
Definition: symmetry.h:41
Bsymmetry
Definition: symmetry.h:38
molgroup_list_kill
int molgroup_list_kill(Bmolgroup *molgroup)
Destroys a molecule group linked list.
Definition: rwmolecule.cpp:347
Bmolgroup::bond
Bbond * bond
Definition: rwmolecule.h:190
Bresidue::next
Bresidue * next
Definition: rwmolecule.h:50
Bresidue
Definition: rwmolecule.h:49
random_numbers.h
Header file for functions for creating random images.
UnitCell::alpha
void alpha(double d)
Definition: UnitCell.h:39
Bstring
Definition: Bstring.h:29
mol_copy_and_add_to_molgroup
Bmolecule * mol_copy_and_add_to_molgroup(Bmolgroup *molgroup, Bmolecule *mol)
Copies a molecule and assign to a new pointer in the molgroup.
Definition: rwmolecule.cpp:664
View::matrix
Matrix3 matrix()
Definition: View.h:150
Batom
Definition: rwmolecule.h:24
matrix_linear.h
Header file for matrix functions.
MassCOM::mass
double mass
Definition: mol_symmetry.cpp:332
Bmolecule::sel
int sel
Definition: rwmolecule.h:120
Vector3< double >
View::angle
double angle()
Definition: View.h:95
View
Definition: View.h:26
Batom::coord
Vector3< double > coord
Definition: rwmolecule.h:30
Bbond
Definition: rwmolecule.h:134
Bbond::next
Bbond * next
Definition: rwmolecule.h:135
MassCOM
Definition: mol_symmetry.cpp:331
molgroup_apply_point_group
int molgroup_apply_point_group(Bmolgroup *molgroup, Bsymmetry *sym, View ref_view)
Generates all symmetry-related coordinates.
Definition: mol_symmetry.cpp:34
Transform::axis
Vector3< double > axis
Definition: Transform.h:28
molgroup_generate_crystal
int molgroup_generate_crystal(Bmolgroup *molgroup, UnitCell uc, Vector3< int > number)
Generates unit cells from a set of coordinates.
Definition: mol_symmetry.cpp:963
UnitCell::check
bool check()
Definition: UnitCell.h:34
Bsymmetry::op
Bsymop * op
Definition: symmetry.h:43
Vector3::volume
double volume()
Definition: Vector3.h:235
VERB_FULL
#define VERB_FULL
Definition: utilities.h:109
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:106
mol_center_of_mass
Vector3< double > mol_center_of_mass(Bmolecule *mol)
Calculates the center of mass of a molecule.
Definition: mol_util.cpp:401
Bsymop::axis
Vector3< double > axis
Definition: symmetry.h:25
Batom::next
Batom * next
Definition: rwmolecule.h:25
Batom::mass
double mass
Definition: rwmolecule.h:32
TWOPI
#define TWOPI
Definition: utilities.h:68
Batom::vel
Vector3< double > vel
Definition: rwmolecule.h:35
molgroup_atom_renumber
int molgroup_atom_renumber(Bmolgroup *molgroup, int first)
Renumbers all atoms, disregarding molecule distinction.
Definition: mol_util.cpp:211
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
UnitCell::c
void c(double d)
Definition: UnitCell.h:38
mol_compare.h
Library routines used to compare sets of atomic coordinates.
verbose
int verbose