示例#1
0
void xvgr_new_dataset(FILE *out, int nr_first, int nsets,
                      const char **setname,
                      const gmx_output_env_t *oenv)
{
    int  i;
    char buf[STRLEN];

    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@\n");
        for (i = 0; (i < nsets); i++)
        {
            if (setname[i])
            {
                if (output_env_get_xvg_format(oenv) == exvgXMGR)
                {
                    fprintf(out, "@ legend string %d \"%s\"\n",
                            i+nr_first, xvgrstr(setname[i], oenv, buf, STRLEN));
                }
                else
                {
                    fprintf(out, "@ s%d legend \"%s\"\n",
                            i+nr_first, xvgrstr(setname[i], oenv, buf, STRLEN));
                }
            }
        }
    }
    else
    {
        fprintf(out, "\n");
    }
}
示例#2
0
void xvgr_legend(FILE *out, int nsets, const char** setname,
                 const gmx_output_env_t *oenv)
{
    int  i;
    char buf[STRLEN];

    if (output_env_get_print_xvgr_codes(oenv))
    {
        xvgr_view(out, 0.15, 0.15, 0.75, 0.85, oenv);
        fprintf(out, "@ legend on\n");
        fprintf(out, "@ legend box on\n");
        fprintf(out, "@ legend loctype view\n");
        fprintf(out, "@ legend %g, %g\n", 0.78, 0.8);
        fprintf(out, "@ legend length %d\n", 2);
        for (i = 0; (i < nsets); i++)
        {
            if (setname[i])
            {
                if (output_env_get_xvg_format(oenv) == exvgXMGR)
                {
                    fprintf(out, "@ legend string %d \"%s\"\n",
                            i, xvgrstr(setname[i], oenv, buf, STRLEN));
                }
                else
                {
                    fprintf(out, "@ s%d legend \"%s\"\n",
                            i, xvgrstr(setname[i], oenv, buf, STRLEN));
                }
            }
        }
    }
}
示例#3
0
文件: xvgr.c 项目: alwanderer/gromacs
gmx_bool output_env_get_print_xvgr_codes(const output_env_t oenv)
{
    int xvg_format;

    xvg_format = output_env_get_xvg_format(oenv);

    return (xvg_format == exvgXMGRACE || xvg_format == exvgXMGR);
}
示例#4
0
文件: xvgr.cpp 项目: rmcgibbo/gromacs
void xvgr_header(FILE *fp, const char *title, const char *xaxis,
                 const char *yaxis, int exvg_graph_type,
                 const gmx_output_env_t *oenv)
{
    char   pukestr[100], buf[STRLEN];

    if (output_env_get_print_xvgr_codes(oenv))
    {
        gmx_format_current_time(buf, STRLEN);
        fprintf(fp, "# This file was created %s", buf);
        try
        {
            gmx::BinaryInformationSettings settings;
            settings.generatedByHeader(true);
            settings.linePrefix("# ");
            gmx::printBinaryInformation(fp, output_env_get_program_context(oenv),
                                        settings);
        }
        GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
        fprintf(fp, "# %s is part of G R O M A C S:\n#\n",
                output_env_get_program_display_name(oenv));
        bromacs(pukestr, 99);
        fprintf(fp, "# %s\n#\n", pukestr);
        fprintf(fp, "@    title \"%s\"\n", xvgrstr(title, oenv, buf, STRLEN));
        fprintf(fp, "@    xaxis  label \"%s\"\n",
                xvgrstr(xaxis, oenv, buf, STRLEN));
        fprintf(fp, "@    yaxis  label \"%s\"\n",
                xvgrstr(yaxis, oenv, buf, STRLEN));
        switch (exvg_graph_type)
        {
            case exvggtXNY:
                if (output_env_get_xvg_format(oenv) == exvgXMGR)
                {
                    fprintf(fp, "@TYPE nxy\n");
                }
                else
                {
                    fprintf(fp, "@TYPE xy\n");
                }
                break;
            case exvggtXYDY:
                fprintf(fp, "@TYPE xydy\n");
                break;
            case exvggtXYDYDY:
                fprintf(fp, "@TYPE xydydy\n");
                break;
        }
    }
}
示例#5
0
void
SelectionCollection::printXvgrInfo(FILE *out, output_env_t oenv) const
{
    if (output_env_get_xvg_format(oenv) != exvgNONE)
    {
        const gmx_ana_selcollection_t &sc = impl_->sc_;
        std::fprintf(out, "# Selections:\n");
        for (int i = 0; i < sc.nvars; ++i)
        {
            std::fprintf(out, "#   %s\n", sc.varstrs[i]);
        }
        for (size_t i = 0; i < sc.sel.size(); ++i)
        {
            std::fprintf(out, "#   %s\n", sc.sel[i]->selectionText());
        }
        std::fprintf(out, "#\n");
    }
}
示例#6
0
文件: xvgr.c 项目: alwanderer/gromacs
void xvgr_header(FILE *fp, const char *title, const char *xaxis,
                 const char *yaxis, int exvg_graph_type,
                 const output_env_t oenv)
{
    char   pukestr[100], buf[STRLEN];
    time_t t;

    if (output_env_get_print_xvgr_codes(oenv))
    {
        time(&t);
        gmx_ctime_r(&t, buf, STRLEN);
        fprintf(fp, "# This file was created %s", buf);
        fprintf(fp, "# by the following command:\n# %s\n#\n", command_line());
        fprintf(fp, "# %s is part of G R O M A C S:\n#\n", ShortProgram());
        bromacs(pukestr, 99);
        fprintf(fp, "# %s\n#\n", pukestr);
        fprintf(fp, "@    title \"%s\"\n", xvgrstr(title, oenv, buf, STRLEN));
        fprintf(fp, "@    xaxis  label \"%s\"\n",
                xvgrstr(xaxis, oenv, buf, STRLEN));
        fprintf(fp, "@    yaxis  label \"%s\"\n",
                xvgrstr(yaxis, oenv, buf, STRLEN));
        switch (exvg_graph_type)
        {
            case exvggtXNY:
                if (output_env_get_xvg_format(oenv) == exvgXMGR)
                {
                    fprintf(fp, "@TYPE nxy\n");
                }
                else
                {
                    fprintf(fp, "@TYPE xy\n");
                }
                break;
            case exvggtXYDY:
                fprintf(fp, "@TYPE xydy\n");
                break;
            case exvggtXYDYDY:
                fprintf(fp, "@TYPE xydydy\n");
                break;
        }
    }
}
void
SelectionCollection::printXvgrInfo(FILE *out, output_env_t oenv) const
{
    int  i;

    if (output_env_get_xvg_format(oenv) != exvgNONE)
    {
        gmx_ana_selcollection_t *sc = &_impl->_sc;
        std::fprintf(out, "# Selections:\n");
        for (i = 0; i < sc->nvars; ++i)
        {
            std::fprintf(out, "#   %s\n", sc->varstrs[i]);
        }
        for (i = 0; i < (int)sc->sel.size(); ++i)
        {
            std::fprintf(out, "#   %s\n", sc->sel[i]->selectionText());
        }
        std::fprintf(out, "#\n");
    }
}
示例#8
0
static void write_xvgr_graphs(const char *file, int ngraphs, int nsetspergraph,
			      const char *title, const char *subtitle,
			      const char *xlabel, const char **ylabel,
			      int n, real *x, real **y, real ***sy,
			      real scale_x, gmx_bool bZero, gmx_bool bSplit,
                              const output_env_t oenv)
{
  FILE *out;
  int g,s,i;
  real min,max,xsp,ysp;
  
  out=ffopen(file,"w"); 
  if (output_env_get_xvg_format(oenv) == exvgXMGRACE) {
    fprintf(out,"@ autoscale onread none\n");
  }
  for(g=0; g<ngraphs; g++) {
    if (y) {
      min=y[g][0];
      max=y[g][0];
      for(i=0; i<n; i++) {
	if (y[g][i]<min) min=y[g][i];
	if (y[g][i]>max) max=y[g][i];
      }
    } else {
      min=sy[g][0][0];
      max=sy[g][0][0];
      for(s=0; s<nsetspergraph; s++) 
	for(i=0; i<n; i++) {
	  if (sy[g][s][i]<min) min=sy[g][s][i];
	  if (sy[g][s][i]>max) max=sy[g][s][i];
	}
    }
    if (bZero)
      min=0;
    else
      min=min-0.1*(max-min);
    max=max+0.1*(max-min);
    xsp=tick_spacing((x[n-1]-x[0])*scale_x,4);
    ysp=tick_spacing(max-min,3);
    if (output_env_get_print_xvgr_codes(oenv)) {
      fprintf(out,"@ with g%d\n@ g%d on\n",g,g);
      if (g==0) {
	fprintf(out,"@ title \"%s\"\n",title);
	if (subtitle)
	  fprintf(out,"@ subtitle \"%s\"\n",subtitle);
      }
      if (g==ngraphs-1)
	fprintf(out,"@ xaxis  label \"%s\"\n",xlabel);
      else 
	fprintf(out,"@ xaxis  ticklabel off\n");
      if (n > 1) {
	fprintf(out,"@ world xmin %g\n",x[0]*scale_x);
	fprintf(out,"@ world xmax %g\n",x[n-1]*scale_x);
	fprintf(out,"@ world ymin %g\n",min);
	fprintf(out,"@ world ymax %g\n",max);
      }
      fprintf(out,"@ view xmin 0.15\n");
      fprintf(out,"@ view xmax 0.85\n");
      fprintf(out,"@ view ymin %g\n",0.15+(ngraphs-1-g)*0.7/ngraphs);
      fprintf(out,"@ view ymax %g\n",0.15+(ngraphs-g)*0.7/ngraphs);
      fprintf(out,"@ yaxis  label \"%s\"\n",ylabel[g]);
      fprintf(out,"@ xaxis tick major %g\n",xsp);
      fprintf(out,"@ xaxis tick minor %g\n",xsp/2);
      fprintf(out,"@ xaxis ticklabel start type spec\n");
      fprintf(out,"@ xaxis ticklabel start %g\n",ceil(min/xsp)*xsp);
      fprintf(out,"@ yaxis tick major %g\n",ysp);
      fprintf(out,"@ yaxis tick minor %g\n",ysp/2);
      fprintf(out,"@ yaxis ticklabel start type spec\n");
      fprintf(out,"@ yaxis ticklabel start %g\n",ceil(min/ysp)*ysp);
      if ((min<0) && (max>0)) {
	fprintf(out,"@ zeroxaxis bar on\n");
	fprintf(out,"@ zeroxaxis bar linestyle 3\n");
      }
    }
    for(s=0; s<nsetspergraph; s++) {
        for(i=0; i<n; i++) {
            if ( bSplit && i>0 && abs(x[i])<1e-5 )
            {
                if (output_env_get_print_xvgr_codes(oenv))
                    fprintf(out,"&\n");
            }
            fprintf(out,"%10.4f %10.5f\n",
                    x[i]*scale_x,y ? y[g][i] : sy[g][s][i]);
        }
        if (output_env_get_print_xvgr_codes(oenv))
            fprintf(out,"&\n");
    }
  }
  ffclose(out);
}
示例#9
0
int gmx_saltbr(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_saltbr[tt] plots the distance between all combination of charged groups",
        "as a function of time. The groups are combined in different ways.",
        "A minimum distance can be given (i.e. a cut-off), such that groups",
        "that are never closer than that distance will not be plotted.[PAR]",
        "Output will be in a number of fixed filenames, [TT]min-min.xvg[tt], [TT]plus-min.xvg[tt]",
        "and [TT]plus-plus.xvg[tt], or files for every individual ion pair if the [TT]-sep[tt]",
        "option is selected. In this case, files are named as [TT]sb-(Resname)(Resnr)-(Atomnr)[tt].",
        "There may be [BB]many[bb] such files."
    };
    static gmx_bool bSep     = FALSE;
    static real     truncate = 1000.0;
    t_pargs         pa[]     = {
        { "-t",   FALSE, etREAL, {&truncate},
          "Groups that are never closer than this distance are not plotted" },
        { "-sep", FALSE, etBOOL, {&bSep},
          "Use separate files for each interaction (may be MANY)" }
    };
    t_filenm        fnm[] = {
        { efTRX, "-f",  NULL, ffREAD },
        { efTPX, NULL,  NULL, ffREAD },
    };
