c38228272764f6d0e18daf39be9e4767c2fa1b8f
[alexxy/gromacs.git] / src / gromacs / gmxana / gmx_analyze.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include <cmath>
40 #include <cstdlib>
41 #include <cstring>
42
43 #include "gromacs/commandline/pargs.h"
44 #include "gromacs/correlationfunctions/autocorr.h"
45 #include "gromacs/correlationfunctions/expfit.h"
46 #include "gromacs/correlationfunctions/integrate.h"
47 #include "gromacs/fileio/xvgr.h"
48 #include "gromacs/gmxana/gmx_ana.h"
49 #include "gromacs/gmxana/gstat.h"
50 #include "gromacs/legacyheaders/copyrite.h"
51 #include "gromacs/legacyheaders/macros.h"
52 #include "gromacs/legacyheaders/readinp.h"
53 #include "gromacs/legacyheaders/txtdump.h"
54 #include "gromacs/legacyheaders/typedefs.h"
55 #include "gromacs/legacyheaders/viewit.h"
56 #include "gromacs/linearalgebra/matrix.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/statistics/statistics.h"
59 #include "gromacs/utility/fatalerror.h"
60 #include "gromacs/utility/futil.h"
61 #include "gromacs/utility/smalloc.h"
62 #include "gromacs/utility/snprintf.h"
63
64 /* must correspond to char *avbar_opt[] declared in main() */
65 enum {
66     avbarSEL, avbarNONE, avbarSTDDEV, avbarERROR, avbar90, avbarNR
67 };
68
69 static void power_fit(int n, int nset, real **val, real *t)
70 {
71     real *x, *y, quality, a, b, r;
72     int   s, i;
73
74     snew(x, n);
75     snew(y, n);
76
77     if (t[0] > 0)
78     {
79         for (i = 0; i < n; i++)
80         {
81             if (t[0] > 0)
82             {
83                 x[i] = std::log(t[i]);
84             }
85         }
86     }
87     else
88     {
89         fprintf(stdout, "First time is not larger than 0, using index number as time for power fit\n");
90         for (i = 0; i < n; i++)
91         {
92             x[i] = gmx_log1p(static_cast<real>(i));
93         }
94     }
95
96     for (s = 0; s < nset; s++)
97     {
98         for (i = 0; i < n && val[s][i] >= 0; i++)
99         {
100             y[i] = std::log(val[s][i]);
101         }
102         if (i < n)
103         {
104             fprintf(stdout, "Will power fit up to point %d, since it is not larger than 0\n", i);
105         }
106         lsq_y_ax_b(i, x, y, &a, &b, &r, &quality);
107         fprintf(stdout, "Power fit set %3d:  error %.3f  a %g  b %g\n",
108                 s+1, quality, a, std::exp(b));
109     }
110
111     sfree(y);
112     sfree(x);
113 }
114
115 static real cosine_content(int nhp, int n, real *y)
116 /* Assumes n equidistant points */
117 {
118     double fac, cosyint, yyint;
119     int    i;
120
121     if (n < 2)
122     {
123         return 0;
124     }
125
126     fac = M_PI*nhp/(n-1);
127
128     cosyint = 0;
129     yyint   = 0;
130     for (i = 0; i < n; i++)
131     {
132         cosyint += std::cos(fac*i)*y[i];
133         yyint   += y[i]*y[i];
134     }
135
136     return 2*cosyint*cosyint/(n*yyint);
137 }
138
139 static void plot_coscont(const char *ccfile, int n, int nset, real **val,
140                          const output_env_t oenv)
141 {
142     FILE *fp;
143     int   s;
144     real  cc;
145
146     fp = xvgropen(ccfile, "Cosine content", "set / half periods", "cosine content",
147                   oenv);
148
149     for (s = 0; s < nset; s++)
150     {
151         cc = cosine_content(s+1, n, val[s]);
152         fprintf(fp, " %d %g\n", s+1, cc);
153         fprintf(stdout, "Cosine content of set %d with %.1f periods: %g\n",
154                 s+1, 0.5*(s+1), cc);
155     }
156     fprintf(stdout, "\n");
157
158     xvgrclose(fp);
159 }
160
161 static void regression_analysis(int n, gmx_bool bXYdy,
162                                 real *x, int nset, real **val)
163 {
164     real S, chi2, a, b, da, db, r = 0;
165     int  ok;
166
167     if (bXYdy || (nset == 1))
168     {
169         printf("Fitting data to a function f(x) = ax + b\n");
170         printf("Minimizing residual chi2 = Sum_i w_i [f(x_i) - y_i]2\n");
171         printf("Error estimates will be given if w_i (sigma) values are given\n");
172         printf("(use option -xydy).\n\n");
173         if (bXYdy)
174         {
175             if ((ok = lsq_y_ax_b_error(n, x, val[0], val[1], &a, &b, &da, &db, &r, &S)) != estatsOK)
176             {
177                 gmx_fatal(FARGS, "Error fitting the data: %s",
178                           gmx_stats_message(ok));
179             }
180         }
181         else
182         {
183             if ((ok = lsq_y_ax_b(n, x, val[0], &a, &b, &r, &S)) != estatsOK)
184             {
185                 gmx_fatal(FARGS, "Error fitting the data: %s",
186                           gmx_stats_message(ok));
187             }
188         }
189         chi2 = sqr((n-2)*S);
190         printf("Chi2                    = %g\n", chi2);
191         printf("S (Sqrt(Chi2/(n-2))     = %g\n", S);
192         printf("Correlation coefficient = %.1f%%\n", 100*r);
193         printf("\n");
194         if (bXYdy)
195         {
196             printf("a    = %g +/- %g\n", a, da);
197             printf("b    = %g +/- %g\n", b, db);
198         }
199         else
200         {
201             printf("a    = %g\n", a);
202             printf("b    = %g\n", b);
203         }
204     }
205     else
206     {
207         double chi2, *a, **xx, *y;
208         int    i, j;
209
210         snew(y, n);
211         snew(xx, nset-1);
212         for (j = 0; (j < nset-1); j++)
213         {
214             snew(xx[j], n);
215         }
216         for (i = 0; (i < n); i++)
217         {
218             y[i] = val[0][i];
219             for (j = 1; (j < nset); j++)
220             {
221                 xx[j-1][i] = val[j][i];
222             }
223         }
224         snew(a, nset-1);
225         chi2 = multi_regression(NULL, n, y, nset-1, xx, a);
226         printf("Fitting %d data points in %d sets\n", n, nset-1);
227         printf("chi2 = %g\n", chi2);
228         printf("A =");
229         for (i = 0; (i < nset-1); i++)
230         {
231             printf("  %g", a[i]);
232             sfree(xx[i]);
233         }
234         printf("\n");
235         sfree(xx);
236         sfree(y);
237         sfree(a);
238     }
239 }
240
241 void histogram(const char *distfile, real binwidth, int n, int nset, real **val,
242                const output_env_t oenv)
243 {
244     FILE          *fp;
245     int            i, s;
246     double         minval, maxval;
247     int            nbin;
248     gmx_int64_t   *histo;
249
250     minval = val[0][0];
251     maxval = val[0][0];
252     for (s = 0; s < nset; s++)
253     {
254         for (i = 0; i < n; i++)
255         {
256             if (val[s][i] < minval)
257             {
258                 minval = val[s][i];
259             }
260             else if (val[s][i] > maxval)
261             {
262                 maxval = val[s][i];
263             }
264         }
265     }
266
267     minval = binwidth*std::floor(minval/binwidth);
268     maxval = binwidth*std::ceil(maxval/binwidth);
269     if (minval != 0)
270     {
271         minval -= binwidth;
272     }
273     maxval += binwidth;
274
275     nbin = static_cast<int>(((maxval - minval)/binwidth + 0.5) + 1);
276     fprintf(stderr, "Making distributions with %d bins\n", nbin);
277     snew(histo, nbin);
278     fp = xvgropen(distfile, "Distribution", "", "", oenv);
279     for (s = 0; s < nset; s++)
280     {
281         for (i = 0; i < nbin; i++)
282         {
283             histo[i] = 0;
284         }
285         for (i = 0; i < n; i++)
286         {
287             histo[static_cast<int>((val[s][i] - minval)/binwidth + 0.5)]++;
288         }
289         for (i = 0; i < nbin; i++)
290         {
291             fprintf(fp, " %g  %g\n", minval+i*binwidth, static_cast<double>(histo[i])/(n*binwidth));
292         }
293         if (s < nset-1)
294         {
295             fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
296         }
297     }
298     xvgrclose(fp);
299 }
300
301 static int real_comp(const void *a, const void *b)
302 {
303     real dif = *(real *)a - *(real *)b;
304
305     if (dif < 0)
306     {
307         return -1;
308     }
309     else if (dif > 0)
310     {
311         return 1;
312     }
313     else
314     {
315         return 0;
316     }
317 }
318
319 static void average(const char *avfile, int avbar_opt,
320                     int n, int nset, real **val, real *t)
321 {
322     FILE   *fp;
323     int     i, s, edge = 0;
324     double  av, var, err;
325     real   *tmp = NULL;
326
327     fp = gmx_ffopen(avfile, "w");
328     if ((avbar_opt == avbarERROR) && (nset == 1))
329     {
330         avbar_opt = avbarNONE;
331     }
332     if (avbar_opt != avbarNONE)
333     {
334         if (avbar_opt == avbar90)
335         {
336             snew(tmp, nset);
337             fprintf(fp, "@TYPE xydydy\n");
338             edge = static_cast<int>(nset*0.05+0.5);
339             fprintf(stdout, "Errorbars: discarding %d points on both sides: %d%%"
340                     " interval\n", edge, static_cast<int>(100*(nset-2*edge)/nset+0.5));
341         }
342         else
343         {
344             fprintf(fp, "@TYPE xydy\n");
345         }
346     }
347
348     for (i = 0; i < n; i++)
349     {
350         av = 0;
351         for (s = 0; s < nset; s++)
352         {
353             av += val[s][i];
354         }
355         av /= nset;
356         fprintf(fp, " %g %g", t[i], av);
357         var = 0;
358         if (avbar_opt != avbarNONE)
359         {
360             if (avbar_opt == avbar90)
361             {
362                 for (s = 0; s < nset; s++)
363                 {
364                     tmp[s] = val[s][i];
365                 }
366                 qsort(tmp, nset, sizeof(tmp[0]), real_comp);
367                 fprintf(fp, " %g %g", tmp[nset-1-edge]-av, av-tmp[edge]);
368             }
369             else
370             {
371                 for (s = 0; s < nset; s++)
372                 {
373                     var += sqr(val[s][i]-av);
374                 }
375                 if (avbar_opt == avbarSTDDEV)
376                 {
377                     err = std::sqrt(var/nset);
378                 }
379                 else
380                 {
381                     err = std::sqrt(var/(nset*(nset-1)));
382                 }
383                 fprintf(fp, " %g", err);
384             }
385         }
386         fprintf(fp, "\n");
387     }
388     gmx_ffclose(fp);
389
390     if (avbar_opt == avbar90)
391     {
392         sfree(tmp);
393     }
394 }
395
396 /*! \brief Compute final error estimate.
397  *
398  * See Eqn A17, Hess, JCP 116 (2002) 209-217 for details.
399  */
400 static real optimal_error_estimate(double sigma, double fitparm[], real tTotal)
401 {
402     double ss = fitparm[1]*fitparm[0]+(1-fitparm[1])*fitparm[2];
403     if ((tTotal <= 0) || (ss <= 0))
404     {
405         fprintf(stderr, "Problem in error estimate: T = %g, ss = %g\n",
406                 tTotal, ss);
407         return 0;
408     }
409
410     return sigma*std::sqrt(2*ss/tTotal);
411 }
412
413 static void estimate_error(const char *eefile, int nb_min, int resol, int n,
414                            int nset, double *av, double *sig, real **val, real dt,
415                            gmx_bool bFitAc, gmx_bool bSingleExpFit, gmx_bool bAllowNegLTCorr,
416                            const output_env_t oenv)
417 {
418     FILE    *fp;
419     int      bs, prev_bs, nbs, nb;
420     real     spacing, nbr;
421     int      s, i, j;
422     double   blav, var;
423     char   **leg;
424     real    *tbs, *ybs, rtmp, dens, *fitsig, twooe, tau1_est, tau_sig;
425     double   fitparm[3];
426     real     ee, a, tau1, tau2;
427
428     if (n < 4)
429     {
430         fprintf(stdout, "The number of points is smaller than 4, can not make an error estimate\n");
431
432         return;
433     }
434
435     fp = xvgropen(eefile, "Error estimates",
436                   "Block size (time)", "Error estimate", oenv);
437     if (output_env_get_print_xvgr_codes(oenv))
438     {
439         fprintf(fp,
440                 "@ subtitle \"using block averaging, total time %g (%d points)\"\n",
441                 (n-1)*dt, n);
442     }
443     snew(leg, 2*nset);
444     xvgr_legend(fp, 2*nset, (const char**)leg, oenv);
445     sfree(leg);
446
447     spacing = std::pow(2.0, 1.0/resol);
448     snew(tbs, n);
449     snew(ybs, n);
450     snew(fitsig, n);
451     for (s = 0; s < nset; s++)
452     {
453         nbs     = 0;
454         prev_bs = 0;
455         nbr     = nb_min;
456         while (nbr <= n)
457         {
458             bs = n/static_cast<int>(nbr);
459             if (bs != prev_bs)
460             {
461                 nb  = n/bs;
462                 var = 0;
463                 for (i = 0; i < nb; i++)
464                 {
465                     blav = 0;
466                     for (j = 0; j < bs; j++)
467                     {
468                         blav += val[s][bs*i+j];
469                     }
470                     var += sqr(av[s] - blav/bs);
471                 }
472                 tbs[nbs] = bs*dt;
473                 if (sig[s] == 0)
474                 {
475                     ybs[nbs] = 0;
476                 }
477                 else
478                 {
479                     ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]);
480                 }
481                 nbs++;
482             }
483             nbr    *= spacing;
484             prev_bs = bs;
485         }
486         if (sig[s] == 0)
487         {
488             ee   = 0;
489             a    = 1;
490             tau1 = 0;
491             tau2 = 0;
492         }
493         else
494         {
495             for (i = 0; i < nbs/2; i++)
496             {
497                 rtmp         = tbs[i];
498                 tbs[i]       = tbs[nbs-1-i];
499                 tbs[nbs-1-i] = rtmp;
500                 rtmp         = ybs[i];
501                 ybs[i]       = ybs[nbs-1-i];
502                 ybs[nbs-1-i] = rtmp;
503             }
504             /* The initial slope of the normalized ybs^2 is 1.
505              * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1
506              * From this we take our initial guess for tau1.
507              */
508             twooe = 2.0/std::exp(1.0);
509             i     = -1;
510             do
511             {
512                 i++;
513                 tau1_est = tbs[i];
514             }
515             while (i < nbs - 1 &&
516                    (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est));
517
518             if (ybs[0] > ybs[1])
519             {
520                 fprintf(stdout, "Data set %d has strange time correlations:\n"
521                         "the std. error using single points is larger than that of blocks of 2 points\n"
522                         "The error estimate might be inaccurate, check the fit\n",
523                         s+1);
524                 /* Use the total time as tau for the fitting weights */
525                 tau_sig = (n - 1)*dt;
526             }
527             else
528             {
529                 tau_sig = tau1_est;
530             }
531
532             if (debug)
533             {
534                 fprintf(debug, "set %d tau1 estimate %f\n", s+1, tau1_est);
535             }
536
537             /* Generate more or less appropriate sigma's,
538              * also taking the density of points into account.
539              */
540             for (i = 0; i < nbs; i++)
541             {
542                 if (i == 0)
543                 {
544                     dens = tbs[1]/tbs[0] - 1;
545                 }
546                 else if (i == nbs-1)
547                 {
548                     dens = tbs[nbs-1]/tbs[nbs-2] - 1;
549                 }
550                 else
551                 {
552                     dens = 0.5*(tbs[i+1]/tbs[i-1] - 1);
553                 }
554                 fitsig[i] = std::sqrt((tau_sig + tbs[i])/dens);
555             }
556
557             if (!bSingleExpFit)
558             {
559                 fitparm[0] = tau1_est;
560                 fitparm[1] = 0.95;
561                 /* We set the initial guess for tau2
562                  * to halfway between tau1_est and the total time (on log scale).
563                  */
564                 fitparm[2] = std::sqrt(tau1_est*(n-1)*dt);
565                 do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv,
566                          bDebugMode(), effnERREST, fitparm, 0,
567                          NULL);
568             }
569             if (bSingleExpFit || fitparm[0] < 0 || fitparm[2] < 0 || fitparm[1] < 0
570                 || (fitparm[1] > 1 && !bAllowNegLTCorr) || fitparm[2] > (n-1)*dt)
571             {
572                 if (!bSingleExpFit)
573                 {
574                     if (fitparm[2] > (n-1)*dt)
575                     {
576                         fprintf(stdout,
577                                 "Warning: tau2 is longer than the length of the data (%g)\n"
578                                 "         the statistics might be bad\n",
579                                 (n-1)*dt);
580                     }
581                     else
582                     {
583                         fprintf(stdout, "a fitted parameter is negative\n");
584                     }
585                     fprintf(stdout, "invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
586                             optimal_error_estimate(sig[s], fitparm, n*dt),
587                             fitparm[1], fitparm[0], fitparm[2]);
588                     /* Do a fit with tau2 fixed at the total time.
589                      * One could also choose any other large value for tau2.
590                      */
591                     fitparm[0] = tau1_est;
592                     fitparm[1] = 0.95;
593                     fitparm[2] = (n-1)*dt;
594                     fprintf(stdout, "Will fix tau2 at the total time: %g\n", fitparm[2]);
595                     do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(),
596                              effnERREST, fitparm, 4, NULL);
597                 }
598                 if (bSingleExpFit || fitparm[0] < 0 || fitparm[1] < 0
599                     || (fitparm[1] > 1 && !bAllowNegLTCorr))
600                 {
601                     if (!bSingleExpFit)
602                     {
603                         fprintf(stdout, "a fitted parameter is negative\n");
604                         fprintf(stdout, "invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
605                                 optimal_error_estimate(sig[s], fitparm, n*dt),
606                                 fitparm[1], fitparm[0], fitparm[2]);
607                     }
608                     /* Do a single exponential fit */
609                     fprintf(stderr, "Will use a single exponential fit for set %d\n", s+1);
610                     fitparm[0] = tau1_est;
611                     fitparm[1] = 1.0;
612                     fitparm[2] = 0.0;
613                     do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(),
614                              effnERREST, fitparm, 6, NULL);
615                 }
616             }
617             ee   = optimal_error_estimate(sig[s], fitparm, n*dt);
618             a    = fitparm[1];
619             tau1 = fitparm[0];
620             tau2 = fitparm[2];
621         }
622         fprintf(stdout, "Set %3d:  err.est. %g  a %g  tau1 %g  tau2 %g\n",
623                 s+1, ee, a, tau1, tau2);
624         if (output_env_get_xvg_format(oenv) == exvgXMGR)
625         {
626             fprintf(fp, "@ legend string %d \"av %f\"\n", 2*s, av[s]);
627             fprintf(fp, "@ legend string %d \"ee %6g\"\n", 2*s+1,
628                     optimal_error_estimate(sig[s], fitparm, n*dt));
629         }
630         else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
631         {
632             fprintf(fp, "@ s%d legend \"av %f\"\n", 2*s, av[s]);
633             fprintf(fp, "@ s%d legend \"ee %6g\"\n", 2*s+1,
634                     optimal_error_estimate(sig[s], fitparm, n*dt));
635         }
636         for (i = 0; i < nbs; i++)
637         {
638             fprintf(fp, "%g %g %g\n", tbs[i], sig[s]*std::sqrt(ybs[i]/(n*dt)),
639                     sig[s]*std::sqrt(fit_function(effnERREST, fitparm, tbs[i])/(n*dt)));
640         }
641
642         if (bFitAc)
643         {
644             int    fitlen;
645             real  *ac, acint;
646             double ac_fit[4];
647
648             snew(ac, n);
649             for (i = 0; i < n; i++)
650             {
651                 ac[i] = val[s][i] - av[s];
652                 if (i > 0)
653                 {
654                     fitsig[i] = std::sqrt(static_cast<real>(i));
655                 }
656                 else
657                 {
658                     fitsig[i] = 1;
659                 }
660             }
661             low_do_autocorr(NULL, oenv, NULL, n, 1, -1, &ac,
662                             dt, eacNormal, 1, FALSE, TRUE,
663                             FALSE, 0, 0, effnNONE);
664
665             fitlen = n/nb_min;
666
667             /* Integrate ACF only up to fitlen/2 to avoid integrating noise */
668             acint = 0.5*ac[0];
669             for (i = 1; i <= fitlen/2; i++)
670             {
671                 acint += ac[i];
672             }
673             acint *= dt;
674
675             /* Generate more or less appropriate sigma's */
676             for (i = 0; i <= fitlen; i++)
677             {
678                 fitsig[i] = std::sqrt(acint + dt*i);
679             }
680
681             ac_fit[0] = 0.5*acint;
682             ac_fit[1] = 0.95;
683             ac_fit[2] = 10*acint;
684             do_lmfit(n/nb_min, ac, fitsig, dt, 0, 0, fitlen*dt, oenv,
685                      bDebugMode(), effnEXPEXP, ac_fit, 0, NULL);
686             ac_fit[3] = 1 - ac_fit[1];
687
688             fprintf(stdout, "Set %3d:  ac erest %g  a %g  tau1 %g  tau2 %g\n",
689                     s+1, optimal_error_estimate(sig[s], ac_fit, n*dt),
690                     ac_fit[1], ac_fit[0], ac_fit[2]);
691
692             fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
693             for (i = 0; i < nbs; i++)
694             {
695                 fprintf(fp, "%g %g\n", tbs[i],
696                         sig[s]*std::sqrt(fit_function(effnERREST, ac_fit, tbs[i]))/(n*dt));
697             }
698
699             sfree(ac);
700         }
701         if (s < nset-1)
702         {
703             fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
704         }
705     }
706     sfree(fitsig);
707     sfree(ybs);
708     sfree(tbs);
709     xvgrclose(fp);
710 }
711
712 static void luzar_correl(int nn, real *time, int nset, real **val, real temp,
713                          gmx_bool bError, real fit_start)
714 {
715     real      *kt;
716     real       d2;
717     int        j;
718
719     please_cite(stdout, "Spoel2006b");
720
721     /* Compute negative derivative k(t) = -dc(t)/dt */
722     if (!bError)
723     {
724         snew(kt, nn);
725         compute_derivative(nn, time, val[0], kt);
726         for (j = 0; (j < nn); j++)
727         {
728             kt[j] = -kt[j];
729         }
730         if (debug)
731         {
732             d2 = 0;
733             for (j = 0; (j < nn); j++)
734             {
735                 d2 += sqr(kt[j] - val[3][j]);
736             }
737             fprintf(debug, "RMS difference in derivatives is %g\n", std::sqrt(d2/nn));
738         }
739         analyse_corr(nn, time, val[0], val[2], kt, NULL, NULL, NULL, fit_start,
740                      temp);
741         sfree(kt);
742     }
743     else if (nset == 6)
744     {
745         analyse_corr(nn, time, val[0], val[2], val[4],
746                      val[1], val[3], val[5], fit_start, temp);
747     }
748     else
749     {
750         printf("Inconsistent input. I need c(t) sigma_c(t) n(t) sigma_n(t) K(t) sigma_K(t)\n");
751         printf("Not doing anything. Sorry.\n");
752     }
753 }
754
755 static void filter(real flen, int n, int nset, real **val, real dt)
756 {
757     int     f, s, i, j;
758     double *filt, sum, vf, fluc, fluctot;
759
760     f = static_cast<int>(flen/(2*dt));
761     snew(filt, f+1);
762     filt[0] = 1;
763     sum     = 1;
764     for (i = 1; i <= f; i++)
765     {
766         filt[i] = std::cos(M_PI*dt*i/flen);
767         sum    += 2*filt[i];
768     }
769     for (i = 0; i <= f; i++)
770     {
771         filt[i] /= sum;
772     }
773     fprintf(stdout, "Will calculate the fluctuation over %d points\n", n-2*f);
774     fprintf(stdout, "  using a filter of length %g of %d points\n", flen, 2*f+1);
775     fluctot = 0;
776     for (s = 0; s < nset; s++)
777     {
778         fluc = 0;
779         for (i = f; i < n-f; i++)
780         {
781             vf = filt[0]*val[s][i];
782             for (j = 1; j <= f; j++)
783             {
784                 vf += filt[j]*(val[s][i-f]+val[s][i+f]);
785             }
786             fluc += sqr(val[s][i] - vf);
787         }
788         fluc    /= n - 2*f;
789         fluctot += fluc;
790         fprintf(stdout, "Set %3d filtered fluctuation: %12.6e\n", s+1, std::sqrt(fluc));
791     }
792     fprintf(stdout, "Overall filtered fluctuation: %12.6e\n", std::sqrt(fluctot/nset));
793     fprintf(stdout, "\n");
794
795     sfree(filt);
796 }
797
798 static void do_fit(FILE *out, int n, gmx_bool bYdy,
799                    int ny, real *x0, real **val,
800                    int npargs, t_pargs *ppa, const output_env_t oenv,
801                    const char *fn_fitted)
802 {
803     real   *c1 = NULL, *sig = NULL;
804     double *fitparm;
805     real    tendfit, tbeginfit;
806     int     i, efitfn, nparm;
807
808     efitfn = get_acffitfn();
809     nparm  = effnNparams(efitfn);
810     fprintf(out, "Will fit to the following function:\n");
811     fprintf(out, "%s\n", effnDescription(efitfn));
812     c1 = val[n];
813     if (bYdy)
814     {
815         c1  = val[n];
816         sig = val[n+1];
817         fprintf(out, "Using two columns as y and sigma values\n");
818     }
819     else
820     {
821         snew(sig, ny);
822     }
823     if (opt2parg_bSet("-beginfit", npargs, ppa))
824     {
825         tbeginfit = opt2parg_real("-beginfit", npargs, ppa);
826     }
827     else
828     {
829         tbeginfit = x0[0];
830     }
831     if (opt2parg_bSet("-endfit", npargs, ppa))
832     {
833         tendfit   = opt2parg_real("-endfit", npargs, ppa);
834     }
835     else
836     {
837         tendfit   = x0[ny-1];
838     }
839
840     snew(fitparm, nparm);
841     switch (efitfn)
842     {
843         case effnEXP1:
844             fitparm[0] = 0.5;
845             break;
846         case effnEXP2:
847             fitparm[0] = 0.5;
848             fitparm[1] = c1[0];
849             break;
850         case effnEXPEXP:
851             fitparm[0] = 1.0;
852             fitparm[1] = 0.5*c1[0];
853             fitparm[2] = 10.0;
854             break;
855         case effnEXP5:
856             fitparm[0] = fitparm[2] = 0.5*c1[0];
857             fitparm[1] = 10;
858             fitparm[3] = 40;
859             fitparm[4] = 0;
860             break;
861         case effnEXP7:
862             fitparm[0] = fitparm[2] = fitparm[4] = 0.33*c1[0];
863             fitparm[1] = 1;
864             fitparm[3] = 10;
865             fitparm[5] = 100;
866             fitparm[6] = 0;
867             break;
868         case effnEXP9:
869             fitparm[0] = fitparm[2] = fitparm[4] = fitparm[6] = 0.25*c1[0];
870             fitparm[1] = 0.1;
871             fitparm[3] = 1;
872             fitparm[5] = 10;
873             fitparm[7] = 100;
874             fitparm[8] = 0;
875             break;
876         default:
877             fprintf(out, "Warning: don't know how to initialize the parameters\n");
878             for (i = 0; (i < nparm); i++)
879             {
880                 fitparm[i] = 1;
881             }
882     }
883     fprintf(out, "Starting parameters:\n");
884     for (i = 0; (i < nparm); i++)
885     {
886         fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
887     }
888     if (do_lmfit(ny, c1, sig, 0, x0, tbeginfit, tendfit,
889                  oenv, bDebugMode(), efitfn, fitparm, 0,
890                  fn_fitted) > 0)
891     {
892         for (i = 0; (i < nparm); i++)
893         {
894             fprintf(out, "a%-2d = %12.5e\n", i+1, fitparm[i]);
895         }
896     }
897     else
898     {
899         fprintf(out, "No solution was found\n");
900     }
901 }
902
903 static void print_fitted_function(const char   *fitfile,
904                                   const char   *fn_fitted,
905                                   gmx_bool      bXYdy,
906                                   int           nset,
907                                   int           n,
908                                   real         *t,
909                                   real        **val,
910                                   int           npargs,
911                                   t_pargs      *ppa,
912                                   output_env_t  oenv)
913 {
914     FILE *out_fit = gmx_ffopen(fitfile, "w");
915     if (bXYdy && nset >= 2)
916     {
917         do_fit(out_fit, 0, TRUE, n, t, val, npargs, ppa, oenv,
918                fn_fitted);
919     }
920     else
921     {
922         char *buf2 = NULL;
923         int   s, buflen = 0;
924         if (NULL != fn_fitted)
925         {
926             buflen = std::strlen(fn_fitted)+32;
927             snew(buf2, buflen);
928             std::strncpy(buf2, fn_fitted, buflen);
929             buf2[std::strlen(buf2)-4] = '\0';
930         }
931         for (s = 0; s < nset; s++)
932         {
933             char *buf = NULL;
934             if (NULL != fn_fitted)
935             {
936                 snew(buf, buflen);
937                 snprintf(buf, n, "%s_%d.xvg", buf2, s);
938             }
939             do_fit(out_fit, s, FALSE, n, t, val, npargs, ppa, oenv, buf);
940             sfree(buf);
941         }
942         sfree(buf2);
943     }
944     gmx_ffclose(out_fit);
945 }
946
947 int gmx_analyze(int argc, char *argv[])
948 {
949     static const char *desc[] = {
950         "[THISMODULE] reads an ASCII file and analyzes data sets.",
951         "A line in the input file may start with a time",
952         "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.",
953         "Multiple sets can also be",
954         "read when they are separated by & (option [TT]-n[tt]);",
955         "in this case only one [IT]y[it]-value is read from each line.",
956         "All lines starting with # and @ are skipped.",
957         "All analyses can also be done for the derivative of a set",
958         "(option [TT]-d[tt]).[PAR]",
959
960         "All options, except for [TT]-av[tt] and [TT]-power[tt], assume that the",
961         "points are equidistant in time.[PAR]",
962
963         "[THISMODULE] always shows the average and standard deviation of each",
964         "set, as well as the relative deviation of the third",
965         "and fourth cumulant from those of a Gaussian distribution with the same",
966         "standard deviation.[PAR]",
967
968         "Option [TT]-ac[tt] produces the autocorrelation function(s).",
969         "Be sure that the time interval between data points is",
970         "much shorter than the time scale of the autocorrelation.[PAR]",
971
972         "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of",
973         "i/2 periods. The formula is::",
974         "",
975         "  [MATH]2 ([INT][FROM]0[from][TO]T[to][int] y(t) [COS]i [GRK]pi[grk] t[cos] dt)^2 / [INT][FROM]0[from][TO]T[to][int] y^2(t) dt[math]",
976         "",
977         "This is useful for principal components obtained from covariance",
978         "analysis, since the principal components of random diffusion are",
979         "pure cosines.[PAR]",
980
981         "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]",
982
983         "Option [TT]-dist[tt] produces distribution plot(s).[PAR]",
984
985         "Option [TT]-av[tt] produces the average over the sets.",
986         "Error bars can be added with the option [TT]-errbar[tt].",
987         "The errorbars can represent the standard deviation, the error",
988         "(assuming the points are independent) or the interval containing",
989         "90% of the points, by discarding 5% of the points at the top and",
990         "the bottom.[PAR]",
991
992         "Option [TT]-ee[tt] produces error estimates using block averaging.",
993         "A set is divided in a number of blocks and averages are calculated for",
994         "each block. The error for the total average is calculated from",
995         "the variance between averages of the m blocks B[SUB]i[sub] as follows:",
996         "error^2 = [SUM][sum] (B[SUB]i[sub] - [CHEVRON]B[chevron])^2 / (m*(m-1)).",
997         "These errors are plotted as a function of the block size.",
998         "Also an analytical block average curve is plotted, assuming",
999         "that the autocorrelation is a sum of two exponentials.",
1000         "The analytical curve for the block average is::",
1001         "",
1002         "  [MATH]f(t) = [GRK]sigma[grk][TT]*[tt][SQRT]2/T (  [GRK]alpha[grk]   ([GRK]tau[grk][SUB]1[sub] (([EXP]-t/[GRK]tau[grk][SUB]1[sub][exp] - 1) [GRK]tau[grk][SUB]1[sub]/t + 1)) +",
1003         "                         (1-[GRK]alpha[grk]) ([GRK]tau[grk][SUB]2[sub] (([EXP]-t/[GRK]tau[grk][SUB]2[sub][exp] - 1) [GRK]tau[grk][SUB]2[sub]/t + 1)))[sqrt][math],",
1004         "",
1005         "where T is the total time.",
1006         "[GRK]alpha[grk], [GRK]tau[grk][SUB]1[sub] and [GRK]tau[grk][SUB]2[sub] are obtained by fitting f^2(t) to error^2.",
1007         "When the actual block average is very close to the analytical curve,",
1008         "the error is [MATH][GRK]sigma[grk][TT]*[tt][SQRT]2/T (a [GRK]tau[grk][SUB]1[sub] + (1-a) [GRK]tau[grk][SUB]2[sub])[sqrt][math].",
1009         "The complete derivation is given in",
1010         "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",
1011
1012         "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
1013         "of each set and over all sets with respect to a filtered average.",
1014         "The filter is proportional to cos([GRK]pi[grk] t/len) where t goes from -len/2",
1015         "to len/2. len is supplied with the option [TT]-filter[tt].",
1016         "This filter reduces oscillations with period len/2 and len by a factor",
1017         "of 0.79 and 0.33 respectively.[PAR]",
1018
1019         "Option [TT]-g[tt] fits the data to the function given with option",
1020         "[TT]-fitfn[tt].[PAR]",
1021
1022         "Option [TT]-power[tt] fits the data to [MATH]b t^a[math], which is accomplished",
1023         "by fitting to [MATH]a t + b[math] on log-log scale. All points after the first",
1024         "zero or with a negative value are ignored.[PAR]"
1025
1026         "Option [TT]-luzar[tt] performs a Luzar & Chandler kinetics analysis",
1027         "on output from [gmx-hbond]. The input file can be taken directly",
1028         "from [TT]gmx hbond -ac[tt], and then the same result should be produced.[PAR]",
1029         "Option [TT]-fitfn[tt] performs curve fitting to a number of different",
1030         "curves that make sense in the context of molecular dynamics, mainly",
1031         "exponential curves. More information is in the manual. To check the output",
1032         "of the fitting procedure the option [TT]-fitted[tt] will print both the",
1033         "original data and the fitted function to a new data file. The fitting",
1034         "parameters are stored as comment in the output file."
1035     };
1036     static real        tb         = -1, te = -1, frac = 0.5, filtlen = 0, binwidth = 0.1, aver_start = 0;
1037     static gmx_bool    bHaveT     = TRUE, bDer = FALSE, bSubAv = TRUE, bAverCorr = FALSE, bXYdy = FALSE;
1038     static gmx_bool    bEESEF     = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE;
1039     static gmx_bool    bIntegrate = FALSE, bRegression = FALSE, bLuzar = FALSE;
1040     static int         nsets_in   = 1, d = 1, nb_min = 4, resol = 10;
1041     static real        temp       = 298.15, fit_start = 1, fit_end = 60;
1042
1043     /* must correspond to enum avbar* declared at beginning of file */
1044     static const char *avbar_opt[avbarNR+1] = {
1045         NULL, "none", "stddev", "error", "90", NULL
1046     };
1047
1048     t_pargs            pa[] = {
1049         { "-time",    FALSE, etBOOL, {&bHaveT},
1050           "Expect a time in the input" },
1051         { "-b",       FALSE, etREAL, {&tb},
1052           "First time to read from set" },
1053         { "-e",       FALSE, etREAL, {&te},
1054           "Last time to read from set" },
1055         { "-n",       FALSE, etINT, {&nsets_in},
1056           "Read this number of sets separated by &" },
1057         { "-d",       FALSE, etBOOL, {&bDer},
1058           "Use the derivative" },
1059         { "-dp",      FALSE, etINT, {&d},
1060           "HIDDENThe derivative is the difference over this number of points" },
1061         { "-bw",      FALSE, etREAL, {&binwidth},
1062           "Binwidth for the distribution" },
1063         { "-errbar",  FALSE, etENUM, {avbar_opt},
1064           "Error bars for [TT]-av[tt]" },
1065         { "-integrate", FALSE, etBOOL, {&bIntegrate},
1066           "Integrate data function(s) numerically using trapezium rule" },
1067         { "-aver_start", FALSE, etREAL, {&aver_start},
1068           "Start averaging the integral from here" },
1069         { "-xydy",    FALSE, etBOOL, {&bXYdy},
1070           "Interpret second data set as error in the y values for integrating" },
1071         { "-regression", FALSE, etBOOL, {&bRegression},
1072           "Perform a linear regression analysis on the data. If [TT]-xydy[tt] is set a second set will be interpreted as the error bar in the Y value. Otherwise, if multiple data sets are present a multilinear regression will be performed yielding the constant A that minimize [MATH][GRK]chi[grk]^2 = (y - A[SUB]0[sub] x[SUB]0[sub] - A[SUB]1[sub] x[SUB]1[sub] - ... - A[SUB]N[sub] x[SUB]N[sub])^2[math] where now Y is the first data set in the input file and x[SUB]i[sub] the others. Do read the information at the option [TT]-time[tt]." },
1073         { "-luzar",   FALSE, etBOOL, {&bLuzar},
1074           "Do a Luzar and Chandler analysis on a correlation function and "
1075           "related as produced by [gmx-hbond]. When in addition the "
1076           "[TT]-xydy[tt] flag is given the second and fourth column will be "
1077           "interpreted as errors in c(t) and n(t)." },
1078         { "-temp",    FALSE, etREAL, {&temp},
1079           "Temperature for the Luzar hydrogen bonding kinetics analysis (K)" },
1080         { "-fitstart", FALSE, etREAL, {&fit_start},
1081           "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" },
1082         { "-fitend", FALSE, etREAL, {&fit_end},
1083           "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with [TT]-gem[tt]" },
1084         { "-nbmin",   FALSE, etINT, {&nb_min},
1085           "HIDDENMinimum number of blocks for block averaging" },
1086         { "-resol", FALSE, etINT, {&resol},
1087           "HIDDENResolution for the block averaging, block size increases with"
1088           " a factor 2^(1/resol)" },
1089         { "-eeexpfit", FALSE, etBOOL, {&bEESEF},
1090           "HIDDENAlways use a single exponential fit for the error estimate" },
1091         { "-eenlc", FALSE, etBOOL, {&bEENLC},
1092           "HIDDENAllow a negative long-time correlation" },
1093         { "-eefitac", FALSE, etBOOL, {&bEeFitAc},
1094           "HIDDENAlso plot analytical block average using a autocorrelation fit" },
1095         { "-filter",  FALSE, etREAL, {&filtlen},
1096           "Print the high-frequency fluctuation after filtering with a cosine filter of this length" },
1097         { "-power", FALSE, etBOOL, {&bPower},
1098           "Fit data to: b t^a" },
1099         { "-subav", FALSE, etBOOL, {&bSubAv},
1100           "Subtract the average before autocorrelating" },
1101         { "-oneacf", FALSE, etBOOL, {&bAverCorr},
1102           "Calculate one ACF over all sets" },
1103     };
1104 #define NPA asize(pa)
1105
1106     FILE           *out;
1107     int             n, nlast, s, nset, i, j = 0;
1108     real          **val, *t, dt, tot, error;
1109     double         *av, *sig, cum1, cum2, cum3, cum4, db;
1110     const char     *acfile, *msdfile, *ccfile, *distfile, *avfile, *eefile, *fitfile;
1111     output_env_t    oenv;
1112
1113     t_filenm        fnm[] = {
1114         { efXVG, "-f",    "graph",    ffREAD   },
1115         { efXVG, "-ac",   "autocorr", ffOPTWR  },
1116         { efXVG, "-msd",  "msd",      ffOPTWR  },
1117         { efXVG, "-cc",   "coscont",  ffOPTWR  },
1118         { efXVG, "-dist", "distr",    ffOPTWR  },
1119         { efXVG, "-av",   "average",  ffOPTWR  },
1120         { efXVG, "-ee",   "errest",   ffOPTWR  },
1121         { efXVG, "-fitted", "fitted", ffOPTWR },
1122         { efLOG, "-g",    "fitlog",   ffOPTWR  }
1123     };
1124 #define NFILE asize(fnm)
1125
1126     int      npargs;
1127     t_pargs *ppa;
1128
1129     npargs = asize(pa);
1130     ppa    = add_acf_pargs(&npargs, pa);
1131
1132     if (!parse_common_args(&argc, argv, PCA_CAN_VIEW,
1133                            NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
1134     {
1135         return 0;
1136     }
1137
1138     acfile   = opt2fn_null("-ac", NFILE, fnm);
1139     msdfile  = opt2fn_null("-msd", NFILE, fnm);
1140     ccfile   = opt2fn_null("-cc", NFILE, fnm);
1141     distfile = opt2fn_null("-dist", NFILE, fnm);
1142     avfile   = opt2fn_null("-av", NFILE, fnm);
1143     eefile   = opt2fn_null("-ee", NFILE, fnm);
1144     if (opt2parg_bSet("-fitfn", npargs, ppa) && acfile == NULL)
1145     {
1146         fitfile  = opt2fn("-g", NFILE, fnm);
1147     }
1148     else
1149     {
1150         fitfile  = opt2fn_null("-g", NFILE, fnm);
1151     }
1152
1153     val = read_xvg_time(opt2fn("-f", NFILE, fnm), bHaveT,
1154                         opt2parg_bSet("-b", npargs, ppa), tb,
1155                         opt2parg_bSet("-e", npargs, ppa), te,
1156                         nsets_in, &nset, &n, &dt, &t);
1157     printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt);
1158
1159     if (bDer)
1160     {
1161         printf("Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n\n",
1162                d, d);
1163         n -= d;
1164         for (s = 0; s < nset; s++)
1165         {
1166             for (i = 0; (i < n); i++)
1167             {
1168                 val[s][i] = (val[s][i+d]-val[s][i])/(d*dt);
1169             }
1170         }
1171     }
1172
1173     if (bIntegrate)
1174     {
1175         real sum, stddev;
1176
1177         printf("Calculating the integral using the trapezium rule\n");
1178
1179         if (bXYdy)
1180         {
1181             sum = evaluate_integral(n, t, val[0], val[1], aver_start, &stddev);
1182             printf("Integral %10.3f +/- %10.5f\n", sum, stddev);
1183         }
1184         else
1185         {
1186             for (s = 0; s < nset; s++)
1187             {
1188                 sum = evaluate_integral(n, t, val[s], NULL, aver_start, &stddev);
1189                 printf("Integral %d  %10.5f  +/- %10.5f\n", s+1, sum, stddev);
1190             }
1191         }
1192     }
1193
1194     if (fitfile != NULL)
1195     {
1196         print_fitted_function(fitfile,
1197                               opt2fn_null("-fitted", NFILE, fnm),
1198                               bXYdy, nset,
1199                               n, t, val,
1200                               npargs, ppa,
1201                               oenv);
1202     }
1203
1204     printf("                                      std. dev.    relative deviation of\n");
1205     printf("                       standard       ---------   cumulants from those of\n");
1206     printf("set      average       deviation      sqrt(n-1)   a Gaussian distribition\n");
1207     printf("                                                      cum. 3   cum. 4\n");
1208     snew(av, nset);
1209     snew(sig, nset);
1210     for (s = 0; (s < nset); s++)
1211     {
1212         cum1 = 0;
1213         cum2 = 0;
1214         cum3 = 0;
1215         cum4 = 0;
1216         for (i = 0; (i < n); i++)
1217         {
1218             cum1 += val[s][i];
1219         }
1220         cum1 /= n;
1221         for (i = 0; (i < n); i++)
1222         {
1223             db    = val[s][i]-cum1;
1224             cum2 += db*db;
1225             cum3 += db*db*db;
1226             cum4 += db*db*db*db;
1227         }
1228         cum2  /= n;
1229         cum3  /= n;
1230         cum4  /= n;
1231         av[s]  = cum1;
1232         sig[s] = std::sqrt(cum2);
1233         if (n > 1)
1234         {
1235             error = std::sqrt(cum2/(n-1));
1236         }
1237         else
1238         {
1239             error = 0;
1240         }
1241         printf("SS%d  %13.6e   %12.6e   %12.6e      %6.3f   %6.3f\n",
1242                s+1, av[s], sig[s], error,
1243                sig[s] ? cum3/(sig[s]*sig[s]*sig[s]*std::sqrt(8/M_PI)) : 0,
1244                sig[s] ? cum4/(sig[s]*sig[s]*sig[s]*sig[s]*3)-1 : 0);
1245     }
1246     printf("\n");
1247
1248     if (filtlen)
1249     {
1250         filter(filtlen, n, nset, val, dt);
1251     }
1252
1253     if (msdfile)
1254     {
1255         out = xvgropen(msdfile, "Mean square displacement",
1256                        "time", "MSD (nm\\S2\\N)", oenv);
1257         nlast = static_cast<int>(n*frac);
1258         for (s = 0; s < nset; s++)
1259         {
1260             for (j = 0; j <= nlast; j++)
1261             {
1262                 if (j % 100 == 0)
1263                 {
1264                     fprintf(stderr, "\r%d", j);
1265                 }
1266                 tot = 0;
1267                 for (i = 0; i < n-j; i++)
1268                 {
1269                     tot += sqr(val[s][i]-val[s][i+j]);
1270                 }
1271                 tot /= (n-j);
1272                 fprintf(out, " %g %8g\n", dt*j, tot);
1273             }
1274             if (s < nset-1)
1275             {
1276                 fprintf(out, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
1277             }
1278         }
1279         xvgrclose(out);
1280         fprintf(stderr, "\r%d, time=%g\n", j-1, (j-1)*dt);
1281     }
1282     if (ccfile)
1283     {
1284         plot_coscont(ccfile, n, nset, val, oenv);
1285     }
1286
1287     if (distfile)
1288     {
1289         histogram(distfile, binwidth, n, nset, val, oenv);
1290     }
1291     if (avfile)
1292     {
1293         average(avfile, nenum(avbar_opt), n, nset, val, t);
1294     }
1295     if (eefile)
1296     {
1297         estimate_error(eefile, nb_min, resol, n, nset, av, sig, val, dt,
1298                        bEeFitAc, bEESEF, bEENLC, oenv);
1299     }
1300     if (bPower)
1301     {
1302         power_fit(n, nset, val, t);
1303     }
1304
1305     if (acfile != NULL)
1306     {
1307         if (bSubAv)
1308         {
1309             for (s = 0; s < nset; s++)
1310             {
1311                 for (i = 0; i < n; i++)
1312                 {
1313                     val[s][i] -= av[s];
1314                 }
1315             }
1316         }
1317         do_autocorr(acfile, oenv, "Autocorrelation", n, nset, val, dt,
1318                     eacNormal, bAverCorr);
1319     }
1320
1321     if (bRegression)
1322     {
1323         regression_analysis(n, bXYdy, t, nset, val);
1324     }
1325
1326     if (bLuzar)
1327     {
1328         luzar_correl(n, t, nset, val, temp, bXYdy, fit_start);
1329     }
1330
1331     view_all(oenv, NFILE, fnm);
1332
1333     return 0;
1334 }