3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
52 #include "gmx_fatal.h"
58 #include "eigensolver.h"
62 static real
find_pdb_bfac(t_atoms
*atoms
,t_resinfo
*ri
,char *atomnm
)
67 strcpy(rresnm
,*ri
->name
);
69 for(i
=0; (i
<atoms
->nr
); i
++) {
70 if ((ri
->nr
== atoms
->resinfo
[atoms
->atom
[i
].resind
].nr
) &&
71 (ri
->ic
== atoms
->resinfo
[atoms
->atom
[i
].resind
].ic
) &&
72 (strcmp(*atoms
->resinfo
[atoms
->atom
[i
].resind
].name
,rresnm
) == 0) &&
73 (strstr(*atoms
->atomname
[i
],atomnm
) != NULL
))
77 fprintf(stderr
,"\rCan not find %s%d-%s in pdbfile\n",
78 rresnm
,ri
->nr
,atomnm
);
82 return atoms
->pdbinfo
[i
].bfac
;
85 void correlate_aniso(const char *fn
,t_atoms
*ref
,t_atoms
*calc
,
86 const output_env_t oenv
)
91 fp
= xvgropen(fn
,"Correlation between X-Ray and Computed Uij","X-Ray",
93 for(i
=0; (i
<ref
->nr
); i
++) {
94 if (ref
->pdbinfo
[i
].bAnisotropic
) {
95 for(j
=U11
; (j
<=U23
); j
++)
96 fprintf(fp
,"%10d %10d\n",ref
->pdbinfo
[i
].uij
[j
],calc
->pdbinfo
[i
].uij
[j
]);
102 static void average_residues(double f
[],double **U
,int uind
,
103 int isize
,atom_id index
[],real w_rls
[],
112 for(i
=0; i
<isize
; i
++) {
113 av
+= w_rls
[index
[i
]]*(f
!= NULL
? f
[i
] : U
[i
][uind
]);
114 m
+= w_rls
[index
[i
]];
116 atoms
->atom
[index
[i
]].resind
!=atoms
->atom
[index
[i
+1]].resind
) {
119 for(j
=start
; j
<=i
; j
++)
122 for(j
=start
; j
<=i
; j
++)
132 void print_dir(FILE *fp
,real
*Uaver
)
134 real eigvec
[DIM
*DIM
];
139 fprintf(fp
,"MSF X Y Z\n");
142 fprintf(fp
," %c ",'X'+d
-XX
);
144 fprintf(fp
," %9.2e",Uaver
[3*m
+d
]);
145 fprintf(fp
,"%s\n",m
==DIM
? " (nm^2)" : "");
148 for(m
=0; m
<DIM
*DIM
; m
++)
152 eigensolver(tmp
,DIM
,0,DIM
,eigval
,eigvec
);
154 fprintf(fp
,"\n Eigenvectors\n\n");
155 fprintf(fp
,"Eigv %-8.2e %-8.2e %-8.2e (nm^2)\n\n",
156 eigval
[2],eigval
[1],eigval
[0]);
159 fprintf(fp
," %c ",'X'+d
-XX
);
160 for(m
=DIM
-1; m
>=0; m
--)
161 fprintf(fp
,"%7.4f ",eigvec
[3*m
+d
]);
166 int gmx_rmsf(int argc
,char *argv
[])
168 const char *desc
[] = {
169 "g_rmsf computes the root mean square fluctuation (RMSF, i.e. standard ",
170 "deviation) of atomic positions ",
171 "after (optionally) fitting to a reference frame.[PAR]",
172 "With option [TT]-oq[tt] the RMSF values are converted to B-factor",
173 "values, which are written to a pdb file with the coordinates, of the",
174 "structure file, or of a pdb file when [TT]-q[tt] is specified.",
175 "Option [TT]-ox[tt] writes the B-factors to a file with the average",
177 "With the option [TT]-od[tt] the root mean square deviation with",
178 "respect to the reference structure is calculated.[PAR]",
179 "With the option [TT]aniso[tt] g_rmsf will compute anisotropic",
180 "temperature factors and then it will also output average coordinates",
181 "and a pdb file with ANISOU records (corresonding to the [TT]-oq[tt]",
182 "or [TT]-ox[tt] option). Please note that the U values",
183 "are orientation dependent, so before comparison with experimental data",
184 "you should verify that you fit to the experimental coordinates.[PAR]",
185 "When a pdb input file is passed to the program and the [TT]-aniso[tt]",
187 "a correlation plot of the Uij will be created, if any anisotropic",
188 "temperature factors are present in the pdb file.[PAR]",
189 "With option [TT]-dir[tt] the average MSF (3x3) matrix is diagonalized.",
190 "This shows the directions in which the atoms fluctuate the most and",
193 static gmx_bool bRes
=FALSE
,bAniso
=FALSE
,bdevX
=FALSE
,bFit
=TRUE
;
195 { "-res", FALSE
, etBOOL
, {&bRes
},
196 "Calculate averages for each residue" },
197 { "-aniso",FALSE
, etBOOL
, {&bAniso
},
198 "Compute anisotropic termperature factors" },
199 { "-fit", FALSE
, etBOOL
, {&bFit
},
200 "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." }
203 int step
,nre
,natoms
,i
,g
,m
,teller
=0;
204 real t
,lambda
,*w_rls
,*w_rms
;
210 t_atoms
*pdbatoms
,*refatoms
;
221 FILE *fp
; /* the graphics file */
222 const char *devfn
,*dirfn
;
230 real bfac
,pdb_bfac
,*Uaver
;
234 double *rmsf
,invcount
,totmass
;
238 gmx_rmpbc_t gpbc
=NULL
;
242 const char *leg
[2] = { "MD", "X-Ray" };
245 { efTRX
, "-f", NULL
, ffREAD
},
246 { efTPS
, NULL
, NULL
, ffREAD
},
247 { efNDX
, NULL
, NULL
, ffOPTRD
},
248 { efPDB
, "-q", NULL
, ffOPTRD
},
249 { efPDB
, "-oq", "bfac", ffOPTWR
},
250 { efPDB
, "-ox", "xaver", ffOPTWR
},
251 { efXVG
, "-o", "rmsf", ffWRITE
},
252 { efXVG
, "-od", "rmsdev", ffOPTWR
},
253 { efXVG
, "-oc", "correl", ffOPTWR
},
254 { efLOG
, "-dir", "rmsf", ffOPTWR
}
256 #define NFILE asize(fnm)
258 CopyRight(stderr
,argv
[0]);
259 parse_common_args(&argc
,argv
,PCA_CAN_TIME
| PCA_CAN_VIEW
| PCA_BE_NICE
,
260 NFILE
,fnm
,asize(pargs
),pargs
,asize(desc
),desc
,0,NULL
,
263 bReadPDB
= ftp2bSet(efPDB
,NFILE
,fnm
);
264 devfn
= opt2fn_null("-od",NFILE
,fnm
);
265 dirfn
= opt2fn_null("-dir",NFILE
,fnm
);
267 read_tps_conf(ftp2fn(efTPS
,NFILE
,fnm
),title
,&top
,&ePBC
,&xref
,NULL
,box
,TRUE
);
268 snew(w_rls
,top
.atoms
.nr
);
270 fprintf(stderr
,"Select group(s) for root mean square calculation\n");
271 get_index(&top
.atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),1,&isize
,&index
,&grpnames
);
274 for(i
=0; i
<isize
; i
++)
275 w_rls
[index
[i
]]=top
.atoms
.atom
[index
[i
]].m
;
277 /* Malloc the rmsf arrays */
280 for(i
=0; i
<isize
; i
++)
287 get_stx_coordnum(opt2fn("-q",NFILE
,fnm
),&npdbatoms
);
290 init_t_atoms(pdbatoms
,npdbatoms
,TRUE
);
291 init_t_atoms(refatoms
,npdbatoms
,TRUE
);
292 snew(pdbx
,npdbatoms
);
293 /* Read coordinates twice */
294 read_stx_conf(opt2fn("-q",NFILE
,fnm
),title
,pdbatoms
,pdbx
,NULL
,NULL
,pdbbox
);
295 read_stx_conf(opt2fn("-q",NFILE
,fnm
),title
,refatoms
,pdbx
,NULL
,NULL
,pdbbox
);
297 pdbatoms
= &top
.atoms
;
298 refatoms
= &top
.atoms
;
300 npdbatoms
= pdbatoms
->nr
;
301 snew(pdbatoms
->pdbinfo
,npdbatoms
);
302 copy_mat(box
,pdbbox
);
306 sub_xcm(xref
,isize
,index
,top
.atoms
.atom
,xcm
,FALSE
);
309 natom
= read_first_x(oenv
,&status
,ftp2fn(efTRX
,NFILE
,fnm
),&t
,&x
,box
);
312 gpbc
= gmx_rmpbc_init(&top
.idef
,ePBC
,natom
,box
);
315 /* Now read the trj again to compute fluctuations */
319 /* Remove periodic boundary */
320 gmx_rmpbc(gpbc
,natom
,box
,x
);
322 /* Set center of mass to zero */
323 sub_xcm(x
,isize
,index
,top
.atoms
.atom
,xcm
,FALSE
);
325 /* Fit to reference structure */
326 do_fit(natom
,w_rls
,xref
,x
);
329 /* Calculate Anisotropic U Tensor */
330 for(i
=0; i
<isize
; i
++) {
332 for(d
=0; d
<DIM
; d
++) {
333 xav
[i
*DIM
+ d
] += x
[aid
][d
];
335 U
[i
][d
*DIM
+ m
] += x
[aid
][d
]*x
[aid
][m
];
340 /* Calculate RMS Deviation */
341 for(i
=0;(i
<isize
);i
++) {
343 for(d
=0;(d
<DIM
);d
++) {
344 rmsd_x
[i
][d
] += sqr(x
[aid
][d
]-xref
[aid
][d
]);
350 } while(read_next_x(oenv
,status
,&t
,natom
,x
,box
));
354 gmx_rmpbc_done(gpbc
);
357 invcount
= 1.0/count
;
360 for(i
=0; i
<isize
; i
++) {
362 xav
[i
*DIM
+ d
] *= invcount
;
364 for(m
=0; m
<DIM
; m
++) {
365 U
[i
][d
*DIM
+ m
] = U
[i
][d
*DIM
+ m
]*invcount
366 - xav
[i
*DIM
+ d
]*xav
[i
*DIM
+ m
];
367 Uaver
[3*d
+m
] += top
.atoms
.atom
[index
[i
]].m
*U
[i
][d
*DIM
+ m
];
369 totmass
+= top
.atoms
.atom
[index
[i
]].m
;
371 for(d
=0; d
<DIM
*DIM
; d
++)
375 for(d
=0; d
<DIM
*DIM
; d
++) {
376 average_residues(NULL
,U
,d
,isize
,index
,w_rls
,&top
.atoms
);
381 for(i
=0; i
<isize
; i
++) {
383 pdbatoms
->pdbinfo
[aid
].bAnisotropic
= TRUE
;
384 pdbatoms
->pdbinfo
[aid
].uij
[U11
] = 1e6
*U
[i
][XX
*DIM
+ XX
];
385 pdbatoms
->pdbinfo
[aid
].uij
[U22
] = 1e6
*U
[i
][YY
*DIM
+ YY
];
386 pdbatoms
->pdbinfo
[aid
].uij
[U33
] = 1e6
*U
[i
][ZZ
*DIM
+ ZZ
];
387 pdbatoms
->pdbinfo
[aid
].uij
[U12
] = 1e6
*U
[i
][XX
*DIM
+ YY
];
388 pdbatoms
->pdbinfo
[aid
].uij
[U13
] = 1e6
*U
[i
][XX
*DIM
+ ZZ
];
389 pdbatoms
->pdbinfo
[aid
].uij
[U23
] = 1e6
*U
[i
][YY
*DIM
+ ZZ
];
397 for(i
=0; i
<isize
; i
++)
398 rmsf
[i
] = U
[i
][XX
*DIM
+ XX
] + U
[i
][YY
*DIM
+ YY
] + U
[i
][ZZ
*DIM
+ ZZ
];
401 fprintf(stdout
,"\n");
402 print_dir(stdout
,Uaver
);
403 fp
= ffopen(dirfn
,"w");
408 for(i
=0; i
<isize
; i
++)
412 /* Write RMSF output */
414 bfac
= 8.0*M_PI
*M_PI
/3.0*100;
415 fp
= xvgropen(ftp2fn(efXVG
,NFILE
,fnm
),"B-Factors",
416 label
,"(A\\b\\S\\So\\N\\S2\\N)",oenv
);
417 xvgr_legend(fp
,2,leg
,oenv
);
418 for(i
=0;(i
<isize
);i
++) {
419 if (!bRes
|| i
+1==isize
||
420 top
.atoms
.atom
[index
[i
]].resind
!=top
.atoms
.atom
[index
[i
+1]].resind
) {
421 resind
= top
.atoms
.atom
[index
[i
]].resind
;
422 pdb_bfac
= find_pdb_bfac(pdbatoms
,&top
.atoms
.resinfo
[resind
],
423 *(top
.atoms
.atomname
[index
[i
]]));
425 fprintf(fp
,"%5d %10.5f %10.5f\n",
426 bRes
? top
.atoms
.resinfo
[top
.atoms
.atom
[index
[i
]].resind
].nr
: i
+1,rmsf
[i
]*bfac
,
432 fp
= xvgropen(ftp2fn(efXVG
,NFILE
,fnm
),"RMS fluctuation",label
,"(nm)",oenv
);
433 for(i
=0; i
<isize
; i
++)
434 if (!bRes
|| i
+1==isize
||
435 top
.atoms
.atom
[index
[i
]].resind
!=top
.atoms
.atom
[index
[i
+1]].resind
)
436 fprintf(fp
,"%5d %8.4f\n",
437 bRes
? top
.atoms
.resinfo
[top
.atoms
.atom
[index
[i
]].resind
].nr
: i
+1,sqrt(rmsf
[i
]));
441 for(i
=0; i
<isize
; i
++)
442 pdbatoms
->pdbinfo
[index
[i
]].bfac
= 800*M_PI
*M_PI
/3.0*rmsf
[i
];
445 for(i
=0; i
<isize
; i
++)
446 rmsf
[i
] = (rmsd_x
[i
][XX
]+rmsd_x
[i
][YY
]+rmsd_x
[i
][ZZ
])/count
;
448 average_residues(rmsf
,NULL
,0,isize
,index
,w_rls
,&top
.atoms
);
449 /* Write RMSD output */
450 fp
= xvgropen(devfn
,"RMS Deviation",label
,"(nm)",oenv
);
451 for(i
=0; i
<isize
; i
++)
452 if (!bRes
|| i
+1==isize
||
453 top
.atoms
.atom
[index
[i
]].resind
!=top
.atoms
.atom
[index
[i
+1]].resind
)
454 fprintf(fp
,"%5d %8.4f\n",
455 bRes
? top
.atoms
.resinfo
[top
.atoms
.atom
[index
[i
]].resind
].nr
: i
+1,sqrt(rmsf
[i
]));
459 if (opt2bSet("-oq",NFILE
,fnm
)) {
460 /* Write a pdb file with B-factors and optionally anisou records */
461 for(i
=0; i
<isize
; i
++)
462 rvec_inc(xref
[index
[i
]],xcm
);
463 write_sto_conf_indexed(opt2fn("-oq",NFILE
,fnm
),title
,pdbatoms
,pdbx
,
464 NULL
,ePBC
,pdbbox
,isize
,index
);
466 if (opt2bSet("-ox",NFILE
,fnm
)) {
467 /* Misuse xref as a temporary array */
468 for(i
=0; i
<isize
; i
++)
470 xref
[index
[i
]][d
] = xcm
[d
] + xav
[i
*DIM
+ d
];
471 /* Write a pdb file with B-factors and optionally anisou records */
472 write_sto_conf_indexed(opt2fn("-ox",NFILE
,fnm
),title
,pdbatoms
,xref
,NULL
,
473 ePBC
,pdbbox
,isize
,index
);
476 correlate_aniso(opt2fn("-oc",NFILE
,fnm
),refatoms
,pdbatoms
,oenv
);
477 do_view(oenv
,opt2fn("-oc",NFILE
,fnm
),"-nxy");
479 do_view(oenv
,opt2fn("-o",NFILE
,fnm
),"-nxy");
481 do_view(oenv
,opt2fn("-od",NFILE
,fnm
),"-nxy");