Fixed a bug in the pdb-writing code.
[gromacs.git] / src / tools / cdist.c
blob34144913300f927c75a76957cdb0d33d44d7650e
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.1
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
29 * And Hey:
30 * Gromacs Runs One Microsecond At Cannonball Speeds
32 static char *SRCID_cdist_c = "$Id$";
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include "assert.h"
36 #include "macros.h"
37 #include "vec.h"
38 #include "txtdump.h"
39 #include "cdist.h"
40 #include "invblock.h"
41 #include "futil.h"
42 #include "tpxio.h"
43 #include "rdgroup.h"
45 #define NINDEX(ai,aj,natom) (natom*(ai)-((ai)*(ai+1))/2+(aj)-(ai))
46 #define INDEX(ai,aj,natom) ((ai) < (aj))?NINDEX((ai),(aj),natom):NINDEX(aj,ai,natom)
47 #define CHECK(ai,natom) if (((ai)<0) || ((ai)>=natom)) fatal_error(0,"Invalid atom number %d",ai+1)
49 static real vdwlen(t_atoms *atoms,int i,int j)
51 #define NAT 5
52 char anm[NAT] = "HCNOS";
53 /* For time being I give S the same vdw-parameters as O */
54 real dist[NAT][NAT] = {
55 { 2.0, 2.4, 2.4, 2.3, 2.3 },
56 { 2.4, 3.0, 2.9, 2.75, 2.75 },
57 { 2.4, 2.9, 2.7, 2.7, 2.7 },
58 { 2.3, 2.75, 2.7, 2.8, 2.8 },
59 { 2.3, 2.75, 2.7, 2.8, 2.8 }
61 char ati,atj;
62 int ai,aj;
64 ati=toupper((*atoms->atomname[i])[0]);
65 atj=toupper((*atoms->atomname[j])[0]);
67 for(ai=0; (ai<NAT) && (ati != anm[ai]); ai++)
69 for(aj=0; (aj<NAT) && (atj != anm[aj]); aj++)
71 if ((ai < NAT) && (aj < NAT))
72 return dist[ai][aj];
73 else {
74 fprintf(stderr,"No combination for nbs (%c %c) using 2.0 A\n",ati,atj);
75 return 2.0;
79 void set_dist(t_dist *d,int natoms,int ai,int aj,real lb,
80 real ub,real len)
82 int index;
84 if (ub <= lb)
85 fprintf(stderr,"set_dist: lb = %f, ub = %f, len = %f, atoms %d,%d\n",
86 lb,ub,len,ai,aj);
87 else {
88 CHECK(ai,natoms);
89 CHECK(aj,natoms);
90 index = INDEX(ai,aj,natoms);
91 d[index].lb = lb;
92 d[index].ub = ub;
93 d[index].len = len;
97 void set_ideal(t_dist *d,int natoms,int ai,int aj,real len)
99 int index;
101 CHECK(ai,natoms);
102 CHECK(aj,natoms);
103 index = INDEX(ai,aj,natoms);
104 d[index].len = len;
107 bool dist_set(t_dist *d,int natoms,int ai,int aj)
109 int index;
111 index = INDEX(ai,aj,natoms);
113 return (d[index].lb != 0.0);
116 static t_dist *new_dist(int natom)
118 t_dist *d;
120 snew(d,(natom*(natom+1))/2);
122 return d;
125 real d_lb(t_dist *d,int natoms,int ai,int aj)
127 int index;
129 index = INDEX(ai,aj,natoms);
131 return d[index].lb;
134 real d_ub(t_dist *d,int natoms,int ai,int aj)
136 int index;
138 index = INDEX(ai,aj,natoms);
140 return d[index].ub;
143 real d_len(t_dist *d,int natoms,int ai,int aj)
145 int index;
147 index = INDEX(ai,aj,natoms);
149 return d[index].len;
152 static t_dist *read_dist(FILE *log,char *fn,int natom,real weight[])
154 #define BLEN 255
155 FILE *fp;
156 char buf[BLEN+1];
157 int i,ai,aj,www,ndist;
158 double lb,ub,len;
159 t_dist *d;
161 fprintf(log,"Going to read %s\n",fn);
162 d = new_dist(natom);
163 fp = ffopen(fn,"r");
164 ndist = 0;
165 www = 0;
166 while (fgets2(buf,BLEN,fp) != NULL) {
167 if (buf[0] != '#') {
168 if (sscanf(buf,"%d%d%lf%lf%lf",&ai,&aj,&len,&lb,&ub) != 5)
169 if (sscanf(buf,"%d%d%lf%lf",&ai,&aj,&lb,&ub) != 4)
170 fatal_error(0,"Invalid dist format in %s",fn);
171 ai--;
172 aj--;
173 if ((weight[ai] != 0) || (weight[aj] != 0)) {
174 if (!dist_set(d,natom,ai,aj)) {
175 if (debug)
176 fprintf(debug,"\r%d %d %d",ndist,ai,aj);
177 set_dist(d,natom,ai,aj,lb,ub,-1);
178 ndist++;
181 else
182 www++;
185 fclose(fp);
187 fprintf(stderr,
188 "Read %d distances from %s (discarded %d due to zero weight)\n",
189 ndist,fn,www);
190 fprintf(log,
191 "Read %d distances from %s (discarded %d due to zero weight)\n",
192 ndist,fn,www);
193 fflush(log);
195 return d;
198 static void measure_report(FILE *fp,int nm,int natom,int nover,int nnotideal,
199 int nhb_rep,int nhb,real cutoff,real rmsd)
201 double ndtot=(natom*(natom-1.0))/2.0;
203 fprintf(fp,"Determined %d distances out of a possible %.0f "
204 "(%.2f %%)\nby measuring from the structure within %f A\n",
205 nm,ndtot,(nm*100.0)/ndtot,cutoff);
206 fprintf(fp,"%d distances from the database were replaced by measured ones\n",
207 nover);
208 fprintf(fp,"Of these, %d were not within the bounds of the database.\n"
209 "RMS deviation from bound limits for these was %e A.\n",
210 nnotideal,rmsd);
211 fprintf(fp,"For %d hydrogen bonds out of %d in the index file the margins "
212 "were reduced\n",nhb_rep/2,nhb/3);
213 fflush(fp);
216 static void measure_dist(FILE *log,t_dist *d,t_atoms *atoms,rvec x[],
217 real cutoff,real margin,real hbmargin,
218 int nhb,atom_id hb[])
220 int i,j,natom,dd,aa,ai,aj,nm,nover,nnotideal,nhb_rep;
221 real msd,rmsd;
222 rvec dx;
223 real ideal,lbfac,ubfac,vdw,lb,ub,nmargin;
225 nm = 0;
226 nover = 0;
227 nnotideal = 0;
228 msd = 0;
229 natom = atoms->nr;
231 lbfac = 1-margin;
232 ubfac = 1+margin;
234 for(ai=0; (ai<natom); ai++)
235 for(aj=ai+1; (aj<natom); aj++) {
236 rvec_sub(x[ai],x[aj],dx);
237 ideal = 10*norm(dx);
238 if (ideal == 0.0) {
239 fprintf(stderr,"Warning distance between atoms %s and %s is zero\n",
240 atomname(atoms,ai),atomname(atoms,aj));
242 else {
243 if (!dist_set(d,natom,ai,aj)) {
244 /* This distance is not determined by the database. */
245 vdw = 0; /*vdwlen(atoms,ai,aj);*/
246 if ((ideal < cutoff) || (cutoff == 0)) {
247 set_dist(d,natom,ai,aj,max(vdw,ideal*lbfac),ideal*ubfac,ideal);
248 nm++;
251 else {
252 /* These distances are already set by the database routines.
253 * However, we override the distances with the measured ones
254 * while keeping the original margins.
256 lb = d_lb(d,natom,ai,aj);
257 ub = d_ub(d,natom,ai,aj);
258 if ((ideal < lb) || (ideal > ub)) {
259 if (debug)
260 fprintf(debug,"Warning: d(%s,%s) = %8.4f. According to E&H"
261 " it should be %8.4f (dev. %.1f%%)\n",
262 atomname(atoms,ai),
263 atomname(atoms,aj),
264 ideal,(lb+ub)*0.5,50*fabs(ideal*2-lb-ub));
265 msd += (ideal < lb) ? sqr(ideal-lb) : sqr(ideal-ub);
266 nnotideal++;
268 nmargin = (ub-lb)/(ub+lb);
269 set_dist(d,natom,ai,aj,ideal*(1-nmargin),ideal*(1+nmargin),ideal);
270 nm++;
271 nover++;
275 /* Now we have set all the distances. We have to verify though
276 * that h bonds are maintained, we therefore reduce their margins.
278 nhb_rep = 0;
279 for(i=0; (i<nhb); i+= 3) {
280 /* Acceptor atom */
281 aa = hb[i+2];
282 assert(aa < natom);
283 for(j=0; (j<2); j++) {
284 /* Donor atom */
285 dd = hb[i+j];
286 assert(dd < natom);
287 if (dist_set(d,natom,dd,aa)) {
288 lb = d_lb(d,natom,dd,aa);
289 ub = d_ub(d,natom,dd,aa);
290 ideal = d_len(d,natom,dd,aa);
291 nmargin = (ub-lb)/(ub+lb);
292 if (hbmargin < nmargin) {
293 set_dist(d,natom,dd,aa,ideal*(1-hbmargin),ideal*(1+hbmargin),ideal);
294 nhb_rep++;
297 else
298 fatal_error(0,"Distance between %s and %s not set, while they do make"
299 " a hbond:\nincrease radius for measuring (now %f A)\n",
300 atomname(atoms,aa),atomname(atoms,dd),cutoff);
304 if (nnotideal > 0)
305 rmsd = sqrt(msd/nnotideal);
306 else
307 rmsd = 0;
308 measure_report(log,nm,natom,nover,nnotideal,nhb_rep,nhb,cutoff,rmsd);
309 measure_report(stderr,nm,natom,nover,nnotideal,nhb_rep,nhb,cutoff,rmsd);
312 static void dump_dist(char *fn,t_dist *d,int natom,bool bAddR)
314 FILE *fp;
315 int i,j;
316 real lb,ub,len;
318 fp = ffopen(fn,"w");
319 fprintf(fp,"# distance file generated by cdist\n");
321 for(i=0; (i<natom); i++) {
322 for(j=i+1; (j<natom); j++) {
323 if (dist_set(d,natom,i,j)) {
324 lb = d_lb(d,natom,i,j);
325 ub = d_ub(d,natom,i,j);
326 len = d_len(d,natom,i,j);
327 if (bAddR)
328 fprintf(fp,"%5d%5d%10.5f%10.5f\n",i+1,j+1,lb,ub);
329 else
330 fprintf(fp,"%5d%5d%10.5f%10.5f%10.5f\n",i+1,j+1,len,lb,ub);
331 /* Output for real-precision disco: */
332 /* fprintf(fp,"%5d%5d%15.10f%15.10f%15.10f\n",i+1,j+1,len,lb,ub); */
336 fclose(fp);
339 static real *read_weights(char *fn,int natom)
341 FILE *in;
342 int i,n;
343 char title[STRLEN];
344 real *w;
345 matrix box;
346 t_atoms atoms;
347 rvec *x;
349 /* Open file */
350 in = ffopen(fn,"r");
352 /* Check the number of atoms */
353 get_pdb_coordnum(in,&n);
354 if (n != natom)
355 fatal_error(0,"Number of atoms in pdb file (%d) does not match tpx (%d)",
356 n,natom);
358 /* Allocate space */
359 snew(w,natom);
360 snew(x,natom);
361 init_t_atoms(&atoms,natom,TRUE);
362 clear_mat(box);
364 /* Now read it all */
365 rewind(in);
366 read_pdbfile(in,title,NULL,&atoms,x,box,FALSE);
367 fclose(in);
368 fprintf(stderr,"%s\n",title);
370 /* Now copy the weights */
371 for(i=0; (i<natom); i++)
372 w[i] = atoms.pdbinfo[i].occup;
374 /* Now free temps */
375 sfree(x);
376 free_t_atoms(&atoms);
378 /* And go back */
379 return w;
382 void init_rot_matrix(real mat[3][3],real theta, real omega)
384 mat[0][0] = -(cos(theta)*cos(omega));
385 mat[1][0] = -(cos(theta)*sin(omega));
386 mat[2][0] = sin(theta);
388 mat[0][1] = sin(omega);
389 mat[1][1] = -(cos(omega));
390 mat[2][1] = 0.0;
392 mat[0][2] = sin(theta)*cos(omega);
393 mat[1][2] = sin(theta)*sin(omega);
394 mat[2][2] = cos(theta);
397 void vect_matrix(real vect[3], real mat[3][3])
400 real tmp[3];
401 int i,j;
403 tmp[0] = 0.0;
404 tmp[1] = 0.0;
405 tmp[2] = 0.0;
407 for ( i=0 ; i <= 2 ; i++ ) {
408 for ( j=0 ; j <=2 ; j++ ) {
409 tmp[i]=tmp[i]+mat[i][j]*vect[j];
412 for ( i=0 ; i <=2 ; i++ ) {
413 vect[i]=tmp[i];
417 void gauche_(int ai,int aj,int ak,int al,t_ilist ilist[],
418 t_iparams iparams[],real *lb,t_atoms *atoms,char *file,int line)
421 /* Matrix based approach */
422 int i,j;
423 real matrix1[3][3],matrix2[3][3];
424 real vect1[3],vect2[3],vect3[3];
425 real dist = 0.0;
426 real pi = M_PI;
427 real half_pi = M_PI*0.5;
428 real rij,rjk,rkl;
429 real thijk,thjkl,theta1,theta2,omega1=pi,omega2 = pi+pi/3.0;
431 rij = lookup_bondlength_(ai,aj,ilist,iparams,TRUE,atoms,file,line);
432 rjk = lookup_bondlength_(aj,ak,ilist,iparams,TRUE,atoms,file,line);
433 rkl = lookup_bondlength_(ak,al,ilist,iparams,TRUE,atoms,file,line);
434 thijk = lookup_angle_(ai,aj,ak,ilist,iparams,atoms,file,line);
435 thjkl = lookup_angle_(aj,ak,al,ilist,iparams,atoms,file,line);
436 theta1 = pi-thijk;
437 theta2 = pi-thjkl;
439 /*Initialise vectors*/
440 vect1[0]=0.0;
441 vect1[1]=0.0;
442 vect1[2]=rij;
443 vect2[0]=0.0;
444 vect2[1]=0.0;
445 vect2[2]=rjk;
446 vect3[0]=0.0;
447 vect3[1]=0.0;
448 vect3[2]=rkl;
450 /*Initialize matrices*/
451 init_rot_matrix(matrix1,theta1,omega1);
452 init_rot_matrix(matrix2,theta2,omega2);
454 /* Express vect2 and vect3 in coord. system of vect1 */
455 vect_matrix(vect2,matrix1);
456 vect_matrix(vect3,matrix2);
457 vect_matrix(vect3,matrix1);
459 /* Add vectors */
460 for ( i=0 ; i <=2 ; i++) {
461 vect3[i] = vect1[i]+vect2[i]+vect3[i];
464 /* Calculate distance */
465 *lb = sqrt(vect3[0]*vect3[0]+vect3[1]*vect3[1]+vect3[2]*vect3[2]);
469 void gauche15_(int ai,int aj,int ak,int al,int am,real omega1,real omega2,
470 real omega3,t_ilist ilist[],t_iparams iparams[],real *lb,
471 t_atoms *atoms,char *file,int line)
474 /* Matrix based approach */
475 int i,j;
476 real matrix1[3][3],matrix2[3][3],matrix3[3][3];
477 real vect1[3],vect2[3],vect3[3],vect4[3];
478 real pi = M_PI;
479 real half_pi = M_PI*0.5;
480 real rij,rjk,rkl,rlm;
481 real thijk,thjkl,thklm,theta1,theta2,theta3;
483 rij = lookup_bondlength_(ai,aj,ilist,iparams,TRUE,atoms,file,line);
484 rjk = lookup_bondlength_(aj,ak,ilist,iparams,TRUE,atoms,file,line);
485 rkl = lookup_bondlength_(ak,al,ilist,iparams,TRUE,atoms,file,line);
486 rlm = lookup_bondlength_(al,am,ilist,iparams,TRUE,atoms,file,line);
487 thijk = lookup_angle_(ai,aj,ak,ilist,iparams,atoms,file,line);
488 thjkl = lookup_angle_(aj,ak,al,ilist,iparams,atoms,file,line);
489 thklm = lookup_angle_(ak,al,am,ilist,iparams,atoms,file,line);
490 theta1 = pi-thijk;
491 theta2 = pi-thjkl;
492 theta3 = pi-thklm;
494 /*Initialise vectors*/
495 vect1[0]=0.0;
496 vect1[1]=0.0;
497 vect1[2]=rij;
498 vect2[0]=0.0;
499 vect2[1]=0.0;
500 vect2[2]=rjk;
501 vect3[0]=0.0;
502 vect3[1]=0.0;
503 vect3[2]=rkl;
504 vect4[0]=0.0;
505 vect4[1]=0.0;
506 vect4[2]=rlm;
508 /*Initialize matrices*/
509 init_rot_matrix(matrix1,theta1,omega1);
510 init_rot_matrix(matrix2,theta2,omega2);
511 init_rot_matrix(matrix3,theta3,omega3);
513 /* Express vect2 and vect3 in coord. system of vect1 */
514 vect_matrix(vect2,matrix1);
515 vect_matrix(vect3,matrix2);
516 vect_matrix(vect3,matrix1);
517 vect_matrix(vect4,matrix3);
518 vect_matrix(vect4,matrix2);
519 vect_matrix(vect4,matrix1);
521 /* Add vectors */
522 for ( i=0 ; i <=2 ; i++) {
523 vect4[i] = vect1[i]+vect2[i]+vect3[i]+vect4[i];
526 /* Calculate distance */
527 *lb = sqrt(vect4[0]*vect4[0]+vect4[1]*vect4[1]+vect4[2]*vect4[2]);
531 static void dump_bonds(t_atoms *atoms,t_dist *d,
532 t_ilist ilist[],t_functype functype[],
533 t_iparams ip[],real bond_margin,real angle_margin,
534 real dih_margin,real idih_margin,
535 real weight[],bool bAddR)
537 int dodist[] = { F_BONDS, F_MORSE, F_SHAKE, F_G96BONDS,
538 F_G96ANGLES, F_ANGLES, F_IDIHS /*,F_RBDIHS, F_PDIHS*/ };
539 int i,j,atom1,atom2,ai,aj,ak,al,type,ftype,nra,ndist,odist,natoms;
540 real blen,rij,rjk,c6,c12,lb=-1,ub,theta;
542 natoms= atoms->nr;
543 ndist = 0;
544 odist = 0;
546 for(j=0; (j<asize(dodist)); j++) {
547 ftype = dodist[j];
548 nra = interaction_function[ftype].nratoms;
549 for(i=0; (i<ilist[ftype].nr); i+=nra+1) {
550 type = ilist[ftype].iatoms[i];
551 ai = ilist[ftype].iatoms[i+1];
552 aj = ilist[ftype].iatoms[i+2];
553 atom1 = ai;
554 atom2 = aj;
555 blen = 0;
556 switch (ftype) {
557 case F_BONDS:
558 case F_MORSE:
559 case F_SHAKE:
560 blen = lookup_bondlength(ai,aj,ilist,ip,TRUE,atoms);
561 break;
562 case F_G96ANGLES:
563 case F_ANGLES:
564 ak = ilist[ftype].iatoms[i+3];
565 theta = lookup_angle(ai,aj,ak,ilist,ip,atoms);
566 blen = angle_length(ai,aj,ak,RAD2DEG*theta,ilist,ip,atoms);
567 atom2 = ak;
568 break;
569 case F_PDIHS:
570 case F_RBDIHS:
571 ak = ilist[ftype].iatoms[i+3];
572 al = ilist[ftype].iatoms[i+4];
573 pdih_lengths(ai,aj,ak,al,ilist,ip,&blen,&ub,atoms);
574 atom2 = al;
575 break;
576 case F_IDIHS:
577 ak = ilist[ftype].iatoms[i+3];
578 al = ilist[ftype].iatoms[i+4];
579 blen = idih_lengths(ai,aj,ak,al,ilist,ip,atoms);
580 atom2 = al;
581 break;
582 default:
583 break;
585 if ((blen != 0) && ((weight[atom1] != 0.0) || (weight[atom2] != 0.0))) {
586 switch (ftype) {
587 case F_BONDS:
588 case F_MORSE:
589 case F_SHAKE:
590 case F_G96BONDS:
591 lb = (1.0-bond_margin)*blen;
592 ub = (1.0+bond_margin)*blen;
593 break;
594 case F_ANGLES:
595 case F_G96ANGLES:
596 lb = (1.0-angle_margin)*blen;
597 ub = (1.0+angle_margin)*blen;
598 break;
599 case F_IDIHS:
600 lb = (1-idih_margin)*blen;
601 ub = (1+idih_margin)*blen;
602 break;
603 case F_PDIHS:
604 case F_RBDIHS:
605 lb = (1.0-dih_margin)*blen;
606 ub = (1.0+dih_margin)*ub;
607 break;
609 if (!dist_set(d,natoms,atom1,atom2)) {
610 set_dist(d,natoms,atom1,atom2,lb,ub,blen);
611 ndist ++;
613 else
614 odist ++;
618 fprintf(stderr,"There are %d new bonded distances + %d old\n",ndist,odist);
621 static bool notexcl(t_block *excl,int ai,int aj)
623 int i;
625 for(i=excl->index[ai]; (i<excl->index[ai+1]); i++) {
626 if (aj == excl->a[i])
627 return FALSE;
629 return TRUE;
632 static void dump_nonbonds(t_dist *d,t_idef *idef,t_atoms *atoms,
633 real hblen,real weight[],
634 real nb_margin,bool bAddR,
635 real maxdist)
637 int i,j,k,natoms,ntype,tpi,tpj,ndist,odist;
638 real **dmat,len,lb;
639 bool *bDA;
640 char element,ati,atj;
642 ntype = idef->atnr;
643 natoms = atoms->nr;
645 /* Determine which atoms are capable of H bonding or not */
646 snew(bDA,ntype);
647 for(j=0; (j<ntype); j++)
648 for(i=0; (i<natoms); i++) {
649 if (atoms->atom[i].type == j) {
650 element = (*atoms->atomname[i])[0];
651 bDA[j] = ((element == 'N') || (element == 'O'));
652 break;
656 /* Make a distance matrix for VDWaals distances */
657 /*snew(dmat,ntype);
658 for(i=0; (i<ntype); i++) {
659 snew(dmat[i],ntype);
660 for(j=0; (j<ntype); j++) {
661 if (bDA[i] && bDA[j])
662 dmat[i][j] = hblen;
663 else
664 dmat[i][j] = vdwlen(idef,i,j,hblen);
666 } */
667 sfree(bDA);
669 /* Now loop over atom pairs */
670 ndist = 0;
671 odist = 0;
672 for(i=0; (i<natoms); i++) {
673 tpi = atoms->atom[i].type;
674 for(j=i+1; (j<natoms); j++) {
675 if (((weight[i] != 0.0) || (weight[j] != 0.0))
676 /*&& (notexcl(&atoms->excl,i,j))*/) {
677 if (!dist_set(d,natoms,i,j)) {
678 /* We don't care about virtual particles */
679 ati=(*atoms->atomname[i])[0];
680 atj=(*atoms->atomname[j])[0];
681 if ( !(ati == 'V' || atj == 'V') ) {
682 /* *** */
683 tpj = atoms->atom[j].type;
684 len = vdwlen(atoms,i,j);
685 lb = (1-nb_margin)*len;
686 if (len > 0) {
687 set_dist(d,natoms,i,j,lb,maxdist,0.0);
688 /* set_dist(d,natoms,i,j,lb,0.0,lb); */
689 ndist++;
693 else
694 odist++;
698 fprintf(stderr,"There are %d new non-bonded distances + %d old ones\n",
699 ndist,odist);
702 static void release_domains(FILE *fp,char *ndx,t_dist dist[],t_atoms *atoms,
703 real maxdist)
705 t_block *doms;
706 char **grpname=NULL;
707 int i,j,k,ii,jj,ai,aj,natoms;
708 real lb;
710 natoms = atoms->nr;
711 doms = init_index(ndx,&grpname);
712 if (doms->nr > 1) {
713 fprintf(fp,"Found %d domains, named:\n",doms->nr);
714 for(i=0; (i<doms->nr); i++)
715 fprintf(fp,"%3d %s\n",i,grpname[i]);
716 fflush(fp);
717 for(i=0; (i<doms->nr); i++) {
718 for(ii=doms->index[i]; (ii<doms->index[i+1]); ii++) {
719 ai = doms->a[ii];
720 for(j=i+1; (j<doms->nr); j++) {
721 for(jj=doms->index[j]; (jj<doms->index[j+1]); jj++) {
722 aj = doms->a[jj];
723 if (dist_set(dist,natoms,ai,aj)) {
724 lb = vdwlen(atoms,ai,aj);
725 set_dist(dist,natoms,ai,aj,lb,maxdist,0.0);
732 done_block(doms);
733 sfree(doms);
736 int main(int argc,char *argv[])
738 static char *desc[] = {
739 "cdist read a [BB]tpx[bb] file and dumps an input file for disco.",
740 "Bond lengths etc. are read from the topology. Pairs of atoms that can",
741 "form hydrogen bonds are given a lowest possible distance of",
742 "[BB]hblen[bb] (can be specified by the user). Other nonbonded pairs",
743 "take their minimum distance from the Lennard Jones parameters",
744 "(at the combined sigma).[PAR]",
745 "The program uses proper dihedrals to give a distance too, as minimum",
746 "respectively maximum the [IT]cis[it] and [IT]trans[it] configurations",
747 "are taken. It is therefore beneficial to use the [BB]-alldih[bb] option",
748 "of [TT]pdb2gmx[tt] to generate a topology with all dihedrals in there.",
749 "If the optional pdb file is given, weights are read from the occupancy",
750 "field, so that",
751 "not all atoms are part of the disco run, only those of which one of the",
752 "weights is non-zero.[PAR]",
753 "If the option -engh is on (default) bond lengths and angles etc. are",
754 "read from another database, which is basically the Engh-Huber data",
755 "but refined to be completely self consistent. The database name is",
756 "refi_aa.dat and it resides in the $GMXLIB directory, or in the current",
757 "directory.[PAR]",
758 "The program can read a file with distances from NMR distance restraints",
759 "(-d option). Note that these distance are treated slightly different",
760 "in the disco program, and therefore these distance should be NMR",
761 "derived distance restraints only.[PAR]",
762 "Furthermore, the program can read an index file with hydrogen bond",
763 "information as generated by [TT]g_hbond[tt]. This is then used to set",
764 "tighter restraints on the hydrogen bonded atoms than on the other",
765 "non bonded atom pairs, in order to maintain secondary structure.",
766 "This option is useful only in combination with the [TT]-measure[tt]",
767 "option, when a sensible structure is known.[PAR]",
768 "The option [TT]-dom[tt] can be used to release distances bounds between",
769 "different domains to the lower bounds given by Van der Waals contacts.",
770 "This way, different domains can move independently, but without",
771 "overlapping. The index file should contain domains that do not overlap",
772 "with each other."
774 t_filenm fnm[] = {
775 { efTPS, "-s", NULL, ffREAD },
776 { efLOG, "-g", "cdist", ffWRITE },
777 { efPDB, "-q", NULL, ffOPTRD },
778 { efDAT, "-d", NULL, ffOPTRD },
779 { efDAT, "-o", "cdist", ffWRITE },
780 { efNDX, "-n", "hbond", ffOPTRD },
781 { efNDX, "-dom","domain",ffOPTRD }
783 #define NFILE asize(fnm)
785 FILE *fp;
786 t_topology *top;
787 t_dist *dist;
788 real *weight;
789 rvec *x;
790 matrix box;
791 char *topfn,title[256];
792 int i,nhb;
793 atom_id *hb;
794 char *grpname;
796 /* Tolerance used in smoothing functions (real precision)*/
798 /* Hacked 990609 by Adam */
800 /* Command line options */
801 static real tol=1e-6;
802 static real bond_margin = 0.01;
803 static real angle_margin = 0.01;
804 /* static real pep_margin = 0.005; */
805 static real pep_margin = 0.01;
806 /* static real ring_margin = 0.002; */
807 static real ring_margin = 0.01;
808 /* static real arg_margin = 0.002; */
809 static real arg_margin = 0.01;
810 /* Use end_margin for asn and gln */
811 /* static real end_margin = 0.004; */
812 static real end_margin = 0.01;
813 static real val_margin = 0.01;
814 static real leu_margin = 0.01;
815 static real ile_margin = 0.03;
816 static real dih_margin = 0.01;
817 static real idih_margin = 0.01;
818 static real nb_margin = 0.05;
819 static real hb_margin = 0.02;
820 static real hblen = 2.3;
821 static real rcut = 0.0;
822 static real maxdist = 0.0;
823 static bool bNB=TRUE,bBON=TRUE,bAddR=FALSE;
824 static bool bVir=FALSE,bEnghHuber=TRUE;
825 static char *smth_str[] = { NULL, "none", "tri", "tetra", NULL };
826 t_pargs pa[] = {
827 { "-engh",FALSE,etBOOL, {&bEnghHuber},
828 "Use the Engh&Huber parameters for bond-lengths etc." },
829 { "-tol", FALSE, etREAL, {&tol},
830 "HIDDENTolerance for smoothing" },
831 { "-bm", FALSE, etREAL, {&bond_margin},
832 "Relative margin for bond lengths" },
833 { "-am", FALSE, etREAL, {&angle_margin},
834 "Relative margin for bond angle lengths" },
835 { "-pm", FALSE, etREAL, {&pep_margin},
836 "Relative margin for peptidebond dihedrals" },
837 { "-rr", FALSE, etREAL, {&ring_margin},
838 "Relative margin to keep rings flat (trp,tyr,phe,hisb)" },
839 { "-ar", FALSE, etREAL, {&arg_margin},
840 "Relative margin for arginine" },
841 { "-er", FALSE, etREAL, {&end_margin},
842 "Relative margin for asn and gln" },
843 { "-vm", FALSE, etREAL, {&val_margin},
844 "Relative margin for valine (0 disables)" },
845 { "-lm", FALSE, etREAL, {&leu_margin},
846 "Relative margin for leucine (0 disables)" },
847 { "-il", FALSE, etREAL, {&ile_margin},
848 "Relative margin for isoleucine (0 disables)" },
849 { "-dm", FALSE, etREAL, {&dih_margin},
850 "!inactive! Relative margin for dihedral lengths" },
851 { "-im", FALSE, etREAL, {&idih_margin},
852 "Relative margin for improper dihedral lengths" },
853 { "-nm", FALSE, etREAL, {&nb_margin},
854 "Relative margin for nonbonded lower bounds" },
855 { "-hm", FALSE, etREAL, {&hb_margin},
856 "Relative margin for hydrogen bonded atoms, which must be specified in an index file, as generated by g_hbond" },
857 { "-hb", FALSE, etREAL, {&hblen},
858 "Shortest possible distance for a hydrogen bond (in Angstrom!)" },
859 { "-bon", FALSE, etBOOL, {&bBON},
860 "Make bonded distance constraints" },
861 { "-nb", FALSE, etBOOL, {&bNB},
862 "Make nonbonded distance constraints (lower bound only) " },
863 { "-measure", FALSE, etREAL, {&rcut},
864 "Add (nonbonded) distances by examining all atoms within the distance given (in Angstrom), and using the margin given by the -nm option." },
865 { "-maxdist", FALSE, etREAL, {&maxdist},
866 "Maximum distance between any pair of atoms" },
867 { "-add",FALSE, etBOOL, {&bAddR},
868 "Write restraints in format of additional restraints for disco" },
869 { "-vir",FALSE, etBOOL, {&bVir},
870 "Use virtual particles"},
871 { "-sm", FALSE, etENUM, {smth_str},
872 "Smoothing: none, tri (Using triangle inequality), or tetra (Partial tetrangle inequaliy)" }
875 CopyRight(stderr,argv[0]);
876 parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
877 asize(desc),desc,0,NULL);
879 #ifndef DOUBLE
880 fprintf(stderr,"WARNING: running %s in single precision may produce bad"
881 " distances\n",argv[0]);
882 #endif
884 fp=ffopen(ftp2fn(efLOG,NFILE,fnm),"w");
886 if ((!bBON && !bNB) && (rcut==0.0))
887 fprintf(stderr,"That was interesting... (nothing done)\n");
888 else {
889 snew(top,1);
890 topfn = ftp2fn(efTPS,NFILE,fnm);
891 if (!read_tps_conf(topfn,title,top,&x,NULL,box,FALSE))
892 fatal_error(0,"No topology in %s",topfn);
893 fprintf(stderr,"Successfully read %s (%s)\n",topfn,title);
895 if (!opt2parg_bSet("-maxdist",asize(pa),pa))
896 maxdist = (top->atoms.nres+3)*3.5; /* Ca-Ca distance + some buffer */
898 if (opt2bSet("-q",NFILE,fnm)) {
899 weight = read_weights(opt2fn("-q",NFILE,fnm),top->atoms.nr);
901 else {
902 snew(weight,top->atoms.nr);
903 for(i=0; (i<top->atoms.nr); i++)
904 weight[i] = 1.0;
906 if (opt2bSet("-d",NFILE,fnm)) {
907 dist = read_dist(fp,opt2fn("-d",NFILE,fnm),top->atoms.nr,weight);
909 else
910 dist = new_dist(top->atoms.nr);
912 if (bEnghHuber)
913 read_O_dist();
915 if (bBON) {
916 simple_bonds_and_angles(fp,dist,&top->idef,&top->atoms,weight,
917 bond_margin,angle_margin);
918 peptide_bonds(fp,dist,&top->idef,&top->atoms,weight,pep_margin,
919 top->idef.il,top->idef.iparams,bVir);
920 arg(fp,dist,&top->idef,&top->atoms,weight,arg_margin,
921 top->idef.il,top->idef.iparams,bVir);
922 asn(fp,dist,&top->idef,&top->atoms,weight,end_margin,
923 top->idef.il,top->idef.iparams,bVir);
924 gln(fp,dist,&top->idef,&top->atoms,weight,end_margin,
925 top->idef.il,top->idef.iparams,bVir);
926 phe(fp,dist,&top->idef,&top->atoms,weight,ring_margin,
927 top->idef.il,top->idef.iparams,bVir);
928 tyr(fp,dist,&top->idef,&top->atoms,weight,ring_margin,
929 top->idef.il,top->idef.iparams,bVir);
930 trp(fp,dist,&top->idef,&top->atoms,weight,ring_margin,
931 top->idef.il,top->idef.iparams,bVir);
932 hisb(fp,dist,&top->idef,&top->atoms,weight,ring_margin,
933 top->idef.il,top->idef.iparams,bVir);
934 if ( val_margin != 0 ) {
935 val(fp,dist,&top->idef,&top->atoms,weight,val_margin,
936 top->idef.il,top->idef.iparams);
938 if ( leu_margin != 0 ) {
939 leu(fp,dist,&top->idef,&top->atoms,weight,leu_margin,
940 top->idef.il,top->idef.iparams);
942 if ( ile_margin != 0 ) {
943 ile(fp,dist,&top->idef,&top->atoms,weight,ile_margin,
944 top->idef.il,top->idef.iparams);
946 fflush(fp);
947 fprintf(stderr,"Done residues...\n");
948 dump_bonds(&top->atoms,dist,
949 top->idef.il,top->idef.functype,top->idef.iparams,
950 bond_margin,angle_margin,dih_margin,
951 idih_margin,weight,bAddR);
953 fprintf(stderr,"Done bondeds\n");
955 if (rcut > 0) {
956 nhb = 0;
957 hb = NULL;
958 grpname = NULL;
959 if (ftp2bSet(efNDX,NFILE,fnm)) {
960 rd_index(ftp2fn(efNDX,NFILE,fnm),1,&nhb,&hb,&grpname);
961 fprintf(stderr,"There are %d hydrogen bonds\n",nhb/3);
963 measure_dist(fp,dist,&top->atoms,x,rcut,nb_margin,hb_margin,nhb,hb);
965 if (opt2bSet("-dom",NFILE,fnm)) {
966 release_domains(fp,opt2fn("-dom",NFILE,fnm),dist,&top->atoms,maxdist);
968 if (bNB)
969 dump_nonbonds(dist,&top->idef,&top->atoms,hblen,weight,
970 nb_margin,bAddR,maxdist);
972 if (strcmp(smth_str[0],smth_str[1]) == 0)
973 fprintf(stderr,"No smoothing\n");
974 else if (strcmp(smth_str[0],smth_str[2]) == 0) {
975 fprintf(stderr,"Triangle smoothing only\n");
976 (void) do_triangle (dist,&top->atoms,tol);
978 else if (strcmp(smth_str[0],smth_str[3]) == 0) {
979 fprintf(stderr,"Partial tetrangle + triangle smoothing\n");
980 do_smooth(dist,&top->atoms,tol);
982 else
983 fatal_error(0,"Uh-oh, smth_str = %s, %s, line %d",
984 smth_str[0],__FILE__,__LINE__);
986 dump_dist(opt2fn("-o",NFILE,fnm),dist,top->atoms.nr,bAddR);
989 ffclose(fp);
991 thanx(stderr);
993 return 0;