4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_g_analyze_c
= "$Id$";
47 real
**read_val(char *fn
,bool bHaveT
,int nsets_in
,
48 int *nset
,int *nval
,real
*t0
,real
*dt
)
51 char line0
[4096],*line
,*format
;
52 int a
,narg
,n
,sin
,set
,nchar
;
59 for(sin
=0; sin
<nsets_in
; sin
++) {
63 narg
= bHaveT
? 2 : 1;
66 while (!bEndOfSet
&& fgets(line0
,STRLEN
-1,fp
)) {
68 bEndOfSet
= (line
[0] == '&');
69 if ((line
[0] != '#') && (line
[0] != '@') && !bEndOfSet
) {
71 while (((a
<narg
) || ((nsets_in
==1) && (n
==0))) &&
72 (line
[0] != '\n') && sscanf(line
,"%lf%n",&dbl
,&nchar
)) {
99 srenew(val
[set
],n
+100);
100 val
[set
][n
] = (real
)dbl
;
107 fprintf(stderr
,"Invalid line in %s: '%s'\n",fn
,line0
);
115 *dt
= (real
)(tend
-*t0
)/(n
-1.0);
118 fprintf(stderr
,"Set %d is shorter (%d) than the previous set (%d)\n",
121 fprintf(stderr
,"Will use only the first %d points of every set\n",
131 void histogram(char *distfile
,real binwidth
,int n
, int nset
, real
**val
)
141 for(s
=0; s
<nset
; s
++)
145 else if (val
[s
][i
] > max
)
150 nbin
= (int)(max
/binwidth
)+1;
151 fprintf(stderr
,"Making distributions with %d bins\n",2*nbin
+1);
152 snew(histo
,2*nbin
+1);
153 fp
= xvgropen(distfile
,"Distribution","","");
154 for(s
=0; s
<nset
; s
++) {
155 for(i
=0; i
<2*nbin
+1; i
++)
158 histo
[nbin
+(int)(floor(val
[s
][i
]/binwidth
+0.5))]++;
159 for(i
=0; i
<2*nbin
+1; i
++)
160 fprintf(fp
," %g %g\n",(i
-nbin
)*binwidth
,(real
)histo
[i
]/(n
*binwidth
));
167 void average(char *avfile
,char **avbar_opt
,
168 int n
, int nset
,real
**val
,real t0
,real dt
)
177 fp
= ffopen(avfile
,"w");
178 if ((c
== 'e') && (nset
== 1))
181 fprintf(fp
,"@TYPE xydy\n");
186 for(s
=0; s
<nset
; s
++)
189 fprintf(fp
," %g %g",t0
+dt
*i
,av
);
192 for(s
=0; s
<nset
; s
++)
193 var
+= sqr(val
[s
][i
]-av
);
195 err
= sqrt(var
/nset
);
197 err
= sqrt(var
/(nset
*(nset
-1)));
198 fprintf(fp
," %g",err
);
205 void estimate_error(char *eefile
,int resol
,int n
,int nset
,
206 real
*av
,real
**val
,real dt
)
209 int log2max
,rlog2
,bs
,prev_bs
,nb
;
214 log2max
= (int)(log(n
)/log(2));
217 for(s
=0; s
<nset
; s
++) {
219 sprintf(leg
[s
],"av %f",av
[s
]);
222 fp
= xvgropen(eefile
,"Error estimates","Block size (time)","Error estimate");
224 "@ subtitle \"using block averaging, total time %g (%d points)\"\n",
226 xvgr_legend(fp
,nset
,leg
);
227 for(s
=0; s
<nset
; s
++)
231 for(s
=0; s
<nset
; s
++) {
233 for(rlog2
=resol
*log2max
; rlog2
>=2*resol
; rlog2
--) {
234 bs
= n
*pow(0.5,(real
)rlog2
/(real
)resol
);
241 for (j
=0; j
<bs
; j
++) {
245 var
+= sqr(av
[s
] - blav
/bs
);
248 fprintf(fp
," %g %g\n",bs
*dt
,sqrt(var
/(nb
*(nb
-1))));
259 int main(int argc
,char *argv
[])
261 static char *desc
[] = {
262 "g_analyze reads an ascii file and analyzes data sets.",
263 "A line in the input file may start with a time",
264 "(see option [TT]-time[tt]) and any number of y values may follow.",
265 "Multiple sets can also be",
266 "read when they are seperated by & (option [TT]-n[tt]),",
267 "in this case only one y value is read from each line.",
268 "All lines starting with # and @ are skipped.",
269 "All analyses can also be done for the derivative of a set",
270 "(option [TT]-d[tt]).[PAR]",
271 "Option [TT]-ac[tt] produces the autocorrelation function(s).[PAR]",
272 "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]",
273 "Option [TT]-dist[tt] produces distribution plot(s).[PAR]",
274 "Option [TT]-av[tt] produces the average over the sets,",
275 "optionally with error bars ([TT]-errbar[tt]).[PAR]",
276 "Option [TT]-ee[tt] produces error estimates using block averaging.",
277 "A set is divided in a number of blocks and averages are calculated for",
278 "each block. The error for the total average is calculated from the",
279 "variance between the block averages. These errors are plotted as a",
280 "function of the block size. For a good error estimate the block size",
281 "should be at least as large as the correlation time, but possibly much",
284 static real frac
=0.5,binwidth
=0.1;
285 static bool bHaveT
=TRUE
,bDer
=FALSE
,bSubAv
=FALSE
,bAverCorr
=FALSE
;
286 static int nsets_in
=1,d
=1,resol
=8;
288 static char *avbar_opt
[] = { NULL
, "none", "stddev", "error", NULL
};
291 { "-time", FALSE
, etBOOL
, {&bHaveT
},
292 "Expect a time in the input" },
293 { "-n", FALSE
, etINT
, {&nsets_in
},
294 "Read # sets seperated by &" },
295 { "-d", FALSE
, etBOOL
, {&bDer
},
296 "Use the derivative" },
297 { "-dp", FALSE
, etINT
, {&d
},
298 "HIDDENThe derivative is the difference over # points" },
299 { "-bw", FALSE
, etREAL
, {&binwidth
},
300 "Binwidth for the distribution" },
301 { "-errbar", FALSE
, etENUM
, {&avbar_opt
},
302 "Error bars for the average" },
303 { "-resol", FALSE
, etINT
, {&resol
},
304 "HIDDENResolution for the block averaging, block size increases with"
305 " a factor 2^(1/#)" },
306 { "-subav", FALSE
, etBOOL
, {&bSubAv
},
307 "Subtract the average before autocorrelating" },
308 { "-oneacf", FALSE
, etBOOL
, {&bAverCorr
},
309 "Calculate one ACF over all sets" }
311 #define NPA asize(pa)
314 int n
,nlast
,s
,nset
,i
,t
;
315 real
**val
,t0
,dt
,tot
,*av
;
316 char *acfile
,*msdfile
,*distfile
,*avfile
,*eefile
;
319 { efXVG
, "-f", "graph", ffREAD
},
320 { efXVG
, "-ac", "autocorr", ffOPTWR
},
321 { efXVG
, "-msd", "msd", ffOPTWR
},
322 { efXVG
, "-dist", "distr", ffOPTWR
},
323 { efXVG
, "-av", "average", ffOPTWR
},
324 { efXVG
, "-ee", "errest", ffOPTWR
}
326 #define NFILE asize(fnm)
332 ppa
= add_acf_pargs(&npargs
,pa
);
334 CopyRight(stderr
,argv
[0]);
335 parse_common_args(&argc
,argv
,0,TRUE
,
336 NFILE
,fnm
,npargs
,ppa
,asize(desc
),desc
,0,NULL
);
338 acfile
= opt2fn_null("-ac",NFILE
,fnm
);
339 msdfile
= opt2fn_null("-msd",NFILE
,fnm
);
340 distfile
= opt2fn_null("-dist",NFILE
,fnm
);
341 avfile
= opt2fn_null("-av",NFILE
,fnm
);
342 eefile
= opt2fn_null("-ee",NFILE
,fnm
);
343 if (!acfile
&& !msdfile
&& !distfile
&& !avfile
&& !eefile
) {
344 fprintf(stderr
,"Please use one of the output file options\n");
348 val
=read_val(opt2fn("-f",NFILE
,fnm
),bHaveT
,nsets_in
,&nset
,&n
,&t0
,&dt
);
349 fprintf(stderr
,"Read %d sets of %d points, dt = %g\n",nset
,n
,dt
);
351 fprintf(stderr
,"Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n",
354 for(s
=0; s
<nset
; s
++)
356 val
[s
][i
] = (val
[s
][i
+d
]-val
[s
][i
])/(d
*dt
);
360 for(s
=0; s
<nset
; s
++) {
364 fprintf(stderr
,"Average of set %d: %g\n",s
+1,av
[s
]);
368 out
=xvgropen(msdfile
,"Mean square displacement",
369 "time (ps)","MSD (nm\\S2\\N)");
370 nlast
= (int)(n
*frac
);
371 for(s
=0; s
<nset
; s
++) {
372 for(t
=0; t
<=nlast
; t
++) {
374 fprintf(stderr
,"\r%d",t
);
377 tot
+= sqr(val
[s
][i
]-val
[s
][i
+t
]);
379 fprintf(out
," %g %8g\n",dt
*t
,tot
);
385 fprintf(stderr
,"\r%d, time=%g\n",t
-1,(t
-1)*dt
);
389 histogram(distfile
,binwidth
,n
,nset
,val
);
392 average(avfile
,avbar_opt
,n
,nset
,val
,t0
,dt
);
395 estimate_error(eefile
,resol
,n
,nset
,av
,val
,dt
);
399 for(s
=0; s
<nset
; s
++)
402 do_autocorr(acfile
,"Autocorrelation",n
,nset
,val
,dt
,
403 eacNormal
,bAverCorr
);