#define NFILE asize(fnm)

    FILE              *out[3], *fp;
    static const char *title[3] = {
        "Distance between positively charged groups",
        "Distance between negatively charged groups",
        "Distance between oppositely charged groups"
    };
    static const char *fn[3] = {
        "plus-plus.xvg",
        "min-min.xvg",
        "plus-min.xvg"
    };
    int                nset[3] = {0, 0, 0};

    t_topology        *top;
    int                ePBC;
    char              *buf;
    t_trxstatus       *status;
    int                i, j, k, m, nnn, teller, ncg, n1, n2, n3, natoms;
    real               t, *time, qi, qj;
    t_charge          *cg;
    real            ***cgdist;
    int              **nWithin;

    double             t0, dt;
    char               label[234];
    t_pbc              pbc;
    rvec              *x;
    matrix             box;
    output_env_t       oenv;

    parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);

    top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC);
    cg  = mk_charge(&top->atoms, &(top->cgs), &ncg);
    snew(cgdist, ncg);
    snew(nWithin, ncg);
    for (i = 0; (i < ncg); i++)
    {
        snew(cgdist[i], ncg);
        snew(nWithin[i], ncg);
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    teller = 0;
    time   = NULL;
    do
    {
        srenew(time, teller+1);
        time[teller] = t;

        set_pbc(&pbc, ePBC, box);

        for (i = 0; (i < ncg); i++)
        {
            for (j = i+1; (j < ncg); j++)
            {
                srenew(cgdist[i][j], teller+1);
                cgdist[i][j][teller] =
                    calc_dist(&pbc, x, &(top->cgs), cg[i].cg, cg[j].cg);
                if (cgdist[i][j][teller] < truncate)
                {
                    nWithin[i][j] = 1;
                }
            }
        }

        teller++;
    }
    while (read_next_x(oenv, status, &t, natoms, x, box));
    fprintf(stderr, "\n");
    close_trj(status);

    if (bSep)
    {
        snew(buf, 256);
        for (i = 0; (i < ncg); i++)
        {
            for (j = i+1; (j < ncg); j++)
            {
                if (nWithin[i][j])
                {
                    sprintf(buf, "sb-%s:%s.xvg", cg[i].label, cg[j].label);
                    fp = xvgropen(buf, buf, "Time (ps)", "Distance (nm)", oenv);
                    for (k = 0; (k < teller); k++)
                    {
                        fprintf(fp, "%10g  %10g\n", time[k], cgdist[i][j][k]);
                    }
                    ffclose(fp);
                }
            }
        }
        sfree(buf);
    }
    else
    {

        for (m = 0; (m < 3); m++)
        {
            out[m] = xvgropen(fn[m], title[m], "Time (ps)", "Distance (nm)", oenv);
        }

        snew(buf, 256);
        for (i = 0; (i < ncg); i++)
        {
            qi = cg[i].q;
            for (j = i+1; (j < ncg); j++)
            {
                qj = cg[j].q;
                if (nWithin[i][j])
                {
                    sprintf(buf, "%s:%s", cg[i].label, cg[j].label);
                    if (qi*qj < 0)
                    {
                        nnn = 2;
                    }
                    else if (qi+qj > 0)
                    {
                        nnn = 0;
                    }
                    else
                    {
                        nnn = 1;
                    }

                    if (nset[nnn] == 0)
                    {
                        xvgr_legend(out[nnn], 1, (const char**)&buf, oenv);
                    }
                    else
                    {
                        if (output_env_get_xvg_format(oenv) == exvgXMGR)
                        {
                            fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf);
                        }
                        else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
                        {
                            fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf);
                        }
                    }
                    nset[nnn]++;
                    nWithin[i][j] = nnn+1;
                }
            }
        }
        for (k = 0; (k < teller); k++)
        {
            for (m = 0; (m < 3); m++)
            {
                fprintf(out[m], "%10g", time[k]);
            }

            for (i = 0; (i < ncg); i++)
            {
                for (j = i+1; (j < ncg); j++)
                {
                    nnn = nWithin[i][j];
                    if (nnn > 0)
                    {
                        fprintf(out[nnn-1], "  %10g", cgdist[i][j][k]);
                    }
                }
            }
            for (m = 0; (m < 3); m++)
            {
                fprintf(out[m], "\n");
            }
        }
        for (m = 0; (m < 3); m++)
        {
            ffclose(out[m]);
            if (nset[m] == 0)
            {
                remove(fn[m]);
            }
        }
    }
    thanx(stderr);

    return 0;
}
示例#10
0
static void estimate_error(const char *eefile, int nb_min, int resol, int n,
                           int nset, double *av, double *sig, real **val, real dt,
                           gmx_bool bFitAc, gmx_bool bSingleExpFit, gmx_bool bAllowNegLTCorr,
                           const gmx_output_env_t *oenv)
{
    FILE    *fp;
    int      bs, prev_bs, nbs, nb;
    real     spacing, nbr;
    int      s, i, j;
    double   blav, var;
    char   **leg;
    real    *tbs, *ybs, rtmp, dens, *fitsig, twooe, tau1_est, tau_sig;
    double   fitparm[3];
    real     ee, a, tau1, tau2;

    if (n < 4)
    {
        fprintf(stdout, "The number of points is smaller than 4, can not make an error estimate\n");

        return;
    }

    fp = xvgropen(eefile, "Error estimates",
                  "Block size (time)", "Error estimate", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp,
                "@ subtitle \"using block averaging, total time %g (%d points)\"\n",
                (n-1)*dt, n);
    }
    snew(leg, 2*nset);
    xvgr_legend(fp, 2*nset, (const char**)leg, oenv);
    sfree(leg);

    spacing = std::pow(2.0, 1.0/resol);
    snew(tbs, n);
    snew(ybs, n);
    snew(fitsig, n);
    for (s = 0; s < nset; s++)
    {
        nbs     = 0;
        prev_bs = 0;
        nbr     = nb_min;
        while (nbr <= n)
        {
            bs = n/static_cast<int>(nbr);
            if (bs != prev_bs)
            {
                nb  = n/bs;
                var = 0;
                for (i = 0; i < nb; i++)
                {
                    blav = 0;
                    for (j = 0; j < bs; j++)
                    {
                        blav += val[s][bs*i+j];
                    }
                    var += sqr(av[s] - blav/bs);
                }
                tbs[nbs] = bs*dt;
                if (sig[s] == 0)
                {
                    ybs[nbs] = 0;
                }
                else
                {
                    ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]);
                }
                nbs++;
            }
            nbr    *= spacing;
            prev_bs = bs;
        }
        if (sig[s] == 0)
        {
            ee   = 0;
            a    = 1;
            tau1 = 0;
            tau2 = 0;
        }
        else
        {
            for (i = 0; i < nbs/2; i++)
            {
                rtmp         = tbs[i];
                tbs[i]       = tbs[nbs-1-i];
                tbs[nbs-1-i] = rtmp;
                rtmp         = ybs[i];
                ybs[i]       = ybs[nbs-1-i];
                ybs[nbs-1-i] = rtmp;
            }
            /* The initial slope of the normalized ybs^2 is 1.
             * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1
             * From this we take our initial guess for tau1.
             */
            twooe = 2.0/std::exp(1.0);
            i     = -1;
            do
            {
                i++;
                tau1_est = tbs[i];
            }
            while (i < nbs - 1 &&
                   (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est));

            if (ybs[0] > ybs[1])
            {
                fprintf(stdout, "Data set %d has strange time correlations:\n"
                        "the std. error using single points is larger than that of blocks of 2 points\n"
                        "The error estimate might be inaccurate, check the fit\n",
                        s+1);
                /* Use the total time as tau for the fitting weights */
                tau_sig = (n - 1)*dt;
            }
            else
            {
                tau_sig = tau1_est;
            }

            if (debug)
            {
                fprintf(debug, "set %d tau1 estimate %f\n", s+1, tau1_est);
            }

            /* Generate more or less appropriate sigma's,
             * also taking the density of points into account.
             */
            for (i = 0; i < nbs; i++)
            {
                if (i == 0)
                {
                    dens = tbs[1]/tbs[0] - 1;
                }
                else if (i == nbs-1)
                {
                    dens = tbs[nbs-1]/tbs[nbs-2] - 1;
                }
                else
                {
                    dens = 0.5*(tbs[i+1]/tbs[i-1] - 1);
                }
                fitsig[i] = std::sqrt((tau_sig + tbs[i])/dens);
            }

            if (!bSingleExpFit)
            {
                fitparm[0] = tau1_est;
                fitparm[1] = 0.95;
                /* We set the initial guess for tau2
                 * to halfway between tau1_est and the total time (on log scale).
                 */
                fitparm[2] = std::sqrt(tau1_est*(n-1)*dt);
                do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv,
                         bDebugMode(), effnERREST, fitparm, 0,
                         NULL);
            }
            if (bSingleExpFit || fitparm[0] < 0 || fitparm[2] < 0 || fitparm[1] < 0
                || (fitparm[1] > 1 && !bAllowNegLTCorr) || fitparm[2] > (n-1)*dt)
            {
                if (!bSingleExpFit)
                {
                    if (fitparm[2] > (n-1)*dt)
                    {
                        fprintf(stdout,
                                "Warning: tau2 is longer than the length of the data (%g)\n"
                                "         the statistics might be bad\n",
                                (n-1)*dt);
                    }
                    else
                    {
                        fprintf(stdout, "a fitted parameter is negative\n");
                    }
                    fprintf(stdout, "invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                            optimal_error_estimate(sig[s], fitparm, n*dt),
                            fitparm[1], fitparm[0], fitparm[2]);
                    /* Do a fit with tau2 fixed at the total time.
                     * One could also choose any other large value for tau2.
                     */
                    fitparm[0] = tau1_est;
                    fitparm[1] = 0.95;
                    fitparm[2] = (n-1)*dt;
                    fprintf(stdout, "Will fix tau2 at the total time: %g\n", fitparm[2]);
                    do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(),
                             effnERREST, fitparm, 4, NULL);
                }
                if (bSingleExpFit || fitparm[0] < 0 || fitparm[1] < 0
                    || (fitparm[1] > 1 && !bAllowNegLTCorr))
                {
                    if (!bSingleExpFit)
                    {
                        fprintf(stdout, "a fitted parameter is negative\n");
                        fprintf(stdout, "invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                                optimal_error_estimate(sig[s], fitparm, n*dt),
                                fitparm[1], fitparm[0], fitparm[2]);
                    }
                    /* Do a single exponential fit */
                    fprintf(stderr, "Will use a single exponential fit for set %d\n", s+1);
                    fitparm[0] = tau1_est;
                    fitparm[1] = 1.0;
                    fitparm[2] = 0.0;
                    do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(),
                             effnERREST, fitparm, 6, NULL);
                }
            }
            ee   = optimal_error_estimate(sig[s], fitparm, n*dt);
            a    = fitparm[1];
            tau1 = fitparm[0];
            tau2 = fitparm[2];
        }
        fprintf(stdout, "Set %3d:  err.est. %g  a %g  tau1 %g  tau2 %g\n",
                s+1, ee, a, tau1, tau2);
        if (output_env_get_xvg_format(oenv) == exvgXMGR)
        {
            fprintf(fp, "@ legend string %d \"av %f\"\n", 2*s, av[s]);
            fprintf(fp, "@ legend string %d \"ee %6g\"\n", 2*s+1,
                    optimal_error_estimate(sig[s], fitparm, n*dt));
        }
        else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
        {
            fprintf(fp, "@ s%d legend \"av %f\"\n", 2*s, av[s]);
            fprintf(fp, "@ s%d legend \"ee %6g\"\n", 2*s+1,
                    optimal_error_estimate(sig[s], fitparm, n*dt));
        }
        for (i = 0; i < nbs; i++)
        {
            fprintf(fp, "%g %g %g\n", tbs[i], sig[s]*std::sqrt(ybs[i]/(n*dt)),
                    sig[s]*std::sqrt(fit_function(effnERREST, fitparm, tbs[i])/(n*dt)));
        }

        if (bFitAc)
        {
            int    fitlen;
            real  *ac, acint;
            double ac_fit[4];

            snew(ac, n);
            for (i = 0; i < n; i++)
            {
                ac[i] = val[s][i] - av[s];
                if (i > 0)
                {
                    fitsig[i] = std::sqrt(static_cast<real>(i));
                }
                else
                {
                    fitsig[i] = 1;
                }
            }
            low_do_autocorr(NULL, oenv, NULL, n, 1, -1, &ac,
                            dt, eacNormal, 1, FALSE, TRUE,
                            FALSE, 0, 0, effnNONE);

            fitlen = n/nb_min;

            /* Integrate ACF only up to fitlen/2 to avoid integrating noise */
            acint = 0.5*ac[0];
            for (i = 1; i <= fitlen/2; i++)
            {
                acint += ac[i];
            }
            acint *= dt;

            /* Generate more or less appropriate sigma's */
            for (i = 0; i <= fitlen; i++)
            {
                fitsig[i] = std::sqrt(acint + dt*i);
            }

            ac_fit[0] = 0.5*acint;
            ac_fit[1] = 0.95;
            ac_fit[2] = 10*acint;
            do_lmfit(n/nb_min, ac, fitsig, dt, 0, 0, fitlen*dt, oenv,
                     bDebugMode(), effnEXPEXP, ac_fit, 0, NULL);
            ac_fit[3] = 1 - ac_fit[1];

            fprintf(stdout, "Set %3d:  ac erest %g  a %g  tau1 %g  tau2 %g\n",
                    s+1, optimal_error_estimate(sig[s], ac_fit, n*dt),
                    ac_fit[1], ac_fit[0], ac_fit[2]);

            fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            for (i = 0; i < nbs; i++)
            {
                fprintf(fp, "%g %g\n", tbs[i],
                        sig[s]*std::sqrt(fit_function(effnERREST, ac_fit, tbs[i]))/(n*dt));
            }

            sfree(ac);
        }
        if (s < nset-1)
        {
            fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        }
    }
    sfree(fitsig);
    sfree(ybs);
    sfree(tbs);
    xvgrclose(fp);
}
示例#11
0
int gmx_enemat(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] extracts an energy matrix from the energy file ([TT]-f[tt]).",
        "With [TT]-groups[tt] a file must be supplied with on each",
        "line a group of atoms to be used. For these groups matrix of",
        "interaction energies will be extracted from the energy file",
        "by looking for energy groups with names corresponding to pairs",
        "of groups of atoms, e.g. if your [TT]-groups[tt] file contains::",
        "",
        "    2",
        "    Protein",
        "    SOL",
        "",
        "then energy groups with names like 'Coul-SR:Protein-SOL' and ",
        "'LJ:Protein-SOL' are expected in the energy file (although",
        "[THISMODULE] is most useful if many groups are analyzed",
        "simultaneously). Matrices for different energy types are written",
        "out separately, as controlled by the",
        "[TT]-[no]coul[tt], [TT]-[no]coulr[tt], [TT]-[no]coul14[tt], ",
        "[TT]-[no]lj[tt], [TT]-[no]lj14[tt], ",
        "[TT]-[no]bham[tt] and [TT]-[no]free[tt] options.",
        "Finally, the total interaction energy energy per group can be ",
        "calculated ([TT]-etot[tt]).[PAR]",

        "An approximation of the free energy can be calculated using:",
        "[MATH]E[SUB]free[sub] = E[SUB]0[sub] + kT [LOG][CHEVRON][EXP](E-E[SUB]0[sub])/kT[exp][chevron][log][math], where '[MATH][CHEVRON][chevron][math]'",
        "stands for time-average. A file with reference free energies",
        "can be supplied to calculate the free energy difference",
        "with some reference state. Group names (e.g. residue names)",
        "in the reference file should correspond to the group names",
        "as used in the [TT]-groups[tt] file, but a appended number",
        "(e.g. residue number) in the [TT]-groups[tt] will be ignored",
        "in the comparison."
    };
    static gmx_bool bSum      = FALSE;
    static gmx_bool bMeanEmtx = TRUE;
    static int      skip      = 0, nlevels = 20;
    static real     cutmax    = 1e20, cutmin = -1e20, reftemp = 300.0;
    static gmx_bool bCoulSR   = TRUE, bCoul14 = FALSE;
    static gmx_bool bLJSR     = TRUE, bLJ14 = FALSE, bBhamSR = FALSE,
                    bFree     = TRUE;
    t_pargs         pa[]      = {
        { "-sum",  FALSE, etBOOL, {&bSum},
          "Sum the energy terms selected rather than display them all" },
        { "-skip", FALSE, etINT,  {&skip},
          "Skip number of frames between data points" },
        { "-mean", FALSE, etBOOL, {&bMeanEmtx},
          "with [TT]-groups[tt] extracts matrix of mean energies instead of "
          "matrix for each timestep" },
        { "-nlevels", FALSE, etINT, {&nlevels}, "number of levels for matrix colors"},
        { "-max", FALSE, etREAL, {&cutmax}, "max value for energies"},
        { "-min", FALSE, etREAL, {&cutmin}, "min value for energies"},
        { "-coulsr", FALSE, etBOOL, {&bCoulSR}, "extract Coulomb SR energies"},
        { "-coul14", FALSE, etBOOL, {&bCoul14}, "extract Coulomb 1-4 energies"},
        { "-ljsr", FALSE, etBOOL, {&bLJSR}, "extract Lennard-Jones SR energies"},
        { "-lj14", FALSE, etBOOL, {&bLJ14}, "extract Lennard-Jones 1-4 energies"},
        { "-bhamsr", FALSE, etBOOL, {&bBhamSR}, "extract Buckingham SR energies"},
        { "-free", FALSE, etBOOL, {&bFree}, "calculate free energy"},
        { "-temp", FALSE, etREAL, {&reftemp},
          "reference temperature for free energy calculation"}
    };
    /* We will define egSP more energy-groups:
       egTotal (total energy) */
