2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
51 #include "gmx_fatal.h"
55 #include "gmx_statistics.h"
60 static void make_dist_leg(FILE *fp,int gnx,atom_id index[],t_atoms *atoms,
61 const output_env_t oenv)
67 for(i=0; i<gnx; i+=2) {
69 sprintf(leg[i/2],"%s %s%d - %s %s%d",
70 *(atoms->atomname[index[i]]),
71 *(atoms->resinfo[atoms->atom[index[i]].resind].name),
72 atoms->resinfo[atoms->atom[index[i]].resind].nr,
73 *(atoms->atomname[index[i+1]]),
74 *(atoms->resinfo[atoms->atom[index[i+1]].resind].name),
75 atoms->resinfo[atoms->atom[index[i+1]].resind].nr);
77 xvgr_legend(fp,gnx/2,(const char**)leg,oenv);
78 for(i=0; i<gnx/2; i++)
83 static void do_bonds(FILE *log,const char *fn,const char *fbond,
84 const char *fdist, int gnx,atom_id index[],
85 real blen,real tol,gmx_bool bAver,
86 t_topology *top,int ePBC,gmx_bool bAverDist,
87 const output_env_t oenv)
94 gmx_stats_t b_one=NULL,*b_all=NULL;
95 /*real mean, mean2, sqrdev2, sigma2;
103 int bind,i,nframes,i0,i1;
106 real aver,sigma,error;
110 for(i=0; (i<gnx/2); i++)
111 b_all[i] = gmx_stats_init();
114 b_one = gmx_stats_init();
118 natoms=read_first_x(oenv,&status,fn,&t,&x,box);
120 gmx_fatal(FARGS,"No atoms in trajectory!");
123 outd = xvgropen(fdist,bAverDist ? "Average distance" : "Distances",
124 "Time (ps)","Distance (nm)",oenv);
126 make_dist_leg(outd,gnx,index,&(top->atoms),oenv);
131 set_pbc(&pbc,ePBC,box);
133 fprintf(outd," %8.4f",t);
134 nframes++; /* count frames */
136 for(i=0; (i<gnx); i+=2) {
137 pbc_dx(&pbc,x[index[i]],x[index[i+1]],dx);
142 fprintf(outd," %.3f",bond);
144 gmx_stats_add_point(b_one,t,bond,0,0);
154 db = (2.0*(b1-b0))/MAXTAB;
157 bind = (int)((bond-b0)/db+0.5);
158 if ((bind >= 0) && (bind <= MAXTAB))
162 printf("bond: %4d-%4d bond=%10.5e, dx=(%10.5e,%10.5e,%10.5e)\n",
163 index[i],index[i+1],bond,dx[XX],dx[YY],dx[ZZ]);
168 gmx_stats_add_point(b_all[i/2],t,bond,0,0);
172 fprintf(outd," %.5f",bav*2.0/gnx);
175 } while (read_next_x(oenv,status,&t,natoms,x,box));
182 mean = mean / counter;
183 mean2 = mean2 / counter;
184 sqrdev2 = (mean2 - mean*mean);
185 sigma2 = sqrdev2*counter / (counter - 1);
187 /* For definitions see "Weet wat je meet" */
190 gmx_stats_get_npoints(b_one,&N);
191 printf("Total number of samples : %d\n",N);
192 gmx_stats_get_ase(b_one,&aver,&sigma,&error);
193 printf("Mean : %g\n",aver);
194 printf("Standard deviation of the distribution: %g\n",sigma);
195 printf("Standard deviation of the mean : %g\n",error);
196 gmx_stats_done(b_one);
199 out=xvgropen(fbond,"Bond Stretching Distribution",
200 "Bond Length (nm)","",oenv);
202 for(i0=0; ((i0 < MAXTAB) && (btab[i0]==0)); i0++)
205 for(i1=MAXTAB; ((i1 > 0) && (btab[i1]==0)); i1--)
210 gmx_fatal(FARGS,"No distribution... (i0 = %d, i1 = %d)? ? ! ! ? !",i0,i1);
212 fac=2.0/(nframes*gnx*db);
213 for(i=i0; (i<=i1); i++)
214 fprintf(out,"%8.5f %8.5f\n",b0+i*db,btab[i]*fac);
218 fprintf(log,"%5s %5s %8s %8s\n","i","j","b_aver","sigma");
219 for(i=0; (i<gnx/2); i++) {
220 gmx_stats_get_ase(b_all[i],&aver,&sigma,NULL);
221 fprintf(log,"%5u %5u %8.5f %8.5f\n",1+index[2*i],1+index[2*i+1],
223 gmx_stats_done(b_all[i]);
230 int gmx_bond(int argc,char *argv[])
232 const char *desc[] = {
233 "[TT]g_bond[tt] makes a distribution of bond lengths. If all is well a",
234 "Gaussian distribution should be made when using a harmonic potential.",
235 "Bonds are read from a single group in the index file in order i1-j1",
236 "i2-j2 through in-jn.[PAR]",
237 "[TT]-tol[tt] gives the half-width of the distribution as a fraction",
238 "of the bondlength ([TT]-blen[tt]). That means, for a bond of 0.2",
239 "a tol of 0.1 gives a distribution from 0.18 to 0.22.[PAR]",
240 "Option [TT]-d[tt] plots all the distances as a function of time.",
241 "This requires a structure file for the atom and residue names in",
242 "the output. If however the option [TT]-averdist[tt] is given (as well",
243 "or separately) the average bond length is plotted instead."
245 const char *bugs[] = {
246 "It should be possible to get bond information from the topology."
248 static real blen=-1.0,tol=0.1;
249 static gmx_bool bAver=TRUE,bAverDist=TRUE;
251 { "-blen", FALSE, etREAL, {&blen},
252 "Bond length. By default length of first bond" },
253 { "-tol", FALSE, etREAL, {&tol},
254 "Half width of distribution as fraction of [TT]-blen[tt]" },
255 { "-aver", FALSE, etBOOL, {&bAver},
256 "Average bond length distributions" },
257 { "-averdist", FALSE, etBOOL, {&bAverDist},
258 "Average distances (turns on [TT]-d[tt])" }
273 { efTRX, "-f", NULL, ffREAD },
274 { efNDX, NULL, NULL, ffREAD },
275 { efTPS, NULL, NULL, ffOPTRD },
276 { efXVG, "-o", "bonds", ffWRITE },
277 { efLOG, NULL, "bonds", ffOPTWR },
278 { efXVG, "-d", "distance", ffOPTWR }
280 #define NFILE asize(fnm)
282 CopyRight(stderr,argv[0]);
283 parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE ,
284 NFILE,fnm,asize(pa),pa,asize(desc),desc,asize(bugs),bugs,
288 fdist = opt2fn("-d",NFILE,fnm);
290 fdist = opt2fn_null("-d",NFILE,fnm);
292 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,
296 rd_index(ftp2fn(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);
298 fprintf(stderr,"WARNING: odd number of atoms (%d) in group!\n",gnx);
299 fprintf(stderr,"Will gather information on %d bonds\n",gnx/2);
302 fp = ftp2FILE(efLOG,NFILE,fnm,"w");
306 do_bonds(fp,ftp2fn(efTRX,NFILE,fnm),opt2fn("-o",NFILE,fnm),fdist,gnx,index,
307 blen,tol,bAver,&top,ePBC,bAverDist,oenv);
309 do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy");
310 do_view(oenv,opt2fn_null("-d",NFILE,fnm),"-nxy");