#define egTotal egNR
#define egSP 1
    gmx_bool          egrp_use[egNR+egSP];
    ener_file_t       in;
    FILE             *out;
    int               timecheck = 0;
    gmx_enxnm_t      *enm       = NULL;
    t_enxframe       *fr;
    int               teller = 0;
    real              sum;
    gmx_bool          bCont, bRef;
    gmx_bool          bCutmax, bCutmin;
    real            **eneset, *time = NULL;
    int              *set, i, j, k, prevk, m = 0, n, nre, nset, nenergy;
    char            **groups = NULL;
    char              groupname[255], fn[255];
    int               ngroups;
    t_rgb             rlo, rhi, rmid;
    real              emax, emid, emin;
    real           ***emat, **etot, *groupnr;
    double            beta, expE, **e, *eaver, *efree = NULL, edum;
    char              label[234];
    char            **ereflines, **erefres = NULL;
    real             *eref  = NULL, *edif = NULL;
    int               neref = 0;
    gmx_output_env_t *oenv;

    t_filenm          fnm[] = {
        { efEDR, "-f", NULL, ffOPTRD },
        { efDAT, "-groups", "groups", ffREAD },
        { efDAT, "-eref",   "eref",   ffOPTRD },
        { efXPM, "-emat",   "emat",   ffWRITE },
        { efXVG, "-etot",   "energy", ffWRITE }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    for (i = 0; (i < egNR+egSP); i++)
    {
        egrp_use[i] = FALSE;
    }
    egrp_use[egCOULSR] = bCoulSR;
    egrp_use[egLJSR]   = bLJSR;
    egrp_use[egBHAMSR] = bBhamSR;
    egrp_use[egCOUL14] = bCoul14;
    egrp_use[egLJ14]   = bLJ14;
    egrp_use[egTotal]  = TRUE;

    bRef = opt2bSet("-eref", NFILE, fnm);
    in   = open_enx(ftp2fn(efEDR, NFILE, fnm), "r");
    do_enxnms(in, &nre, &enm);

    if (nre == 0)
    {
        gmx_fatal(FARGS, "No energies!\n");
    }

    bCutmax = opt2parg_bSet("-max", asize(pa), pa);
    bCutmin = opt2parg_bSet("-min", asize(pa), pa);

    nenergy = 0;

    /* Read groupnames from input file and construct selection of
       energy groups from it*/

    fprintf(stderr, "Will read groupnames from inputfile\n");
    ngroups = get_lines(opt2fn("-groups", NFILE, fnm), &groups);
    fprintf(stderr, "Read %d groups\n", ngroups);
    snew(set, static_cast<size_t>(gmx::square(ngroups)*egNR/2));
    n     = 0;
    prevk = 0;
    for (i = 0; (i < ngroups); i++)
    {
        fprintf(stderr, "\rgroup %d", i);
        for (j = i; (j < ngroups); j++)
        {
            for (m = 0; (m < egNR); m++)
            {
                if (egrp_use[m])
                {
                    sprintf(groupname, "%s:%s-%s", egrp_nm[m], groups[i], groups[j]);
#ifdef DEBUG
                    fprintf(stderr, "\r%-15s %5d", groupname, n);
#endif
                    for (k = prevk; (k < prevk+nre); k++)
                    {
                        if (std::strcmp(enm[k%nre].name, groupname) == 0)
                        {
                            set[n++] = k;
                            break;
                        }
                    }
                    if (k == prevk+nre)
                    {
                        fprintf(stderr, "WARNING! could not find group %s (%d,%d)"
                                "in energy file\n", groupname, i, j);
                    }
                    else
                    {
                        prevk = k;
                    }
                }
            }
        }
    }
    fprintf(stderr, "\n");
    nset = n;
    snew(eneset, nset+1);
    fprintf(stderr, "Will select half-matrix of energies with %d elements\n", n);

    /* Start reading energy frames */
    snew(fr, 1);
    do
    {
        do
        {
            bCont = do_enx(in, fr);
            if (bCont)
            {
                timecheck = check_times(fr->t);
            }
        }
        while (bCont && (timecheck < 0));

        if (timecheck == 0)
        {
#define DONTSKIP(cnt) (skip) ? ((cnt % skip) == 0) : TRUE

            if (bCont)
            {
                fprintf(stderr, "\rRead frame: %d, Time: %.3f", teller, fr->t);

                if ((nenergy % 1000) == 0)
                {
                    srenew(time, nenergy+1000);
                    for (i = 0; (i <= nset); i++)
                    {
                        srenew(eneset[i], nenergy+1000);
                    }
                }
                time[nenergy] = fr->t;
                sum           = 0;
                for (i = 0; (i < nset); i++)
                {
                    eneset[i][nenergy] = fr->ener[set[i]].e;
                    sum               += fr->ener[set[i]].e;
                }
                if (bSum)
                {
                    eneset[nset][nenergy] = sum;
                }
                nenergy++;
            }
            teller++;
        }
    }
    while (bCont && (timecheck == 0));

    fprintf(stderr, "\n");

    fprintf(stderr, "Will build energy half-matrix of %d groups, %d elements, "
            "over %d frames\n", ngroups, nset, nenergy);

    snew(emat, egNR+egSP);
    for (j = 0; (j < egNR+egSP); j++)
    {
        if (egrp_use[m])
        {
            snew(emat[j], ngroups);
            for (i = 0; (i < ngroups); i++)
            {
                snew(emat[j][i], ngroups);
            }
        }
    }
    snew(groupnr, ngroups);
    for (i = 0; (i < ngroups); i++)
    {
        groupnr[i] = i+1;
    }
    rlo.r  = 1.0, rlo.g  = 0.0, rlo.b  = 0.0;
    rmid.r = 1.0, rmid.g = 1.0, rmid.b = 1.0;
    rhi.r  = 0.0, rhi.g  = 0.0, rhi.b  = 1.0;
    if (bMeanEmtx)
    {
        snew(e, ngroups);
        for (i = 0; (i < ngroups); i++)
        {
            snew(e[i], nenergy);
        }
        n = 0;
        for (i = 0; (i < ngroups); i++)
        {
            for (j = i; (j < ngroups); j++)
            {
                for (m = 0; (m < egNR); m++)
                {
                    if (egrp_use[m])
                    {
                        for (k = 0; (k < nenergy); k++)
                        {
                            emat[m][i][j] += eneset[n][k];
                            e[i][k]       += eneset[n][k]; /* *0.5; */
                            e[j][k]       += eneset[n][k]; /* *0.5; */
                        }
                        n++;
                        emat[egTotal][i][j] += emat[m][i][j];
                        emat[m][i][j]       /= nenergy;
                        emat[m][j][i]        = emat[m][i][j];
                    }
                }
                emat[egTotal][i][j] /= nenergy;
                emat[egTotal][j][i]  = emat[egTotal][i][j];
            }
        }
        if (bFree)
        {
            if (bRef)
            {
                fprintf(stderr, "Will read reference energies from inputfile\n");
                neref = get_lines(opt2fn("-eref", NFILE, fnm), &ereflines);
                fprintf(stderr, "Read %d reference energies\n", neref);
                snew(eref, neref);
                snew(erefres, neref);
                for (i = 0; (i < neref); i++)
                {
                    snew(erefres[i], 5);
                    sscanf(ereflines[i], "%s %lf", erefres[i], &edum);
                    eref[i] = edum;
                }
            }
            snew(eaver, ngroups);
            for (i = 0; (i < ngroups); i++)
            {
                for (k = 0; (k < nenergy); k++)
                {
                    eaver[i] += e[i][k];
                }
                eaver[i] /= nenergy;
            }
            beta = 1.0/(BOLTZ*reftemp);
            snew(efree, ngroups);
            snew(edif, ngroups);
            for (i = 0; (i < ngroups); i++)
            {
                expE = 0;
                for (k = 0; (k < nenergy); k++)
                {
                    expE += std::exp(beta*(e[i][k]-eaver[i]));
                }
                efree[i] = std::log(expE/nenergy)/beta + eaver[i];
                if (bRef)
                {
                    n = search_str2(neref, erefres, groups[i]);
                    if (n != -1)
                    {
                        edif[i] = efree[i]-eref[n];
                    }
                    else
                    {
                        edif[i] = efree[i];
                        fprintf(stderr, "WARNING: group %s not found "
                                "in reference energies.\n", groups[i]);
                    }
                }
                else
                {
                    edif[i] = 0;
                }
            }
        }

        emid             = 0.0; /*(emin+emax)*0.5;*/
        egrp_nm[egTotal] = "total";
        for (m = 0; (m < egNR+egSP); m++)
        {
            if (egrp_use[m])
            {
                emin = 1e10;
                emax = -1e10;
                for (i = 0; (i < ngroups); i++)
                {
                    for (j = i; (j < ngroups); j++)
                    {
                        if (emat[m][i][j] > emax)
                        {
                            emax = emat[m][i][j];
                        }
                        else if (emat[m][i][j] < emin)
                        {
                            emin = emat[m][i][j];
                        }
                    }
                }
                if (emax == emin)
                {
                    fprintf(stderr, "Matrix of %s energy is uniform at %f "
                            "(will not produce output).\n", egrp_nm[m], emax);
                }
                else
                {
                    fprintf(stderr, "Matrix of %s energy ranges from %f to %f\n",
                            egrp_nm[m], emin, emax);
                    if ((bCutmax) || (emax > cutmax))
                    {
                        emax = cutmax;
                    }
                    if ((bCutmin) || (emin < cutmin))
                    {
                        emin = cutmin;
                    }
                    if ((emax == cutmax) || (emin == cutmin))
                    {
                        fprintf(stderr, "Energy range adjusted: %f to %f\n", emin, emax);
                    }

                    sprintf(fn, "%s%s", egrp_nm[m], ftp2fn(efXPM, NFILE, fnm));
                    sprintf(label, "%s Interaction Energies", egrp_nm[m]);
                    out = gmx_ffopen(fn, "w");
                    if (emin >= emid)
                    {
                        write_xpm(out, 0, label, "Energy (kJ/mol)",
                                  "Residue Index", "Residue Index",
                                  ngroups, ngroups, groupnr, groupnr, emat[m],
                                  emid, emax, rmid, rhi, &nlevels);
                    }
                    else if (emax <= emid)
                    {
                        write_xpm(out, 0, label, "Energy (kJ/mol)",
                                  "Residue Index", "Residue Index",
                                  ngroups, ngroups, groupnr, groupnr, emat[m],
                                  emin, emid, rlo, rmid, &nlevels);
                    }
                    else
                    {
                        write_xpm3(out, 0, label, "Energy (kJ/mol)",
                                   "Residue Index", "Residue Index",
                                   ngroups, ngroups, groupnr, groupnr, emat[m],
                                   emin, emid, emax, rlo, rmid, rhi, &nlevels);
                    }
                    gmx_ffclose(out);
                }
            }
        }
        snew(etot, egNR+egSP);
        for (m = 0; (m < egNR+egSP); m++)
        {
            snew(etot[m], ngroups);
            for (i = 0; (i < ngroups); i++)
            {
                for (j = 0; (j < ngroups); j++)
                {
                    etot[m][i] += emat[m][i][j];
                }
            }
        }

        out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Mean Energy", "Residue", "kJ/mol",
                       oenv);
        xvgr_legend(out, 0, NULL, oenv);
        j = 0;
        if (output_env_get_print_xvgr_codes(oenv))
        {
            char str1[STRLEN], str2[STRLEN];
            if (output_env_get_xvg_format(oenv) == exvgXMGR)
            {
                sprintf(str1, "@ legend string ");
                sprintf(str2, " ");
            }
            else
            {
                sprintf(str1, "@ s");
                sprintf(str2, " legend ");
            }

            for (m = 0; (m < egNR+egSP); m++)
            {
                if (egrp_use[m])
                {
                    fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, egrp_nm[m]);
                }
            }
            if (bFree)
            {
                fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Free");
            }
            if (bFree)
            {
                fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Diff");
            }
            fprintf(out, "@TYPE xy\n");
            fprintf(out, "#%3s", "grp");

            for (m = 0; (m < egNR+egSP); m++)
            {
                if (egrp_use[m])
                {
                    fprintf(out, " %9s", egrp_nm[m]);
                }
            }
            if (bFree)
            {
                fprintf(out, " %9s", "Free");
            }
            if (bFree)
            {
                fprintf(out, " %9s", "Diff");
            }
            fprintf(out, "\n");
        }
        for (i = 0; (i < ngroups); i++)
        {
            fprintf(out, "%3.0f", groupnr[i]);
            for (m = 0; (m < egNR+egSP); m++)
            {
                if (egrp_use[m])
                {
                    fprintf(out, " %9.5g", etot[m][i]);
                }
            }
            if (bFree)
            {
                fprintf(out, " %9.5g", efree[i]);
            }
            if (bRef)
            {
                fprintf(out, " %9.5g", edif[i]);
            }
            fprintf(out, "\n");
        }
        xvgrclose(out);
    }
    else
    {
        fprintf(stderr, "While typing at your keyboard, suddenly...\n"
                "...nothing happens.\nWARNING: Not Implemented Yet\n");
/*
    out=ftp2FILE(efMAT,NFILE,fnm,"w");
    n=0;
    emin=emax=0.0;
    for (k=0; (k<nenergy); k++) {
      for (i=0; (i<ngroups); i++)
    for (j=i+1; (j<ngroups); j++)
      emat[i][j]=eneset[n][k];
      sprintf(label,"t=%.0f ps",time[k]);
      write_matrix(out,ngroups,1,ngroups,groupnr,emat,label,emin,emax,nlevels);
      n++;
    }
    gmx_ffclose(out);
 */
    }
    close_enx(in);

    return 0;
}
示例#12
0
文件: xvgr.c 项目: alwanderer/gromacs
static char *xvgrstr(const char *gmx, const output_env_t oenv,
                     char *buf, int buflen)
{
    /* Supported greek letter names and corresponding xmgrace/xmgr symbols */
    const char *sym[]  = { "beta", "chi", "delta", "eta", "lambda", "mu", "omega", "phi", "psi", "rho", "theta", NULL };
    const char  symc[] = { 'b',    'c',   'd',     'h',   'l',      'm',  'w',     'f',   'y',   'r',   'q',     '\0' };
    int         xvgf;
    gmx_bool    bXVGR;
    int         g, b, i;
    char        c;

    xvgf  = output_env_get_xvg_format(oenv);
    bXVGR = (xvgf == exvgXMGRACE || xvgf == exvgXMGR);

    g = 0;
    b = 0;
    while (gmx[g] != '\0')
    {
        /* Check with the largest string we have ("lambda"), add one for \0 */
        if (b + 6 + 1 >= buflen)
        {
            gmx_fatal(FARGS, "Output buffer length in xvgstr (%d) too small to process xvg input string '%s'", buflen, gmx);
        }
        if (gmx[g] == '\\')
        {
            g++;
            if (gmx[g] == 's')
            {
                /* Subscript */
                if (bXVGR)
                {
                    buf[b++] = '\\';
                    buf[b++] = 's';
                }
                else
                {
                    buf[b++] = '_';
                }
                g++;
            }
            else if (gmx[g] == 'S')
            {
                /* Superscript */
                if (bXVGR)
                {
                    buf[b++] = '\\';
                    buf[b++] = 'S';
                }
                else
                {
                    buf[b++] = '^';
                }
                g++;
            }
            else if (gmx[g] == 'N')
            {
                /* End sub/superscript */
                if (bXVGR)
                {
                    buf[b++] = '\\';
                    buf[b++] = 'N';
                }
                else
                {
                    if (gmx[g+1] != ' ')
                    {
                        buf[b++] = ' ';
                    }
                }
                g++;
            }
            else if (gmx[g] == '4')
            {
                /* Backward compatibility for xmgr normal font "\4" */
                switch (xvgf)
                {
                    case exvgXMGRACE:
                        sprintf(buf+b, "%s", "\\f{}");
                        break;
                    case exvgXMGR:
                        sprintf(buf+b, "%s", "\\4");
                        break;
                    default:
                        buf[b] = '\0';
                        break;
                }
                g++;
                b = strlen(buf);
            }
            else if (gmx[g] == '8')
            {
                /* Backward compatibility for xmgr symbol font "\8" */
                switch (xvgf)
                {
                    case exvgXMGRACE:
                        sprintf(buf+b, "%s", "\\x");
                        break;
                    case exvgXMGR:
                        sprintf(buf+b, "%s", "\\8");
                        break;
                    default:
                        buf[b] = '\0';
                        break;
                }
                g++;
                b = strlen(buf);
            }
            else
            {
                /* Check for special symbol */
                i = 0;
                while (sym[i] != NULL &&
                       gmx_strncasecmp(sym[i], gmx+g, strlen(sym[i])) != 0)
                {
                    i++;
                }
                if (sym[i] != NULL)
                {
                    c = symc[i];
                    if (isupper(gmx[g]))
                    {
                        c = toupper(c);
                    }
                    switch (xvgf)
                    {
                        case exvgXMGRACE:
                            sprintf(buf+b, "%s%c%s", "\\x", c, "\\f{}");
                            break;
                        case exvgXMGR:
                            sprintf(buf+b, "%s%c%s", "\\8", c, "\\4");
                            break;
                        default:
                            strncat(buf+b, gmx+g, strlen(sym[i]));
                            b += strlen(sym[i]);
                            if (gmx[g+strlen(sym[i])] != ' ')
                            {
                                buf[b++] = ' ';
                            }
                            buf[b] = '\0';
                            break;
                    }
                    g += strlen(sym[i]);
                    b  = strlen(buf);
                }
                else
                {
                    /* Unknown escape sequence, this should not happen.
                     * We do not generate a fatal error, since that might
                     * stop otherwise functioning code from working.
                     * Copy the backslash to the output and continue processing.
                     */
                    buf[b++] = '\\';
                }
            }
        }
        else
        {
            buf[b++] = gmx[g++];
        }
    }

    buf[b++] = '\0';

    return buf;
}