Example #1
0
void xvgr_new_dataset(FILE *out, int nr_first, int nsets,
                      const char **setname,
                      const 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");
    }
}
Example #2
0
void xvgr_legend(FILE *out, int nsets, const char** setname,
                 const 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));
                }
            }
        }
    }
}
Example #3
0
void histogram(const char *distfile, real binwidth, int n, int nset, real **val,
               const gmx_output_env_t *oenv)
{
    FILE          *fp;
    int            i, s;
    double         minval, maxval;
    int            nbin;
    gmx_int64_t   *histo;

    minval = val[0][0];
    maxval = val[0][0];
    for (s = 0; s < nset; s++)
    {
        for (i = 0; i < n; i++)
        {
            if (val[s][i] < minval)
            {
                minval = val[s][i];
            }
            else if (val[s][i] > maxval)
            {
                maxval = val[s][i];
            }
        }
    }

    minval = binwidth*std::floor(minval/binwidth);
    maxval = binwidth*std::ceil(maxval/binwidth);
    if (minval != 0)
    {
        minval -= binwidth;
    }
    maxval += binwidth;

    nbin = static_cast<int>(((maxval - minval)/binwidth + 0.5) + 1);
    fprintf(stderr, "Making distributions with %d bins\n", nbin);
    snew(histo, nbin);
    fp = xvgropen(distfile, "Distribution", "", "", oenv);
    for (s = 0; s < nset; s++)
    {
        for (i = 0; i < nbin; i++)
        {
            histo[i] = 0;
        }
        for (i = 0; i < n; i++)
        {
            histo[static_cast<int>((val[s][i] - minval)/binwidth + 0.5)]++;
        }
        for (i = 0; i < nbin; i++)
        {
            fprintf(fp, " %g  %g\n", minval+i*binwidth, static_cast<double>(histo[i])/(n*binwidth));
        }
        if (s < nset-1)
        {
            fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        }
    }
    xvgrclose(fp);
}
Example #4
0
void histogram(const char *distfile, real binwidth, int n, int nset, real **val,
               const output_env_t oenv)
{
    FILE          *fp;
    int            i, s;
    double         min, max;
    int            nbin;
    gmx_int64_t   *histo;

    min = val[0][0];
    max = val[0][0];
    for (s = 0; s < nset; s++)
    {
        for (i = 0; i < n; i++)
        {
            if (val[s][i] < min)
            {
                min = val[s][i];
            }
            else if (val[s][i] > max)
            {
                max = val[s][i];
            }
        }
    }

    min = binwidth*floor(min/binwidth);
    max = binwidth*ceil(max/binwidth);
    if (min != 0)
    {
        min -= binwidth;
    }
    max += binwidth;

    nbin = (int)((max - min)/binwidth + 0.5) + 1;
    fprintf(stderr, "Making distributions with %d bins\n", nbin);
    snew(histo, nbin);
    fp = xvgropen(distfile, "Distribution", "", "", oenv);
    for (s = 0; s < nset; s++)
    {
        for (i = 0; i < nbin; i++)
        {
            histo[i] = 0;
        }
        for (i = 0; i < n; i++)
        {
            histo[(int)((val[s][i] - min)/binwidth + 0.5)]++;
        }
        for (i = 0; i < nbin; i++)
        {
            fprintf(fp, " %g  %g\n", min+i*binwidth, (double)histo[i]/(n*binwidth));
        }
        if (s < nset-1)
        {
            fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        }
    }
    gmx_ffclose(fp);
}
Example #5
0
void xvgr_view(FILE *out, real xmin, real ymin, real xmax, real ymax,
               const output_env_t oenv)
{
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@ view %g, %g, %g, %g\n", xmin, ymin, xmax, ymax);
    }
}
Example #6
0
void xvgr_subtitle(FILE *out, const char *subtitle, const output_env_t oenv)
{
    char buf[STRLEN];

    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@ subtitle \"%s\"\n", xvgrstr(subtitle, oenv, buf, STRLEN));
    }
}
Example #7
0
void xvgr_line_props(FILE *out, int NrSet, int LineStyle, int LineColor,
                     const output_env_t oenv)
{
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@    with g0\n");
        fprintf(out, "@    s%d linestyle %d\n", NrSet, LineStyle);
        fprintf(out, "@    s%d color %d\n", NrSet, LineColor);
    }
}
Example #8
0
void xvgr_world(FILE *out, real xmin, real ymin, real xmax, real ymax,
                const output_env_t oenv)
{
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@ world xmin %g\n"
                "@ world ymin %g\n"
                "@ world xmax %g\n"
                "@ world ymax %g\n", xmin, ymin, xmax, ymax);
    }
}
Example #9
0
void
AbstractPlotModule::dataStarted(AbstractAnalysisData * /* data */)
{
    if (!impl_->filename_.empty())
    {
        if (impl_->bPlain_)
        {
            impl_->fp_ = gmx_fio_fopen(impl_->filename_.c_str(), "w");
        }
        else
        {
            time_unit_t  time_unit
                = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1);
            xvg_format_t xvg_format
                = (impl_->settings_.plotFormat() > 0
                   ? static_cast<xvg_format_t>(impl_->settings_.plotFormat())
                   : exvgNONE);
            output_env_t                  oenv;
            output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0);
            boost::shared_ptr<output_env> oenvGuard(oenv, &output_env_done);
            impl_->fp_ = xvgropen(impl_->filename_.c_str(), impl_->title_.c_str(),
                                  impl_->xlabel_.c_str(), impl_->ylabel_.c_str(),
                                  oenv);
            const SelectionCollection *selections
                = impl_->settings_.selectionCollection();
            if (selections != NULL)
            {
                selections->printXvgrInfo(impl_->fp_, oenv);
            }
            if (!impl_->subtitle_.empty())
            {
                xvgr_subtitle(impl_->fp_, impl_->subtitle_.c_str(), oenv);
            }
            if (output_env_get_print_xvgr_codes(oenv)
                && !impl_->legend_.empty())
            {
                std::vector<const char *> legend;
                legend.reserve(impl_->legend_.size());
                for (size_t i = 0; i < impl_->legend_.size(); ++i)
                {
                    legend.push_back(impl_->legend_[i].c_str());
                }
                xvgr_legend(impl_->fp_, legend.size(), &legend[0], oenv);
            }
        }
    }
}
Example #10
0
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;
        }
    }
}
Example #11
0
void xvgr_box(FILE *out,
              int LocType,
              real xmin, real ymin, real xmax, real ymax,
              int LineStyle, int LineWidth, int LineColor,
              int BoxFill, int BoxColor, int BoxPattern, const output_env_t oenv)
{
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@with box\n");
        fprintf(out, "@    box on\n");
        fprintf(out, "@    box loctype %s\n", LocTypeStr[LocType]);
        fprintf(out, "@    box %g, %g, %g, %g\n", xmin, ymin, xmax, ymax);
        fprintf(out, "@    box linestyle %d\n", LineStyle);
        fprintf(out, "@    box linewidth %d\n", LineWidth);
        fprintf(out, "@    box color %d\n", LineColor);
        fprintf(out, "@    box fill %s\n", BoxFillStr[BoxFill]);
        fprintf(out, "@    box fill color %d\n", BoxColor);
        fprintf(out, "@    box fill pattern %d\n", BoxPattern);
        fprintf(out, "@box def\n");
    }
}
Example #12
0
int gmx_g_angle(int argc, char *argv[])
{
    static const char *desc[] = {
        "[TT]g_angle[tt] computes the angle distribution for a number of angles",
        "or dihedrals.[PAR]",
        "With option [TT]-ov[tt], you can plot the average angle of",
        "a group of angles as a function of time. With the [TT]-all[tt] option,",
        "the first graph is the average and the rest are the individual angles.[PAR]",
        "With the [TT]-of[tt] option, [TT]g_angle[tt] also calculates the fraction of trans",
        "dihedrals (only for dihedrals) as function of time, but this is",
        "probably only fun for a select few.[PAR]",
        "With option [TT]-oc[tt], a dihedral correlation function is calculated.[PAR]",
        "It should be noted that the index file must contain",
        "atom triplets for angles or atom quadruplets for dihedrals.",
        "If this is not the case, the program will crash.[PAR]",
        "With option [TT]-or[tt], a trajectory file is dumped containing cos and",
        "sin of selected dihedral angles, which subsequently can be used as",
        "input for a principal components analysis using [TT]g_covar[tt].[PAR]",
        "Option [TT]-ot[tt] plots when transitions occur between",
        "dihedral rotamers of multiplicity 3 and [TT]-oh[tt]",
        "records a histogram of the times between such transitions,",
        "assuming the input trajectory frames are equally spaced in time."
    };
    static const char *opt[]    = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
    static gmx_bool    bALL     = FALSE, bChandler = FALSE, bAverCorr = FALSE, bPBC = TRUE;
    static real        binwidth = 1;
    t_pargs            pa[]     = {
        {   "-type", FALSE, etENUM, {opt},
            "Type of angle to analyse"
        },
        {   "-all",    FALSE,  etBOOL, {&bALL},
            "Plot all angles separately in the averages file, in the order of appearance in the index file."
        },
        {   "-binwidth", FALSE, etREAL, {&binwidth},
            "binwidth (degrees) for calculating the distribution"
        },
        {   "-periodic", FALSE, etBOOL, {&bPBC},
            "Print dihedral angles modulo 360 degrees"
        },
        {   "-chandler", FALSE,  etBOOL, {&bChandler},
            "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 or phi > 60."
        },
        {   "-avercorr", FALSE,  etBOOL, {&bAverCorr},
            "Average the correlation functions for the individual angles/dihedrals"
        }
    };
    static const char *bugs[] = {
        "Counting transitions only works for dihedrals with multiplicity 3"
    };

    FILE              *out;
    real               tmp, dt;
    int                status, isize;
    atom_id           *index;
    char              *grpname;
    real               maxang, Jc, S2, norm_fac, maxstat;
    unsigned long      mode;
    int                nframes, maxangstat, mult, *angstat;
    int                i, j, total, nangles, natoms, nat2, first, last, angind;
    gmx_bool           bAver, bRb, bPeriodic,
                       bFrac,                           /* calculate fraction too?  */
                       bTrans,                          /* worry about transtions too? */
                       bCorr;                           /* correlation function ? */
    real         t, aa, aver, aver2, aversig, fraction; /* fraction trans dihedrals */
    double       tfrac = 0;
    char         title[256];
    real       **dih = NULL;      /* mega array with all dih. angles at all times*/
    char         buf[80];
    real        *time, *trans_frac, *aver_angle;
    t_filenm     fnm[] = {
        { efTRX, "-f", NULL,  ffREAD  },
        { efNDX, NULL, "angle",  ffREAD  },
        { efXVG, "-od", "angdist",  ffWRITE },
        { efXVG, "-ov", "angaver",  ffOPTWR },
        { efXVG, "-of", "dihfrac",  ffOPTWR },
        { efXVG, "-ot", "dihtrans", ffOPTWR },
        { efXVG, "-oh", "trhisto",  ffOPTWR },
        { efXVG, "-oc", "dihcorr",  ffOPTWR },
        { efTRR, "-or", NULL,       ffOPTWR }
    };
#define NFILE asize(fnm)
    int          npargs;
    t_pargs     *ppa;
    output_env_t oenv;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs,
                      &oenv);

    mult   = 4;
    maxang = 360.0;
    bRb    = FALSE;
    switch (opt[0][0])
    {
    case 'a':
        mult   = 3;
        maxang = 180.0;
        break;
    case 'd':
        break;
    case 'i':
        break;
    case 'r':
        bRb = TRUE;
        break;
    }

    if (opt2bSet("-or", NFILE, fnm))
    {
        if (mult != 4)
        {
            gmx_fatal(FARGS, "Can not combine angles with trn dump");
        }
        else
        {
            please_cite(stdout, "Mu2005a");
        }
    }

    /* Calculate bin size */
    maxangstat = (int)(maxang/binwidth+0.5);
    binwidth   = maxang/maxangstat;

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
    nangles = isize/mult;
    if ((isize % mult) != 0)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of %d, "
                  "these can not be %s\n",
                  mult, (mult == 3) ? "angle triplets" : "dihedral quadruplets");
    }


    /* Check whether specific analysis has to be performed */
    bCorr  = opt2bSet("-oc", NFILE, fnm);
    bAver  = opt2bSet("-ov", NFILE, fnm);
    bTrans = opt2bSet("-ot", NFILE, fnm);
    bFrac  = opt2bSet("-of", NFILE, fnm);
    if (bTrans && opt[0][0] != 'd')
    {
        fprintf(stderr, "Option -ot should only accompany -type dihedral. Disabling -ot.\n");
        bTrans = FALSE;
    }

    if (bChandler && !bCorr)
    {
        bCorr = TRUE;
    }

    if (bFrac && !bRb)
    {
        fprintf(stderr, "Warning:"
                " calculating fractions as defined in this program\n"
                "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n");
        bFrac = FALSE;
    }

    if ( (bTrans || bFrac || bCorr) && mult == 3)
    {
        gmx_fatal(FARGS, "Can only do transition, fraction or correlation\n"
                  "on dihedrals. Select -d\n");
    }

    /*
     * We need to know the nr of frames so we can allocate memory for an array
     * with all dihedral angles at all timesteps. Works for me.
     */
    if (bTrans || bCorr  || bALL || opt2bSet("-or", NFILE, fnm))
    {
        snew(dih, nangles);
    }

    snew(angstat, maxangstat);

    read_ang_dih(ftp2fn(efTRX, NFILE, fnm), (mult == 3),
                 bALL || bCorr || bTrans || opt2bSet("-or", NFILE, fnm),
                 bRb, bPBC, maxangstat, angstat,
                 &nframes, &time, isize, index, &trans_frac, &aver_angle, dih,
                 oenv);

    dt = (time[nframes-1]-time[0])/(nframes-1);

    if (bAver)
    {
        sprintf(title, "Average Angle: %s", grpname);
        out = xvgropen(opt2fn("-ov", NFILE, fnm),
                       title, "Time (ps)", "Angle (degrees)", oenv);
        for (i = 0; (i < nframes); i++)
        {
            fprintf(out, "%10.5f  %8.3f", time[i], aver_angle[i]*RAD2DEG);
            if (bALL)
            {
                for (j = 0; (j < nangles); j++)
                {
                    if (bPBC)
                    {
                        real dd = dih[j][i];
                        fprintf(out, "  %8.3f", atan2(sin(dd), cos(dd))*RAD2DEG);
                    }
                    else
                    {
                        fprintf(out, "  %8.3f", dih[j][i]*RAD2DEG);
                    }
                }
            }
            fprintf(out, "\n");
        }
        ffclose(out);
    }
    if (opt2bSet("-or", NFILE, fnm))
    {
        dump_dih_trn(nframes, nangles, dih, opt2fn("-or", NFILE, fnm), time);
    }

    if (bFrac)
    {
        sprintf(title, "Trans fraction: %s", grpname);
        out = xvgropen(opt2fn("-of", NFILE, fnm),
                       title, "Time (ps)", "Fraction", oenv);
        tfrac = 0.0;
        for (i = 0; (i < nframes); i++)
        {
            fprintf(out, "%10.5f  %10.3f\n", time[i], trans_frac[i]);
            tfrac += trans_frac[i];
        }
        ffclose(out);

        tfrac /= nframes;
        fprintf(stderr, "Average trans fraction: %g\n", tfrac);
    }
    sfree(trans_frac);

    if (bTrans)
    {
        ana_dih_trans(opt2fn("-ot", NFILE, fnm), opt2fn("-oh", NFILE, fnm),
                      dih, nframes, nangles, grpname, time, bRb, oenv);
    }

    if (bCorr)
    {
        /* Autocorrelation function */
        if (nframes < 2)
        {
            fprintf(stderr, "Not enough frames for correlation function\n");
        }
        else
        {

            if (bChandler)
            {
                real     dval, sixty = DEG2RAD*60;
                gmx_bool bTest;

                for (i = 0; (i < nangles); i++)
                {
                    for (j = 0; (j < nframes); j++)
                    {
                        dval = dih[i][j];
                        if (bRb)
                        {
                            bTest = (dval > -sixty) && (dval < sixty);
                        }
                        else
                        {
                            bTest = (dval < -sixty) || (dval > sixty);
                        }
                        if (bTest)
                        {
                            dih[i][j] = dval-tfrac;
                        }
                        else
                        {
                            dih[i][j] = -tfrac;
                        }
                    }
                }
            }
            if (bChandler)
            {
                mode = eacNormal;
            }
            else
            {
                mode = eacCos;
            }
            do_autocorr(opt2fn("-oc", NFILE, fnm), oenv,
                        "Dihedral Autocorrelation Function",
                        nframes, nangles, dih, dt, mode, bAverCorr);
        }
    }


    /* Determine the non-zero part of the distribution */
    for (first = 0; (first < maxangstat-1) && (angstat[first+1] == 0); first++)
    {
        ;
    }
    for (last = maxangstat-1; (last > 0) && (angstat[last-1] == 0); last--)
    {
        ;
    }

    aver = aver2 = 0;
    for (i = 0; (i < nframes); i++)
    {
        aver  += RAD2DEG*aver_angle[i];
        aver2 += sqr(RAD2DEG*aver_angle[i]);
    }
    aver   /= (real) nframes;
    aver2  /= (real) nframes;
    aversig = sqrt(aver2-sqr(aver));
    printf("Found points in the range from %d to %d (max %d)\n",
           first, last, maxangstat);
    printf(" < angle >  = %g\n", aver);
    printf("< angle^2 > = %g\n", aver2);
    printf("Std. Dev.   = %g\n", aversig);

    if (mult == 3)
    {
        sprintf(title, "Angle Distribution: %s", grpname);
    }
    else
    {
        sprintf(title, "Dihedral Distribution: %s", grpname);

        calc_distribution_props(maxangstat, angstat, -180.0, 0, NULL, &S2);
        fprintf(stderr, "Order parameter S^2 = %g\n", S2);
    }

    bPeriodic = (mult == 4) && (first == 0) && (last == maxangstat-1);

    out = xvgropen(opt2fn("-od", NFILE, fnm), title, "Degrees", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@    subtitle \"average angle: %g\\So\\N\"\n", aver);
    }
    norm_fac = 1.0/(nangles*nframes*binwidth);
    if (bPeriodic)
    {
        maxstat = 0;
        for (i = first; (i <= last); i++)
        {
            maxstat = max(maxstat, angstat[i]*norm_fac);
        }
        fprintf(out, "@with g0\n");
        fprintf(out, "@    world xmin -180\n");
        fprintf(out, "@    world xmax  180\n");
        fprintf(out, "@    world ymin 0\n");
        fprintf(out, "@    world ymax %g\n", maxstat*1.05);
        fprintf(out, "@    xaxis  tick major 60\n");
        fprintf(out, "@    xaxis  tick minor 30\n");
        fprintf(out, "@    yaxis  tick major 0.005\n");
        fprintf(out, "@    yaxis  tick minor 0.0025\n");
    }
    for (i = first; (i <= last); i++)
    {
        fprintf(out, "%10g  %10f\n", i*binwidth+180.0-maxang, angstat[i]*norm_fac);
    }
    if (bPeriodic)
    {
        /* print first bin again as last one */
        fprintf(out, "%10g  %10f\n", 180.0, angstat[0]*norm_fac);
    }

    ffclose(out);

    do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy");
    if (bAver)
    {
        do_view(oenv, opt2fn("-ov", NFILE, fnm), "-nxy");
    }

    thanx(stderr);

    return 0;
}
Example #13
0
int gmx_nmeig(int argc, char *argv[])
{
    const char            *desc[] = {
        "[TT]g_nmeig[tt] calculates the eigenvectors/values of a (Hessian) matrix,",
        "which can be calculated with [TT]mdrun[tt].",
        "The eigenvectors are written to a trajectory file ([TT]-v[tt]).",
        "The structure is written first with t=0. The eigenvectors",
        "are written as frames with the eigenvector number as timestamp.",
        "The eigenvectors can be analyzed with [TT]g_anaeig[tt].",
        "An ensemble of structures can be generated from the eigenvectors with",
        "[TT]g_nmens[tt]. When mass weighting is used, the generated eigenvectors",
        "will be scaled back to plain Cartesian coordinates before generating the",
        "output. In this case, they will no longer be exactly orthogonal in the",
        "standard Cartesian norm, but in the mass-weighted norm they would be.[PAR]",
        "This program can be optionally used to compute quantum corrections to heat capacity",
        "and enthalpy by providing an extra file argument [TT]-qcorr[tt]. See the GROMACS",
        "manual, Chapter 1, for details. The result includes subtracting a harmonic",
        "degree of freedom at the given temperature.",
        "The total correction is printed on the terminal screen.",
        "The recommended way of getting the corrections out is:[PAR]",
        "[TT]g_nmeig -s topol.tpr -f nm.mtx -first 7 -last 10000 -T 300 -qc [-constr][tt][PAR]",
        "The [TT]-constr[tt] option should be used when bond constraints were used during the",
        "simulation [BB]for all the covalent bonds[bb]. If this is not the case, ",
        "you need to analyze the [TT]quant_corr.xvg[tt] file yourself.[PAR]",
        "To make things more flexible, the program can also take virtual sites into account",
        "when computing quantum corrections. When selecting [TT]-constr[tt] and",
        "[TT]-qc[tt], the [TT]-begin[tt] and [TT]-end[tt] options will be set automatically as well.",
        "Again, if you think you know it better, please check the [TT]eigenfreq.xvg[tt]",
        "output."
    };

    static gmx_bool        bM    = TRUE, bCons = FALSE;
    static int             begin = 1, end = 50, maxspec = 4000;
    static real            T     = 298.15, width = 1;
    t_pargs                pa[]  =
    {
        { "-m",  FALSE, etBOOL, {&bM},
          "Divide elements of Hessian by product of sqrt(mass) of involved "
          "atoms prior to diagonalization. This should be used for 'Normal Modes' "
          "analysis" },
        { "-first", FALSE, etINT, {&begin},
          "First eigenvector to write away" },
        { "-last",  FALSE, etINT, {&end},
          "Last eigenvector to write away" },
        { "-maxspec", FALSE, etINT, {&maxspec},
          "Highest frequency (1/cm) to consider in the spectrum" },
        { "-T",     FALSE, etREAL, {&T},
          "Temperature for computing quantum heat capacity and enthalpy when using normal mode calculations to correct classical simulations" },
        { "-constr", FALSE, etBOOL, {&bCons},
          "If constraints were used in the simulation but not in the normal mode analysis (this is the recommended way of doing it) you will need to set this for computing the quantum corrections." },
        { "-width",  FALSE, etREAL, {&width},
          "Width (sigma) of the gaussian peaks (1/cm) when generating a spectrum" }
    };
    FILE                  *out, *qc, *spec;
    int                    status, trjout;
    t_topology             top;
    gmx_mtop_t             mtop;
    int                    ePBC;
    rvec                  *top_x;
    matrix                 box;
    real                  *eigenvalues;
    real                  *eigenvectors;
    real                   rdum, mass_fac, qcvtot, qutot, qcv, qu;
    int                    natoms, ndim, nrow, ncol, count, nharm, nvsite;
    char                  *grpname;
    int                    i, j, k, l, d, gnx;
    gmx_bool               bSuck;
    atom_id               *index;
    t_tpxheader            tpx;
    int                    version, generation;
    real                   value, omega, nu;
    real                   factor_gmx_to_omega2;
    real                   factor_omega_to_wavenumber;
    real                  *spectrum = NULL;
    real                   wfac;
    output_env_t           oenv;
    const char            *qcleg[] = {
        "Heat Capacity cV (J/mol K)",
        "Enthalpy H (kJ/mol)"
    };
    real *                 full_hessian   = NULL;
    gmx_sparsematrix_t *   sparse_hessian = NULL;

    t_filenm               fnm[] = {
        { efMTX, "-f", "hessian",    ffREAD  },
        { efTPX, NULL, NULL,         ffREAD  },
        { efXVG, "-of", "eigenfreq", ffWRITE },
        { efXVG, "-ol", "eigenval",  ffWRITE },
        { efXVG, "-os", "spectrum",  ffOPTWR },
        { efXVG, "-qc", "quant_corr",  ffOPTWR },
        { efTRN, "-v", "eigenvec",  ffWRITE }
    };
#define NFILE asize(fnm)

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

    /* Read tpr file for volume and number of harmonic terms */
    read_tpxheader(ftp2fn(efTPX, NFILE, fnm), &tpx, TRUE, &version, &generation);
    snew(top_x, tpx.natoms);

    read_tpx(ftp2fn(efTPX, NFILE, fnm), NULL, box, &natoms,
             top_x, NULL, NULL, &mtop);
    if (bCons)
    {
        nharm = get_nharm(&mtop, &nvsite);
    }
    else
    {
        nharm  = 0;
        nvsite = 0;
    }
    top = gmx_mtop_t_to_t_topology(&mtop);

    bM   = TRUE;
    ndim = DIM*natoms;

    if (opt2bSet("-qc", NFILE, fnm))
    {
        begin = 7+DIM*nvsite;
        end   = DIM*natoms;
    }
    if (begin < 1)
    {
        begin = 1;
    }
    if (end > ndim)
    {
        end = ndim;
    }
    printf("Using begin = %d and end = %d\n", begin, end);

    /*open Hessian matrix */
    gmx_mtxio_read(ftp2fn(efMTX, NFILE, fnm), &nrow, &ncol, &full_hessian, &sparse_hessian);

    /* Memory for eigenvalues and eigenvectors (begin..end) */
    snew(eigenvalues, nrow);
    snew(eigenvectors, nrow*(end-begin+1));

    /* If the Hessian is in sparse format we can calculate max (ndim-1) eigenvectors,
     * and they must start at the first one. If this is not valid we convert to full matrix
     * storage, but warn the user that we might run out of memory...
     */
    if ((sparse_hessian != NULL) && (begin != 1 || end == ndim))
    {
        if (begin != 1)
        {
            fprintf(stderr, "Cannot use sparse Hessian with first eigenvector != 1.\n");
        }
        else if (end == ndim)
        {
            fprintf(stderr, "Cannot use sparse Hessian to calculate all eigenvectors.\n");
        }

        fprintf(stderr, "Will try to allocate memory and convert to full matrix representation...\n");

        snew(full_hessian, nrow*ncol);
        for (i = 0; i < nrow*ncol; i++)
        {
            full_hessian[i] = 0;
        }

        for (i = 0; i < sparse_hessian->nrow; i++)
        {
            for (j = 0; j < sparse_hessian->ndata[i]; j++)
            {
                k                      = sparse_hessian->data[i][j].col;
                value                  = sparse_hessian->data[i][j].value;
                full_hessian[i*ndim+k] = value;
                full_hessian[k*ndim+i] = value;
            }
        }
        gmx_sparsematrix_destroy(sparse_hessian);
        sparse_hessian = NULL;
        fprintf(stderr, "Converted sparse to full matrix storage.\n");
    }

    if (full_hessian != NULL)
    {
        /* Using full matrix storage */
        nma_full_hessian(full_hessian, nrow, bM, &top, begin, end,
                         eigenvalues, eigenvectors);
    }
    else
    {
        /* Sparse memory storage, allocate memory for eigenvectors */
        snew(eigenvectors, ncol*end);
        nma_sparse_hessian(sparse_hessian, bM, &top, end, eigenvalues, eigenvectors);
    }

    /* check the output, first 6 eigenvalues should be reasonably small */
    bSuck = FALSE;
    for (i = begin-1; (i < 6); i++)
    {
        if (fabs(eigenvalues[i]) > 1.0e-3)
        {
            bSuck = TRUE;
        }
    }
    if (bSuck)
    {
        fprintf(stderr, "\nOne of the lowest 6 eigenvalues has a non-zero value.\n");
        fprintf(stderr, "This could mean that the reference structure was not\n");
        fprintf(stderr, "properly energy minimized.\n");
    }

    /* now write the output */
    fprintf (stderr, "Writing eigenvalues...\n");
    out = xvgropen(opt2fn("-ol", NFILE, fnm),
                   "Eigenvalues", "Eigenvalue index", "Eigenvalue [Gromacs units]",
                   oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        if (bM)
        {
            fprintf(out, "@ subtitle \"mass weighted\"\n");
        }
        else
        {
            fprintf(out, "@ subtitle \"not mass weighted\"\n");
        }
    }

    for (i = 0; i <= (end-begin); i++)
    {
        fprintf (out, "%6d %15g\n", begin+i, eigenvalues[i]);
    }
    ffclose(out);


    if (opt2bSet("-qc", NFILE, fnm))
    {
        qc = xvgropen(opt2fn("-qc", NFILE, fnm), "Quantum Corrections", "Eigenvector index", "", oenv);
        xvgr_legend(qc, asize(qcleg), qcleg, oenv);
        qcvtot = qutot = 0;
    }
    else
    {
        qc = NULL;
    }
    printf("Writing eigenfrequencies - negative eigenvalues will be set to zero.\n");

    out = xvgropen(opt2fn("-of", NFILE, fnm),
                   "Eigenfrequencies", "Eigenvector index", "Wavenumber [cm\\S-1\\N]",
                   oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        if (bM)
        {
            fprintf(out, "@ subtitle \"mass weighted\"\n");
        }
        else
        {
            fprintf(out, "@ subtitle \"not mass weighted\"\n");
        }
    }
    /* Spectrum ? */
    spec = NULL;
    if (opt2bSet("-os", NFILE, fnm) && (maxspec > 0))
    {
        snew(spectrum, maxspec);
        spec = xvgropen(opt2fn("-os", NFILE, fnm),
                        "Vibrational spectrum based on harmonic approximation",
                        "\\f{12}w\\f{4} (cm\\S-1\\N)",
                        "Intensity [Gromacs units]",
                        oenv);
        for (i = 0; (i < maxspec); i++)
        {
            spectrum[i] = 0;
        }
    }

    /* Gromacs units are kJ/(mol*nm*nm*amu),
     * where amu is the atomic mass unit.
     *
     * For the eigenfrequencies we want to convert this to spectroscopic absorption
     * wavenumbers given in cm^(-1), which is the frequency divided by the speed of
     * light. Do this by first converting to omega^2 (units 1/s), take the square
     * root, and finally divide by the speed of light (nm/ps in gromacs).
     */
    factor_gmx_to_omega2       = 1.0E21/(AVOGADRO*AMU);
    factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT);

    for (i = begin; (i <= end); i++)
    {
        value = eigenvalues[i-begin];
        if (value < 0)
        {
            value = 0;
        }
        omega = sqrt(value*factor_gmx_to_omega2);
        nu    = 1e-12*omega/(2*M_PI);
        value = omega*factor_omega_to_wavenumber;
        fprintf (out, "%6d %15g\n", i, value);
        if (NULL != spec)
        {
            wfac = eigenvalues[i-begin]/(width*sqrt(2*M_PI));
            for (j = 0; (j < maxspec); j++)
            {
                spectrum[j] += wfac*exp(-sqr(j-value)/(2*sqr(width)));
            }
        }
        if (NULL != qc)
        {
            qcv = cv_corr(nu, T);
            qu  = u_corr(nu, T);
            if (i > end-nharm)
            {
                qcv += BOLTZ*KILO;
                qu  += BOLTZ*T;
            }
            fprintf (qc, "%6d %15g %15g\n", i, qcv, qu);
            qcvtot += qcv;
            qutot  += qu;
        }
    }
    ffclose(out);
    if (NULL != spec)
    {
        for (j = 0; (j < maxspec); j++)
        {
            fprintf(spec, "%10g  %10g\n", 1.0*j, spectrum[j]);
        }
        ffclose(spec);
    }
    if (NULL != qc)
    {
        printf("Quantum corrections for harmonic degrees of freedom\n");
        printf("Use appropriate -first and -last options to get reliable results.\n");
        printf("There were %d constraints and %d vsites in the simulation\n",
               nharm, nvsite);
        printf("Total correction to cV = %g J/mol K\n", qcvtot);
        printf("Total correction to  H = %g kJ/mol\n", qutot);
        ffclose(qc);
        please_cite(stdout, "Caleman2011b");
    }
    /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors
     * were scaled back from mass weighted cartesian to plain cartesian in the
     * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors
     * will not be strictly orthogonal in plain cartesian scalar products.
     */
    write_eigenvectors(opt2fn("-v", NFILE, fnm), natoms, eigenvectors, FALSE, begin, end,
                       eWXR_NO, NULL, FALSE, top_x, bM, eigenvalues);

    thanx(stderr);

    return 0;
}
Example #14
0
int gmx_gyrate(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes the radius of gyration of a molecule",
        "and the radii of gyration about the [IT]x[it]-, [IT]y[it]- and [IT]z[it]-axes,",
        "as a function of time. The atoms are explicitly mass weighted.[PAR]",
        "The axis components corresponds to the mass-weighted root-mean-square",
        "of the radii components orthogonal to each axis, for example:[PAR]",
        "Rg(x) = sqrt((sum_i m_i (R_i(y)^2 + R_i(z)^2))/(sum_i m_i)).[PAR]",
        "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
        "for multiple molecules by splitting the analysis group in equally",
        "sized parts.[PAR]",
        "With the option [TT]-nz[tt] 2D radii of gyration in the [IT]x-y[it] plane",
        "of slices along the [IT]z[it]-axis are calculated."
    };
    static int        nmol = 1, nz = 0;
    static gmx_bool   bQ   = FALSE, bRot = FALSE, bMOI = FALSE;
    t_pargs           pa[] = {
        { "-nmol", FALSE, etINT, {&nmol},
          "The number of molecules to analyze" },
        { "-q", FALSE, etBOOL, {&bQ},
          "Use absolute value of the charge of an atom as weighting factor instead of mass" },
        { "-p", FALSE, etBOOL, {&bRot},
          "Calculate the radii of gyration about the principal axes." },
        { "-moi", FALSE, etBOOL, {&bMOI},
          "Calculate the moments of inertia (defined by the principal axes)." },
        { "-nz", FALSE, etINT, {&nz},
          "Calculate the 2D radii of gyration of this number of slices along the z-axis" },
    };
    FILE             *out;
    t_trxstatus      *status;
    t_topology        top;
    int               ePBC;
    rvec             *x, *x_s;
    rvec              xcm, gvec, gvec1;
    matrix            box, trans;
    gmx_bool          bACF;
    real            **moi_trans = NULL;
    int               max_moi   = 0, delta_moi = 100;
    rvec              d, d1; /* eigenvalues of inertia tensor */
    real              t, t0, tm, gyro;
    int               natoms;
    char             *grpname;
    int               j, m, gnx, nam, mol;
    atom_id          *index;
    gmx_output_env_t *oenv;
    gmx_rmpbc_t       gpbc   = NULL;
    const char       *leg[]  = { "Rg", "Rg\\sX\\N", "Rg\\sY\\N", "Rg\\sZ\\N" };
    const char       *legI[] = { "Itot", "I1", "I2", "I3" };
#define NLEG asize(leg)
    t_filenm          fnm[] = {
        { efTRX, "-f",   NULL,       ffREAD },
        { efTPS, NULL,   NULL,       ffREAD },
        { efNDX, NULL,   NULL,       ffOPTRD },
        { efXVG, NULL,   "gyrate",   ffWRITE },
        { efXVG, "-acf", "moi-acf",  ffOPTWR },
    };
#define NFILE asize(fnm)
    int               npargs;
    t_pargs          *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }
    bACF = opt2bSet("-acf", NFILE, fnm);
    if (bACF && nmol != 1)
    {
        gmx_fatal(FARGS, "Can only do acf with nmol=1");
    }
    bRot = bRot || bMOI || bACF;
    /*
       if (nz > 0)
       bMOI = TRUE;
     */
    if (bRot)
    {
        printf("Will rotate system along principal axes\n");
        snew(moi_trans, DIM);
    }
    if (bMOI)
    {
        printf("Will print moments of inertia\n");
        bQ = FALSE;
    }
    if (bQ)
    {
        printf("Will print radius normalised by charge\n");
    }

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, TRUE);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);

    if (nmol > gnx || gnx % nmol != 0)
    {
        gmx_fatal(FARGS, "The number of atoms in the group (%d) is not a multiple of nmol (%d)", gnx, nmol);
    }
    nam = gnx/nmol;

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

    j  = 0;
    t0 = t;
    if (bQ)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of Charge (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    else if (bMOI)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Moments of inertia (total and around axes)", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv);
    }
    else
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of gyration (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    if (bMOI)
    {
        xvgr_legend(out, NLEG, legI, oenv);
    }
    else
    {
        if (bRot)
        {
            if (output_env_get_print_xvgr_codes(oenv))
            {
                fprintf(out, "@ subtitle \"Axes are principal component axes\"\n");
            }
        }
        xvgr_legend(out, NLEG, leg, oenv);
    }
    if (nz == 0)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    }
    do
    {
        if (nz == 0)
        {
            gmx_rmpbc_copy(gpbc, natoms, box, x, x_s);
        }
        gyro = 0;
        clear_rvec(gvec);
        clear_rvec(gvec1);
        clear_rvec(d);
        clear_rvec(d1);
        for (mol = 0; mol < nmol; mol++)
        {
            tm    = sub_xcm(nz == 0 ? x_s : x, nam, index+mol*nam, top.atoms.atom, xcm, bQ);
            if (nz == 0)
            {
                gyro += calc_gyro(x_s, nam, index+mol*nam, top.atoms.atom,
                                  tm, gvec1, d1, bQ, bRot, bMOI, trans);
            }
            else
            {
                calc_gyro_z(x, box, nam, index+mol*nam, top.atoms.atom, nz, t, out);
            }
            rvec_inc(gvec, gvec1);
            rvec_inc(d, d1);
        }
        if (nmol > 0)
        {
            gyro /= nmol;
            svmul(1.0/nmol, gvec, gvec);
            svmul(1.0/nmol, d, d);
        }

        if (nz == 0)
        {
            if (bRot)
            {
                if (j >= max_moi)
                {
                    max_moi += delta_moi;
                    for (m = 0; (m < DIM); m++)
                    {
                        srenew(moi_trans[m], max_moi*DIM);
                    }
                }
                for (m = 0; (m < DIM); m++)
                {
                    copy_rvec(trans[m], moi_trans[m]+DIM*j);
                }
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, d[XX], d[YY], d[ZZ]);
            }
            else
            {
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, gvec[XX], gvec[YY], gvec[ZZ]);
            }
        }
        j++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);
    if (nz == 0)
    {
        gmx_rmpbc_done(gpbc);
    }

    xvgrclose(out);

    if (bACF)
    {
        int mode = eacVector;

        do_autocorr(opt2fn("-acf", NFILE, fnm), oenv,
                    "Moment of inertia vector ACF",
                    j, 3, moi_trans, (t-t0)/j, mode, FALSE);
        do_view(oenv, opt2fn("-acf", NFILE, fnm), "-nxy");
    }

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy");

    return 0;
}
Example #15
0
int gmx_analyze(int argc, char *argv[])
{
    static const char *desc[] = {
        "[THISMODULE] reads an ASCII file and analyzes data sets.",
        "A line in the input file may start with a time",
        "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.",
        "Multiple sets can also be",
        "read when they are separated by & (option [TT]-n[tt]);",
        "in this case only one [IT]y[it]-value is read from each line.",
        "All lines starting with # and @ are skipped.",
        "All analyses can also be done for the derivative of a set",
        "(option [TT]-d[tt]).[PAR]",

        "All options, except for [TT]-av[tt] and [TT]-power[tt], assume that the",
        "points are equidistant in time.[PAR]",

        "[THISMODULE] always shows the average and standard deviation of each",
        "set, as well as the relative deviation of the third",
        "and fourth cumulant from those of a Gaussian distribution with the same",
        "standard deviation.[PAR]",

        "Option [TT]-ac[tt] produces the autocorrelation function(s).",
        "Be sure that the time interval between data points is",
        "much shorter than the time scale of the autocorrelation.[PAR]",

        "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of",
        "i/2 periods. The formula is::",
        "",
        "  [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]",
        "",
        "This is useful for principal components obtained from covariance",
        "analysis, since the principal components of random diffusion are",
        "pure cosines.[PAR]",

        "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]",

        "Option [TT]-dist[tt] produces distribution plot(s).[PAR]",

        "Option [TT]-av[tt] produces the average over the sets.",
        "Error bars can be added with the option [TT]-errbar[tt].",
        "The errorbars can represent the standard deviation, the error",
        "(assuming the points are independent) or the interval containing",
        "90% of the points, by discarding 5% of the points at the top and",
        "the bottom.[PAR]",

        "Option [TT]-ee[tt] produces error estimates using block averaging.",
        "A set is divided in a number of blocks and averages are calculated for",
        "each block. The error for the total average is calculated from",
        "the variance between averages of the m blocks B[SUB]i[sub] as follows:",
        "error^2 = [SUM][sum] (B[SUB]i[sub] - [CHEVRON]B[chevron])^2 / (m*(m-1)).",
        "These errors are plotted as a function of the block size.",
        "Also an analytical block average curve is plotted, assuming",
        "that the autocorrelation is a sum of two exponentials.",
        "The analytical curve for the block average is::",
        "",
        "  [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)) +",
        "                         (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],",
        "",
        "where T is the total time.",
        "[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.",
        "When the actual block average is very close to the analytical curve,",
        "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].",
        "The complete derivation is given in",
        "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",

        "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
        "of each set and over all sets with respect to a filtered average.",
        "The filter is proportional to cos([GRK]pi[grk] t/len) where t goes from -len/2",
        "to len/2. len is supplied with the option [TT]-filter[tt].",
        "This filter reduces oscillations with period len/2 and len by a factor",
        "of 0.79 and 0.33 respectively.[PAR]",

        "Option [TT]-g[tt] fits the data to the function given with option",
        "[TT]-fitfn[tt].[PAR]",

        "Option [TT]-power[tt] fits the data to [MATH]b t^a[math], which is accomplished",
        "by fitting to [MATH]a t + b[math] on log-log scale. All points after the first",
        "zero or with a negative value are ignored.[PAR]"

        "Option [TT]-luzar[tt] performs a Luzar & Chandler kinetics analysis",
        "on output from [gmx-hbond]. The input file can be taken directly",
        "from [TT]gmx hbond -ac[tt], and then the same result should be produced.[PAR]",
        "Option [TT]-fitfn[tt] performs curve fitting to a number of different",
        "curves that make sense in the context of molecular dynamics, mainly",
        "exponential curves. More information is in the manual. To check the output",
        "of the fitting procedure the option [TT]-fitted[tt] will print both the",
        "original data and the fitted function to a new data file. The fitting",
        "parameters are stored as comment in the output file."
    };
    static real        tb         = -1, te = -1, frac = 0.5, filtlen = 0, binwidth = 0.1, aver_start = 0;
    static gmx_bool    bHaveT     = TRUE, bDer = FALSE, bSubAv = TRUE, bAverCorr = FALSE, bXYdy = FALSE;
    static gmx_bool    bEESEF     = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE;
    static gmx_bool    bIntegrate = FALSE, bRegression = FALSE, bLuzar = FALSE;
    static int         nsets_in   = 1, d = 1, nb_min = 4, resol = 10;
    static real        temp       = 298.15, fit_start = 1, fit_end = 60;

    /* must correspond to enum avbar* declared at beginning of file */
    static const char *avbar_opt[avbarNR+1] = {
        NULL, "none", "stddev", "error", "90", NULL
    };

    t_pargs            pa[] = {
        { "-time",    FALSE, etBOOL, {&bHaveT},
          "Expect a time in the input" },
        { "-b",       FALSE, etREAL, {&tb},
          "First time to read from set" },
        { "-e",       FALSE, etREAL, {&te},
          "Last time to read from set" },
        { "-n",       FALSE, etINT, {&nsets_in},
          "Read this number of sets separated by &" },
        { "-d",       FALSE, etBOOL, {&bDer},
          "Use the derivative" },
        { "-dp",      FALSE, etINT, {&d},
          "HIDDENThe derivative is the difference over this number of points" },
        { "-bw",      FALSE, etREAL, {&binwidth},
          "Binwidth for the distribution" },
        { "-errbar",  FALSE, etENUM, {avbar_opt},
          "Error bars for [TT]-av[tt]" },
        { "-integrate", FALSE, etBOOL, {&bIntegrate},
          "Integrate data function(s) numerically using trapezium rule" },
        { "-aver_start", FALSE, etREAL, {&aver_start},
          "Start averaging the integral from here" },
        { "-xydy",    FALSE, etBOOL, {&bXYdy},
          "Interpret second data set as error in the y values for integrating" },
        { "-regression", FALSE, etBOOL, {&bRegression},
          "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]." },
        { "-luzar",   FALSE, etBOOL, {&bLuzar},
          "Do a Luzar and Chandler analysis on a correlation function and "
          "related as produced by [gmx-hbond]. When in addition the "
          "[TT]-xydy[tt] flag is given the second and fourth column will be "
          "interpreted as errors in c(t) and n(t)." },
        { "-temp",    FALSE, etREAL, {&temp},
          "Temperature for the Luzar hydrogen bonding kinetics analysis (K)" },
        { "-fitstart", FALSE, etREAL, {&fit_start},
          "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" },
        { "-fitend", FALSE, etREAL, {&fit_end},
          "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]" },
        { "-nbmin",   FALSE, etINT, {&nb_min},
          "HIDDENMinimum number of blocks for block averaging" },
        { "-resol", FALSE, etINT, {&resol},
          "HIDDENResolution for the block averaging, block size increases with"
          " a factor 2^(1/resol)" },
        { "-eeexpfit", FALSE, etBOOL, {&bEESEF},
          "HIDDENAlways use a single exponential fit for the error estimate" },
        { "-eenlc", FALSE, etBOOL, {&bEENLC},
          "HIDDENAllow a negative long-time correlation" },
        { "-eefitac", FALSE, etBOOL, {&bEeFitAc},
          "HIDDENAlso plot analytical block average using a autocorrelation fit" },
        { "-filter",  FALSE, etREAL, {&filtlen},
          "Print the high-frequency fluctuation after filtering with a cosine filter of this length" },
        { "-power", FALSE, etBOOL, {&bPower},
          "Fit data to: b t^a" },
        { "-subav", FALSE, etBOOL, {&bSubAv},
          "Subtract the average before autocorrelating" },
        { "-oneacf", FALSE, etBOOL, {&bAverCorr},
          "Calculate one ACF over all sets" },
    };
#define NPA asize(pa)

    FILE             *out;
    int               n, nlast, s, nset, i, j = 0;
    real            **val, *t, dt, tot, error;
    double           *av, *sig, cum1, cum2, cum3, cum4, db;
    const char       *acfile, *msdfile, *ccfile, *distfile, *avfile, *eefile, *fitfile;
    gmx_output_env_t *oenv;

    t_filenm          fnm[] = {
        { efXVG, "-f",    "graph",    ffREAD   },
        { efXVG, "-ac",   "autocorr", ffOPTWR  },
        { efXVG, "-msd",  "msd",      ffOPTWR  },
        { efXVG, "-cc",   "coscont",  ffOPTWR  },
        { efXVG, "-dist", "distr",    ffOPTWR  },
        { efXVG, "-av",   "average",  ffOPTWR  },
        { efXVG, "-ee",   "errest",   ffOPTWR  },
        { efXVG, "-fitted", "fitted", ffOPTWR },
        { efLOG, "-g",    "fitlog",   ffOPTWR  }
    };
#define NFILE asize(fnm)

    int      npargs;
    t_pargs *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

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

    acfile   = opt2fn_null("-ac", NFILE, fnm);
    msdfile  = opt2fn_null("-msd", NFILE, fnm);
    ccfile   = opt2fn_null("-cc", NFILE, fnm);
    distfile = opt2fn_null("-dist", NFILE, fnm);
    avfile   = opt2fn_null("-av", NFILE, fnm);
    eefile   = opt2fn_null("-ee", NFILE, fnm);
    if (opt2parg_bSet("-fitfn", npargs, ppa) && acfile == NULL)
    {
        fitfile  = opt2fn("-g", NFILE, fnm);
    }
    else
    {
        fitfile  = opt2fn_null("-g", NFILE, fnm);
    }

    val = read_xvg_time(opt2fn("-f", NFILE, fnm), bHaveT,
                        opt2parg_bSet("-b", npargs, ppa), tb,
                        opt2parg_bSet("-e", npargs, ppa), te,
                        nsets_in, &nset, &n, &dt, &t);
    printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt);

    if (bDer)
    {
        printf("Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n\n",
               d, d);
        n -= d;
        for (s = 0; s < nset; s++)
        {
            for (i = 0; (i < n); i++)
            {
                val[s][i] = (val[s][i+d]-val[s][i])/(d*dt);
            }
        }
    }

    if (bIntegrate)
    {
        real sum, stddev;

        printf("Calculating the integral using the trapezium rule\n");

        if (bXYdy)
        {
            sum = evaluate_integral(n, t, val[0], val[1], aver_start, &stddev);
            printf("Integral %10.3f +/- %10.5f\n", sum, stddev);
        }
        else
        {
            for (s = 0; s < nset; s++)
            {
                sum = evaluate_integral(n, t, val[s], NULL, aver_start, &stddev);
                printf("Integral %d  %10.5f  +/- %10.5f\n", s+1, sum, stddev);
            }
        }
    }

    if (fitfile != NULL)
    {
        print_fitted_function(fitfile,
                              opt2fn_null("-fitted", NFILE, fnm),
                              bXYdy, nset,
                              n, t, val,
                              npargs, ppa,
                              oenv);
    }

    printf("                                      std. dev.    relative deviation of\n");
    printf("                       standard       ---------   cumulants from those of\n");
    printf("set      average       deviation      sqrt(n-1)   a Gaussian distribition\n");
    printf("                                                      cum. 3   cum. 4\n");
    snew(av, nset);
    snew(sig, nset);
    for (s = 0; (s < nset); s++)
    {
        cum1 = 0;
        cum2 = 0;
        cum3 = 0;
        cum4 = 0;
        for (i = 0; (i < n); i++)
        {
            cum1 += val[s][i];
        }
        cum1 /= n;
        for (i = 0; (i < n); i++)
        {
            db    = val[s][i]-cum1;
            cum2 += db*db;
            cum3 += db*db*db;
            cum4 += db*db*db*db;
        }
        cum2  /= n;
        cum3  /= n;
        cum4  /= n;
        av[s]  = cum1;
        sig[s] = std::sqrt(cum2);
        if (n > 1)
        {
            error = std::sqrt(cum2/(n-1));
        }
        else
        {
            error = 0;
        }
        printf("SS%d  %13.6e   %12.6e   %12.6e      %6.3f   %6.3f\n",
               s+1, av[s], sig[s], error,
               sig[s] ? cum3/(sig[s]*sig[s]*sig[s]*std::sqrt(8/M_PI)) : 0,
               sig[s] ? cum4/(sig[s]*sig[s]*sig[s]*sig[s]*3)-1 : 0);
    }
    printf("\n");

    if (filtlen)
    {
        filter(filtlen, n, nset, val, dt);
    }

    if (msdfile)
    {
        out = xvgropen(msdfile, "Mean square displacement",
                       "time", "MSD (nm\\S2\\N)", oenv);
        nlast = static_cast<int>(n*frac);
        for (s = 0; s < nset; s++)
        {
            for (j = 0; j <= nlast; j++)
            {
                if (j % 100 == 0)
                {
                    fprintf(stderr, "\r%d", j);
                }
                tot = 0;
                for (i = 0; i < n-j; i++)
                {
                    tot += sqr(val[s][i]-val[s][i+j]);
                }
                tot /= (n-j);
                fprintf(out, " %g %8g\n", dt*j, tot);
            }
            if (s < nset-1)
            {
                fprintf(out, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            }
        }
        xvgrclose(out);
        fprintf(stderr, "\r%d, time=%g\n", j-1, (j-1)*dt);
    }
    if (ccfile)
    {
        plot_coscont(ccfile, n, nset, val, oenv);
    }

    if (distfile)
    {
        histogram(distfile, binwidth, n, nset, val, oenv);
    }
    if (avfile)
    {
        average(avfile, nenum(avbar_opt), n, nset, val, t);
    }
    if (eefile)
    {
        estimate_error(eefile, nb_min, resol, n, nset, av, sig, val, dt,
                       bEeFitAc, bEESEF, bEENLC, oenv);
    }
    if (bPower)
    {
        power_fit(n, nset, val, t);
    }

    if (acfile != NULL)
    {
        if (bSubAv)
        {
            for (s = 0; s < nset; s++)
            {
                for (i = 0; i < n; i++)
                {
                    val[s][i] -= av[s];
                }
            }
        }
        do_autocorr(acfile, oenv, "Autocorrelation", n, nset, val, dt,
                    eacNormal, bAverCorr);
    }

    if (bRegression)
    {
        regression_analysis(n, bXYdy, t, nset, val);
    }

    if (bLuzar)
    {
        luzar_correl(n, t, nset, val, temp, bXYdy, fit_start);
    }

    view_all(oenv, NFILE, fnm);

    return 0;
}
Example #16
0
static void periodic_mindist_plot(const char *trxfn, const char *outfn,
                                  t_topology *top, int ePBC,
                                  int n, atom_id index[], gmx_bool bSplit,
                                  const output_env_t oenv)
{
    FILE        *out;
    const char  *leg[5] = { "min per.", "max int.", "box1", "box2", "box3" };
    t_trxstatus *status;
    real         t;
    rvec        *x;
    matrix       box;
    int          natoms, ind_min[2] = {0, 0}, ind_mini = 0, ind_minj = 0;
    real         r, rmin, rmax, rmint, tmint;
    gmx_bool     bFirst;
    gmx_rmpbc_t  gpbc = NULL;

    natoms = read_first_x(oenv, &status, trxfn, &t, &x, box);

    check_index(NULL, n, index, NULL, natoms);

    out = xvgropen(outfn, "Minimum distance to periodic image",
                   output_env_get_time_label(oenv), "Distance (nm)", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(out, "@ subtitle \"and maximum internal distance\"\n");
    }
    xvgr_legend(out, 5, leg, oenv);

    rmint = box[XX][XX];
    tmint = 0;

    if (NULL != top)
    {
        gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
    }

    bFirst = TRUE;
    do
    {
        if (NULL != top)
        {
            gmx_rmpbc(gpbc, natoms, box, x);
        }

        periodic_dist(box, x, n, index, &rmin, &rmax, ind_min);
        if (rmin < rmint)
        {
            rmint    = rmin;
            tmint    = t;
            ind_mini = ind_min[0];
            ind_minj = ind_min[1];
        }
        if (bSplit && !bFirst && abs(t/output_env_get_time_factor(oenv)) < 1e-5)
        {
            fprintf(out, "&\n");
        }
        fprintf(out, "\t%g\t%6.3f %6.3f %6.3f %6.3f %6.3f\n",
                output_env_conv_time(oenv, t), rmin, rmax, norm(box[0]), norm(box[1]), norm(box[2]));
        bFirst = FALSE;
    }
    while (read_next_x(oenv, status, &t, x, box));

    if (NULL != top)
    {
        gmx_rmpbc_done(gpbc);
    }

    ffclose(out);

    fprintf(stdout,
            "\nThe shortest periodic distance is %g (nm) at time %g (%s),\n"
            "between atoms %d and %d\n",
            rmint, output_env_conv_time(oenv, tmint), output_env_get_time_unit(oenv),
            index[ind_mini]+1, index[ind_minj]+1);
}
Example #17
0
void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string,
                const output_env_t oenv)
{
    FILE        *fp;
    t_mapping   *map;
    int          f, r, *count, *total, ss_count, total_count;
    size_t       s;
    const char** leg;

    map = mat->map;
    snew(count, mat->nmap);
    snew(total, mat->nmap);
    snew(leg, mat->nmap+1);
    leg[0] = "Structure";
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        leg[s+1] = gmx_strdup(map[s].desc);
    }

    fp = xvgropen(outfile, "Secondary Structure",
                  output_env_get_xvgr_tlabel(oenv), "Number of Residues", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"Structure = ");
    }
    for (s = 0; s < strlen(ss_string); s++)
    {
        if (s > 0)
        {
            fprintf(fp, " + ");
        }
        for (f = 0; f < mat->nmap; f++)
        {
            if (ss_string[s] == map[f].code.c1)
            {
                fprintf(fp, "%s", map[f].desc);
            }
        }
    }
    fprintf(fp, "\"\n");
    xvgr_legend(fp, mat->nmap+1, leg, oenv);

    total_count = 0;
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        total[s] = 0;
    }
    for (f = 0; f < mat->nx; f++)
    {
        ss_count = 0;
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            count[s] = 0;
        }
        for (r = 0; r < mat->ny; r++)
        {
            count[mat->matrix[f][r]]++;
            total[mat->matrix[f][r]]++;
        }
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            if (strchr(ss_string, map[s].code.c1))
            {
                ss_count    += count[s];
                total_count += count[s];
            }
        }
        fprintf(fp, "%8g %5d", mat->axis_x[f], ss_count);
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            fprintf(fp, " %5d", count[s]);
        }
        fprintf(fp, "\n");
    }
    /* now print column totals */
    fprintf(fp, "%-8s %5d", "# Totals", total_count);
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        fprintf(fp, " %5d", total[s]);
    }
    fprintf(fp, "\n");

    /* now print percentages */
    fprintf(fp, "%-8s %5.2f", "# SS %", total_count / (real) (mat->nx * mat->ny));
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        fprintf(fp, " %5.2f", total[s] / (real) (mat->nx * mat->ny));
    }
    fprintf(fp, "\n");

    xvgrclose(fp);
    sfree(leg);
    sfree(count);
}
Example #18
0
void get_chi_product_traj (real **dih, int nframes, int nlist,
                           int maxchi, t_dlist dlist[], real time[],
                           int **lookup, int *multiplicity, gmx_bool bRb, gmx_bool bNormalize,
                           real core_frac, gmx_bool bAll, const char *fnall,
                           const gmx_output_env_t *oenv)
{

    gmx_bool bRotZero, bHaveChi = FALSE;
    int      accum = 0, index, i, j, k, Xi, n, b;
    real    *chi_prtrj;
    int     *chi_prhist;
    int      nbin;
    FILE    *fp, *fpall;
    char     hisfile[256], histitle[256], *namept;

    int      (*calc_bin)(real, int, real);

    /* Analysis of dihedral transitions */
    fprintf(stderr, "Now calculating Chi product trajectories...\n");

    if (bRb)
    {
        calc_bin = calc_RBbin;
    }
    else
    {
        calc_bin = calc_Nbin;
    }

    snew(chi_prtrj, nframes);

    /* file for info on all residues */
    if (bNormalize)
    {
        fpall = xvgropen(fnall, "Cumulative Rotamers", "Residue", "Probability", oenv);
    }
    else
    {
        fpall = xvgropen(fnall, "Cumulative Rotamers", "Residue", "# Counts", oenv);
    }

    for (i = 0; (i < nlist); i++)
    {

        /* get nbin, the nr. of cumulative rotamers that need to be considered */
        nbin = 1;
        for (Xi = 0; Xi < maxchi; Xi++)
        {
            index = lookup[i][Xi]; /* chi_(Xi+1) of res i (-1 if off end) */
            if (index >= 0)
            {
                n    = multiplicity[index];
                nbin = n*nbin;
            }
        }
        nbin += 1; /* for the "zero rotamer", outside the core region */

        for (j = 0; (j < nframes); j++)
        {

            bRotZero = FALSE;
            bHaveChi = TRUE;
            index    = lookup[i][0]; /* index into dih of chi1 of res i */
            if (index == -1)
            {
                bRotZero = TRUE;
                bHaveChi = FALSE;
            }
            else
            {
                b     = calc_bin(dih[index][j], multiplicity[index], core_frac);
                accum = b - 1;
                if (b == 0)
                {
                    bRotZero = TRUE;
                }
                for (Xi = 1; Xi < maxchi; Xi++)
                {
                    index = lookup[i][Xi]; /* chi_(Xi+1) of res i (-1 if off end) */
                    if (index >= 0)
                    {
                        n     = multiplicity[index];
                        b     = calc_bin(dih[index][j], n, core_frac);
                        accum = n * accum + b - 1;
                        if (b == 0)
                        {
                            bRotZero = TRUE;
                        }
                    }
                }
                accum++;
            }
            if (bRotZero)
            {
                chi_prtrj[j] = 0.0;
            }
            else
            {
                chi_prtrj[j] = accum;
                if (accum+1 > nbin)
                {
                    nbin = accum+1;
                }
            }
        }
        if (bHaveChi)
        {

            if (bAll)
            {
                /* print cuml rotamer vs time */
                print_one(oenv, "chiproduct", dlist[i].name, "chi product for",
                          "cumulative rotamer", nframes, time, chi_prtrj);
            }

            /* make a histogram pf culm. rotamer occupancy too */
            snew(chi_prhist, nbin);
            make_histo(nullptr, nframes, chi_prtrj, nbin, chi_prhist, 0, nbin);
            if (bAll)
            {
                sprintf(hisfile, "histo-chiprod%s.xvg", dlist[i].name);
                sprintf(histitle, "cumulative rotamer distribution for %s", dlist[i].name);
                fprintf(stderr, "  and %s  ", hisfile);
                fp = xvgropen(hisfile, histitle, "number", "", oenv);
                if (output_env_get_print_xvgr_codes(oenv))
                {
                    fprintf(fp, "@ xaxis tick on\n");
                    fprintf(fp, "@ xaxis tick major 1\n");
                    fprintf(fp, "@ type xy\n");
                }
                for (k = 0; (k < nbin); k++)
                {
                    if (bNormalize)
                    {
                        fprintf(fp, "%5d  %10g\n", k, (1.0*chi_prhist[k])/nframes);
                    }
                    else
                    {
                        fprintf(fp, "%5d  %10d\n", k, chi_prhist[k]);
                    }
                }
                fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
                xvgrclose(fp);
            }

            /* and finally print out occupancies to a single file */
            /* get the gmx from-1 res nr by setting a ptr to the number part
             * of dlist[i].name - potential bug for 4-letter res names... */
            namept = dlist[i].name + 3;
            fprintf(fpall, "%5s ", namept);
            for (k = 0; (k < nbin); k++)
            {
                if (bNormalize)
                {
                    fprintf(fpall, "  %10g", (1.0*chi_prhist[k])/nframes);
                }
                else
                {
                    fprintf(fpall, "  %10d", chi_prhist[k]);
                }
            }
            fprintf(fpall, "\n");

            sfree(chi_prhist);
            /* histogram done */
        }
    }

    sfree(chi_prtrj);
    xvgrclose(fpall);
    fprintf(stderr, "\n");

}
Example #19
0
int gmx_nmeig(int argc,char *argv[])
{
  const char *desc[] = {
    "g_nmeig calculates the eigenvectors/values of a (Hessian) matrix,",
    "which can be calculated with [TT]mdrun[tt].",
    "The eigenvectors are written to a trajectory file ([TT]-v[tt]).",
    "The structure is written first with t=0. The eigenvectors",
    "are written as frames with the eigenvector number as timestamp.",
    "The eigenvectors can be analyzed with [TT]g_anaeig[tt].",
    "An ensemble of structures can be generated from the eigenvectors with",
    "[TT]g_nmens[tt]. When mass weighting is used, the generated eigenvectors",
    "will be scaled back to plain cartesian coordinates before generating the",
    "output - in this case they will no longer be exactly orthogonal in the",
    "standard cartesian norm (But in the mass weighted norm they would be)."
  };
    
  static gmx_bool bM=TRUE;
  static int  begin=1,end=50;
  t_pargs pa[] = 
  {
    { "-m",  FALSE, etBOOL, {&bM},
      "Divide elements of Hessian by product of sqrt(mass) of involved "
      "atoms prior to diagonalization. This should be used for 'Normal Modes' "
      "analysis" },
    { "-first", FALSE, etINT, {&begin},     
      "First eigenvector to write away" },
    { "-last",  FALSE, etINT, {&end}, 
      "Last eigenvector to write away" }
  };
  FILE       *out;
  int        status,trjout;
  t_topology top;
  int        ePBC;
  rvec       *top_x;
  matrix     box;
  real       *eigenvalues;
  real       *eigenvectors;
  real       rdum,mass_fac;
  int        natoms,ndim,nrow,ncol,count;
  char       *grpname,title[256];
  int        i,j,k,l,d,gnx;
  gmx_bool       bSuck;
  atom_id    *index;
  real       value;
  real       factor_gmx_to_omega2;
  real       factor_omega_to_wavenumber;
  t_commrec  *cr;
  output_env_t oenv;
  
  real *                 full_hessian   = NULL;
  gmx_sparsematrix_t *   sparse_hessian = NULL;

  t_filenm fnm[] = { 
    { efMTX, "-f", "hessian",    ffREAD  }, 
    { efTPS, NULL, NULL,         ffREAD  },
    { efXVG, "-of", "eigenfreq", ffWRITE },
    { efXVG, "-ol", "eigenval",  ffWRITE },
    { efTRN, "-v", "eigenvec",  ffWRITE }
  }; 
#define NFILE asize(fnm) 

	cr = init_par(&argc,&argv);

	if(MASTER(cr))
		CopyRight(stderr,argv[0]); 
	
  parse_common_args(&argc,argv,PCA_BE_NICE | (MASTER(cr) ? 0 : PCA_QUIET),
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); 

  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&top_x,NULL,box,bM);

  natoms = top.atoms.nr;
  ndim = DIM*natoms;

  if(begin<1)
      begin = 1;
  if(end>ndim)
      end = ndim;

  /*open Hessian matrix */
  gmx_mtxio_read(ftp2fn(efMTX,NFILE,fnm),&nrow,&ncol,&full_hessian,&sparse_hessian);
    
  /* Memory for eigenvalues and eigenvectors (begin..end) */
  snew(eigenvalues,nrow);
  snew(eigenvectors,nrow*(end-begin+1));
       
  /* If the Hessian is in sparse format we can calculate max (ndim-1) eigenvectors,
   * and they must start at the first one. If this is not valid we convert to full matrix
   * storage, but warn the user that we might run out of memory...
   */    
  if((sparse_hessian != NULL) && (begin!=1 || end==ndim))
  {
      if(begin!=1)
      {
          fprintf(stderr,"Cannot use sparse Hessian with first eigenvector != 1.\n");
      }
      else if(end==ndim)
      {
          fprintf(stderr,"Cannot use sparse Hessian to calculate all eigenvectors.\n");
      }
      
      fprintf(stderr,"Will try to allocate memory and convert to full matrix representation...\n");
      
      snew(full_hessian,nrow*ncol);
      for(i=0;i<nrow*ncol;i++)
          full_hessian[i] = 0;
      
      for(i=0;i<sparse_hessian->nrow;i++)
      {
          for(j=0;j<sparse_hessian->ndata[i];j++)
          {
              k     = sparse_hessian->data[i][j].col;
              value = sparse_hessian->data[i][j].value;
              full_hessian[i*ndim+k] = value;
              full_hessian[k*ndim+i] = value;
          }
      }
      gmx_sparsematrix_destroy(sparse_hessian);
      sparse_hessian = NULL;
      fprintf(stderr,"Converted sparse to full matrix storage.\n");
  }
  
  if(full_hessian != NULL)
  {
      /* Using full matrix storage */
      nma_full_hessian(full_hessian,nrow,bM,&top,begin,end,eigenvalues,eigenvectors);
  }
  else
  {
      /* Sparse memory storage, allocate memory for eigenvectors */
      snew(eigenvectors,ncol*end);
      nma_sparse_hessian(sparse_hessian,bM,&top,end,eigenvalues,eigenvectors);
  }
  
  
  /* check the output, first 6 eigenvalues should be reasonably small */  
  bSuck=FALSE;
  for (i=begin-1; (i<6); i++) 
  {
      if (fabs(eigenvalues[i]) > 1.0e-3) 
          bSuck=TRUE;
  }
  if (bSuck) 
  {
      fprintf(stderr,"\nOne of the lowest 6 eigenvalues has a non-zero value.\n");
      fprintf(stderr,"This could mean that the reference structure was not\n");
      fprintf(stderr,"properly energy minimized.\n");
  }
                      
                      
  /* now write the output */
  fprintf (stderr,"Writing eigenvalues...\n");
  out=xvgropen(opt2fn("-ol",NFILE,fnm), 
               "Eigenvalues","Eigenvalue index","Eigenvalue [Gromacs units]",
               oenv);
  if (output_env_get_print_xvgr_codes(oenv)) {
    if (bM)
      fprintf(out,"@ subtitle \"mass weighted\"\n");
    else 
      fprintf(out,"@ subtitle \"not mass weighted\"\n");
  }
  
  for (i=0; i<=(end-begin); i++)
      fprintf (out,"%6d %15g\n",begin+i,eigenvalues[i]);
  ffclose(out);
  

  
  fprintf(stderr,"Writing eigenfrequencies - negative eigenvalues will be set to zero.\n");

  out=xvgropen(opt2fn("-of",NFILE,fnm), 
               "Eigenfrequencies","Eigenvector index","Wavenumber [cm\\S-1\\N]",
               oenv);
  if (output_env_get_print_xvgr_codes(oenv)) { 
    if (bM)
      fprintf(out,"@ subtitle \"mass weighted\"\n");
    else 
      fprintf(out,"@ subtitle \"not mass weighted\"\n");
  }
  
  /* Gromacs units are kJ/(mol*nm*nm*amu),
   * where amu is the atomic mass unit.
   *
   * For the eigenfrequencies we want to convert this to spectroscopic absorption
   * wavenumbers given in cm^(-1), which is the frequency divided by the speed of
   * light. Do this by first converting to omega^2 (units 1/s), take the square 
   * root, and finally divide by the speed of light (nm/ps in gromacs).   
   */
  factor_gmx_to_omega2       = 1.0E21/(AVOGADRO*AMU);
  factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT);  
    
  for (i=0; i<=(end-begin); i++)
  {
      value = eigenvalues[i];
      if(value < 0)
          value = 0;
      value=sqrt(value*factor_gmx_to_omega2)*factor_omega_to_wavenumber;
      fprintf (out,"%6d %15g\n",begin+i,value);
  }
  ffclose(out);
  
  /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors 
   * were scaled back from mass weighted cartesian to plain cartesian in the
   * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors
   * will not be strictly orthogonal in plain cartesian scalar products.
   */   
  write_eigenvectors(opt2fn("-v",NFILE,fnm),natoms,eigenvectors,FALSE,begin,end,
                     eWXR_NO,NULL,FALSE,top_x,bM,eigenvalues);
  
  thanx(stderr);
  
  return 0;
}
Example #20
0
int gmx_rmsdist(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] computes the root mean square deviation of atom distances,",
        "which has the advantage that no fit is needed like in standard RMS",
        "deviation as computed by [gmx-rms].",
        "The reference structure is taken from the structure file.",
        "The RMSD at time t is calculated as the RMS",
        "of the differences in distance between atom-pairs in the reference",
        "structure and the structure at time t.[PAR]",
        "[THISMODULE] can also produce matrices of the rms distances, rms distances",
        "scaled with the mean distance and the mean distances and matrices with",
        "NMR averaged distances (1/r^3 and 1/r^6 averaging). Finally, lists",
        "of atom pairs with 1/r^3 and 1/r^6 averaged distance below the",
        "maximum distance ([TT]-max[tt], which will default to 0.6 in this case)",
        "can be generated, by default averaging over equivalent hydrogens",
        "(all triplets of hydrogens named \\*[123]). Additionally a list of",
        "equivalent atoms can be supplied ([TT]-equiv[tt]), each line containing",
        "a set of equivalent atoms specified as residue number and name and",
        "atom name; e.g.:[PAR]",
        "[TT]HB* 3 SER  HB1 3 SER  HB2[tt][PAR]",
        "Residue and atom names must exactly match those in the structure",
        "file, including case. Specifying non-sequential atoms is undefined."

    };

    int             i, teller;
    real            t;

    t_topology      top;
    int             ePBC;
    t_atoms        *atoms;
    matrix          box;
    rvec           *x;
    FILE           *fp;

    t_trxstatus    *status;
    int             isize, gnr = 0;
    atom_id        *index, *noe_index;
    char           *grpname;
    real          **d_r, **d, **dtot, **dtot2, **mean, **rms, **rmsc, *resnr;
    real          **dtot1_3 = NULL, **dtot1_6 = NULL;
    real            rmsnow, meanmax, rmsmax, rmscmax;
    real            max1_3, max1_6;
    t_noe_gr       *noe_gr = NULL;
    t_noe         **noe    = NULL;
    t_rgb           rlo, rhi;
    gmx_bool        bRMS, bScale, bMean, bNOE, bNMR3, bNMR6, bNMR;

    static int      nlevels  = 40;
    static real     scalemax = -1.0;
    static gmx_bool bSumH    = TRUE;
    static gmx_bool bPBC     = TRUE;
    output_env_t    oenv;

    t_pargs         pa[] = {
        { "-nlevels",   FALSE, etINT,  {&nlevels},
          "Discretize RMS in this number of levels" },
        { "-max",   FALSE, etREAL, {&scalemax},
          "Maximum level in matrices" },
        { "-sumh",  FALSE, etBOOL, {&bSumH},
          "Average distance over equivalent hydrogens" },
        { "-pbc",   FALSE, etBOOL, {&bPBC},
          "Use periodic boundary conditions when computing distances" }
    };
    t_filenm        fnm[] = {
        { efTRX, "-f",   NULL,       ffREAD },
        { efTPS, NULL,   NULL,       ffREAD },
        { efNDX, NULL,   NULL,       ffOPTRD },
        { efDAT, "-equiv", "equiv",   ffOPTRD },
        { efXVG, NULL,   "distrmsd", ffWRITE },
        { efXPM, "-rms", "rmsdist",  ffOPTWR },
        { efXPM, "-scl", "rmsscale", ffOPTWR },
        { efXPM, "-mean", "rmsmean",  ffOPTWR },
        { efXPM, "-nmr3", "nmr3",     ffOPTWR },
        { efXPM, "-nmr6", "nmr6",     ffOPTWR },
        { efDAT, "-noe", "noe",     ffOPTWR },
    };
#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;
    }

    bRMS   = opt2bSet("-rms", NFILE, fnm);
    bScale = opt2bSet("-scl", NFILE, fnm);
    bMean  = opt2bSet("-mean", NFILE, fnm);
    bNOE   = opt2bSet("-noe", NFILE, fnm);
    bNMR3  = opt2bSet("-nmr3", NFILE, fnm);
    bNMR6  = opt2bSet("-nmr6", NFILE, fnm);
    bNMR   = bNMR3 || bNMR6 || bNOE;

    max1_3 = 0;
    max1_6 = 0;

    /* check input */
    if (bNOE && scalemax < 0)
    {
        scalemax = 0.6;
        fprintf(stderr, "WARNING: using -noe without -max "
                "makes no sense, setting -max to %g\n\n", scalemax);
    }

    /* get topology and index */
    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, FALSE);

    if (!bPBC)
    {
        ePBC = epbcNONE;
    }
    atoms = &(top.atoms);

    get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);

    /* initialize arrays */
    snew(d, isize);
    snew(dtot, isize);
    snew(dtot2, isize);
    if (bNMR)
    {
        snew(dtot1_3, isize);
        snew(dtot1_6, isize);
    }
    snew(mean, isize);
    snew(rms, isize);
    snew(rmsc, isize);
    snew(d_r, isize);
    snew(resnr, isize);
    for (i = 0; (i < isize); i++)
    {
        snew(d[i], isize);
        snew(dtot[i], isize);
        snew(dtot2[i], isize);
        if (bNMR)
        {
            snew(dtot1_3[i], isize);
            snew(dtot1_6[i], isize);
        }
        snew(mean[i], isize);
        snew(rms[i], isize);
        snew(rmsc[i], isize);
        snew(d_r[i], isize);
        resnr[i] = i+1;
    }

    /*set box type*/
    calc_dist(isize, index, x, ePBC, box, d_r);
    sfree(x);

    /*open output files*/
    fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS Deviation", "Time (ps)", "RMSD (nm)",
                  oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"of distances between %s atoms\"\n", grpname);
    }

    /*do a first step*/
    read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    teller = 0;

    do
    {
        calc_dist_tot(isize, index, x, ePBC, box, d, dtot, dtot2, bNMR, dtot1_3, dtot1_6);

        rmsnow = rms_diff(isize, d, d_r);
        fprintf(fp, "%g  %g\n", t, rmsnow);
        teller++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    fprintf(stderr, "\n");

    xvgrclose(fp);

    close_trj(status);

    calc_rms(isize, teller, dtot, dtot2, rms, &rmsmax, rmsc, &rmscmax, mean, &meanmax);
    fprintf(stderr, "rmsmax = %g, rmscmax = %g\n", rmsmax, rmscmax);

    if (bNMR)
    {
        calc_nmr(isize, teller, dtot1_3, dtot1_6, &max1_3, &max1_6);
    }

    if (scalemax > -1.0)
    {
        rmsmax  = scalemax;
        rmscmax = scalemax;
        meanmax = scalemax;
        max1_3  = scalemax;
        max1_6  = scalemax;
    }

    if (bNOE)
    {
        /* make list of noe atom groups */
        snew(noe_index, isize+1);
        snew(noe_gr, isize);
        gnr = analyze_noe_equivalent(opt2fn_null("-equiv", NFILE, fnm),
                                     atoms, isize, index, bSumH, noe_index, noe_gr);
        fprintf(stdout, "Found %d non-equivalent atom-groups in %d atoms\n",
                gnr, isize);
        /* make half matrix of of noe-group distances from atom distances */
        snew(noe, gnr);
        for (i = 0; i < gnr; i++)
        {
            snew(noe[i], gnr);
        }
        calc_noe(isize, noe_index, dtot1_3, dtot1_6, gnr, noe);
    }

    rlo.r = 1.0, rlo.g = 1.0, rlo.b = 1.0;
    rhi.r = 0.0, rhi.g = 0.0, rhi.b = 0.0;

    if (bRMS)
    {
        write_xpm(opt2FILE("-rms", NFILE, fnm, "w"), 0,
                  "RMS of distance", "RMS (nm)", "Atom Index", "Atom Index",
                  isize, isize, resnr, resnr, rms, 0.0, rmsmax, rlo, rhi, &nlevels);
    }

    if (bScale)
    {
        write_xpm(opt2FILE("-scl", NFILE, fnm, "w"), 0,
                  "Relative RMS", "RMS", "Atom Index", "Atom Index",
                  isize, isize, resnr, resnr, rmsc, 0.0, rmscmax, rlo, rhi, &nlevels);
    }

    if (bMean)
    {
        write_xpm(opt2FILE("-mean", NFILE, fnm, "w"), 0,
                  "Mean Distance", "Distance (nm)", "Atom Index", "Atom Index",
                  isize, isize, resnr, resnr, mean, 0.0, meanmax, rlo, rhi, &nlevels);
    }

    if (bNMR3)
    {
        write_xpm(opt2FILE("-nmr3", NFILE, fnm, "w"), 0, "1/r^3 averaged distances",
                  "Distance (nm)", "Atom Index", "Atom Index",
                  isize, isize, resnr, resnr, dtot1_3, 0.0, max1_3, rlo, rhi, &nlevels);
    }
    if (bNMR6)
    {
        write_xpm(opt2FILE("-nmr6", NFILE, fnm, "w"), 0, "1/r^6 averaged distances",
                  "Distance (nm)", "Atom Index", "Atom Index",
                  isize, isize, resnr, resnr, dtot1_6, 0.0, max1_6, rlo, rhi, &nlevels);
    }

    if (bNOE)
    {
        write_noe(opt2FILE("-noe", NFILE, fnm, "w"), gnr, noe, noe_gr, scalemax);
    }

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL);

    return 0;
}
Example #21
0
int gmx_polystat(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] plots static properties of polymers as a function of time",
        "and prints the average.[PAR]",
        "By default it determines the average end-to-end distance and radii",
        "of gyration of polymers. It asks for an index group and split this",
        "into molecules. The end-to-end distance is then determined using",
        "the first and the last atom in the index group for each molecules.",
        "For the radius of gyration the total and the three principal components",
        "for the average gyration tensor are written.",
        "With option [TT]-v[tt] the eigenvectors are written.",
        "With option [TT]-pc[tt] also the average eigenvalues of the individual",
        "gyration tensors are written.",
        "With option [TT]-i[tt] the mean square internal distances are",
        "written.[PAR]",
        "With option [TT]-p[tt] the persistence length is determined.",
        "The chosen index group should consist of atoms that are",
        "consecutively bonded in the polymer mainchains.",
        "The persistence length is then determined from the cosine of",
        "the angles between bonds with an index difference that is even,",
        "the odd pairs are not used, because straight polymer backbones",
        "are usually all trans and therefore only every second bond aligns.",
        "The persistence length is defined as number of bonds where",
        "the average cos reaches a value of 1/e. This point is determined",
        "by a linear interpolation of [LOG]<cos>[log]."
    };
    static gmx_bool bMW  = TRUE, bPC = FALSE;
    t_pargs         pa[] = {
        { "-mw", FALSE, etBOOL, {&bMW},
          "Use the mass weighting for radii of gyration" },
        { "-pc", FALSE, etBOOL, {&bPC},
          "Plot average eigenvalues" }
    };

    t_filenm        fnm[] = {
        { efTPR, nullptr, nullptr,  ffREAD  },
        { efTRX, "-f", nullptr,  ffREAD  },
        { efNDX, nullptr, nullptr,  ffOPTRD },
        { efXVG, "-o", "polystat",  ffWRITE },
        { efXVG, "-v", "polyvec", ffOPTWR },
        { efXVG, "-p", "persist",  ffOPTWR },
        { efXVG, "-i", "intdist", ffOPTWR }
    };
#define NFILE asize(fnm)

    t_topology       *top;
    gmx_output_env_t *oenv;
    int               ePBC;
    int               isize, *index, nmol, *molind, mol, nat_min = 0, nat_max = 0;
    char             *grpname;
    t_trxstatus      *status;
    real              t;
    rvec             *x, *bond = nullptr;
    matrix            box;
    int               natoms, i, j, frame, ind0, ind1, a, d, d2, ord[DIM] = {0};
    dvec              cm, sum_eig = {0, 0, 0};
    double          **gyr, **gyr_all, eig[DIM], **eigv;
    double            sum_eed2, sum_eed2_tot, sum_gyro, sum_gyro_tot, sum_pers_tot;
    int              *ninp    = nullptr;
    double           *sum_inp = nullptr, pers;
    double           *intd, ymax, ymin;
    double            mmol, m;
    char              title[STRLEN];
    FILE             *out, *outv, *outp, *outi;
    const char       *leg[8] = {
        "end to end", "<R\\sg\\N>",
        "<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3",
        "<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>"
    };
    char            **legp, buf[STRLEN];
    gmx_rmpbc_t       gpbc = nullptr;

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

    snew(top, 1);
    ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm),
                        nullptr, box, &natoms, nullptr, nullptr, top);

    fprintf(stderr, "Select a group of polymer mainchain atoms:\n");
    get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm),
              1, &isize, &index, &grpname);

    snew(molind, top->mols.nr+1);
    nmol = 0;
    mol  = -1;
    for (i = 0; i < isize; i++)
    {
        if (i == 0 || index[i] >= top->mols.index[mol+1])
        {
            molind[nmol++] = i;
            do
            {
                mol++;
            }
            while (index[i] >= top->mols.index[mol+1]);
        }
    }
    molind[nmol] = i;
    nat_min      = top->atoms.nr;
    nat_max      = 0;
    for (mol = 0; mol < nmol; mol++)
    {
        nat_min = std::min(nat_min, molind[mol+1]-molind[mol]);
        nat_max = std::max(nat_max, molind[mol+1]-molind[mol]);
    }
    fprintf(stderr, "Group %s consists of %d molecules\n", grpname, nmol);
    fprintf(stderr, "Group size per molecule, min: %d atoms, max %d atoms\n",
            nat_min, nat_max);

    sprintf(title, "Size of %d polymers", nmol);
    out = xvgropen(opt2fn("-o", NFILE, fnm), title, output_env_get_xvgr_tlabel(oenv), "(nm)",
                   oenv);
    xvgr_legend(out, bPC ? 8 : 5, leg, oenv);

    if (opt2bSet("-v", NFILE, fnm))
    {
        outv = xvgropen(opt2fn("-v", NFILE, fnm), "Principal components",
                        output_env_get_xvgr_tlabel(oenv), "(nm)", oenv);
        snew(legp, DIM*DIM);
        for (d = 0; d < DIM; d++)
        {
            for (d2 = 0; d2 < DIM; d2++)
            {
                sprintf(buf, "eig%d %c", d+1, 'x'+d2);
                legp[d*DIM+d2] = gmx_strdup(buf);
            }
        }
        xvgr_legend(outv, DIM*DIM, (const char**)legp, oenv);
    }
    else
    {
        outv = nullptr;
    }

    if (opt2bSet("-p", NFILE, fnm))
    {
        outp = xvgropen(opt2fn("-p", NFILE, fnm), "Persistence length",
                        output_env_get_xvgr_tlabel(oenv), "bonds", oenv);
        snew(bond, nat_max-1);
        snew(sum_inp, nat_min/2);
        snew(ninp, nat_min/2);
    }
    else
    {
        outp = nullptr;
    }

    if (opt2bSet("-i", NFILE, fnm))
    {
        outi = xvgropen(opt2fn("-i", NFILE, fnm), "Internal distances",
                        "n", "<R\\S2\\N(n)>/n (nm\\S2\\N)", oenv);
        i = index[molind[1]-1] - index[molind[0]]; /* Length of polymer -1 */
        snew(intd, i);
    }
    else
    {
        intd = nullptr;
        outi = nullptr;
    }

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

    snew(gyr, DIM);
    snew(gyr_all, DIM);
    snew(eigv, DIM);
    for (d = 0; d < DIM; d++)
    {
        snew(gyr[d], DIM);
        snew(gyr_all[d], DIM);
        snew(eigv[d], DIM);
    }

    frame        = 0;
    sum_eed2_tot = 0;
    sum_gyro_tot = 0;
    sum_pers_tot = 0;

    gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);

    do
    {
        gmx_rmpbc(gpbc, natoms, box, x);

        sum_eed2 = 0;
        for (d = 0; d < DIM; d++)
        {
            clear_dvec(gyr_all[d]);
        }

        if (bPC)
        {
            clear_dvec(sum_eig);
        }

        if (outp)
        {
            for (i = 0; i < nat_min/2; i++)
            {
                sum_inp[i] = 0;
                ninp[i]    = 0;
            }
        }

        for (mol = 0; mol < nmol; mol++)
        {
            ind0 = molind[mol];
            ind1 = molind[mol+1];

            /* Determine end to end distance */
            sum_eed2 += distance2(x[index[ind0]], x[index[ind1-1]]);

            /* Determine internal distances */
            if (outi)
            {
                calc_int_dist(intd, x, index[ind0], index[ind1-1]);
            }

            /* Determine the radius of gyration */
            clear_dvec(cm);
            for (d = 0; d < DIM; d++)
            {
                clear_dvec(gyr[d]);
            }
            mmol = 0;

            for (i = ind0; i < ind1; i++)
            {
                a = index[i];
                if (bMW)
                {
                    m = top->atoms.atom[a].m;
                }
                else
                {
                    m = 1;
                }
                mmol += m;
                for (d = 0; d < DIM; d++)
                {
                    cm[d] += m*x[a][d];
                    for (d2 = 0; d2 < DIM; d2++)
                    {
                        gyr[d][d2] += m*x[a][d]*x[a][d2];
                    }
                }
            }
            dsvmul(1/mmol, cm, cm);
            for (d = 0; d < DIM; d++)
            {
                for (d2 = 0; d2 < DIM; d2++)
                {
                    gyr[d][d2]      = gyr[d][d2]/mmol - cm[d]*cm[d2];
                    gyr_all[d][d2] += gyr[d][d2];
                }
            }
            if (bPC)
            {
                gyro_eigen(gyr, eig, eigv, ord);
                for (d = 0; d < DIM; d++)
                {
                    sum_eig[d] += eig[ord[d]];
                }
            }
            if (outp)
            {
                for (i = ind0; i < ind1-1; i++)
                {
                    rvec_sub(x[index[i+1]], x[index[i]], bond[i-ind0]);
                    unitv(bond[i-ind0], bond[i-ind0]);
                }
                for (i = ind0; i < ind1-1; i++)
                {
                    for (j = 0; (i+j < ind1-1 && j < nat_min/2); j += 2)
                    {
                        sum_inp[j] += iprod(bond[i-ind0], bond[i-ind0+j]);
                        ninp[j]++;
                    }
                }
            }
        }
        sum_eed2 /= nmol;

        sum_gyro = 0;
        for (d = 0; d < DIM; d++)
        {
            for (d2 = 0; d2 < DIM; d2++)
            {
                gyr_all[d][d2] /= nmol;
            }
            sum_gyro += gyr_all[d][d];
        }

        gyro_eigen(gyr_all, eig, eigv, ord);

        fprintf(out, "%10.3f %8.4f %8.4f %8.4f %8.4f %8.4f",
                t*output_env_get_time_factor(oenv),
                std::sqrt(sum_eed2), sqrt(sum_gyro),
                std::sqrt(eig[ord[0]]), std::sqrt(eig[ord[1]]), std::sqrt(eig[ord[2]]));
        if (bPC)
        {
            for (d = 0; d < DIM; d++)
            {
                fprintf(out, " %8.4f", std::sqrt(sum_eig[d]/nmol));
            }
        }
        fprintf(out, "\n");

        if (outv)
        {
            fprintf(outv, "%10.3f", t*output_env_get_time_factor(oenv));
            for (d = 0; d < DIM; d++)
            {
                for (d2 = 0; d2 < DIM; d2++)
                {
                    fprintf(outv, " %6.3f", eigv[ord[d]][d2]);
                }
            }
            fprintf(outv, "\n");
        }

        sum_eed2_tot += sum_eed2;
        sum_gyro_tot += sum_gyro;

        if (outp)
        {
            i = -1;
            for (j = 0; j < nat_min/2; j += 2)
            {
                sum_inp[j] /= ninp[j];
                if (i == -1 && sum_inp[j] <= std::exp(-1.0))
                {
                    i = j;
                }
            }
            if (i == -1)
            {
                pers = j;
            }
            else
            {
                /* Do linear interpolation on a log scale */
                pers = i - 2.0
                    + 2.0*(std::log(sum_inp[i-2]) + 1.0)/(std::log(sum_inp[i-2]) - std::log(sum_inp[i]));
            }
            fprintf(outp, "%10.3f %8.4f\n", t*output_env_get_time_factor(oenv), pers);
            sum_pers_tot += pers;
        }

        frame++;
    }
    while (read_next_x(oenv, status, &t, x, box));

    gmx_rmpbc_done(gpbc);

    close_trx(status);

    xvgrclose(out);
    if (outv)
    {
        xvgrclose(outv);
    }
    if (outp)
    {
        xvgrclose(outp);
    }

    sum_eed2_tot /= frame;
    sum_gyro_tot /= frame;
    sum_pers_tot /= frame;
    fprintf(stdout, "\nAverage end to end distance: %.3f (nm)\n",
            std::sqrt(sum_eed2_tot));
    fprintf(stdout, "\nAverage radius of gyration:  %.3f (nm)\n",
            std::sqrt(sum_gyro_tot));
    if (opt2bSet("-p", NFILE, fnm))
    {
        fprintf(stdout, "\nAverage persistence length:  %.2f bonds\n",
                sum_pers_tot);
    }

    /* Handle printing of internal distances. */
    if (outi)
    {
        if (output_env_get_print_xvgr_codes(oenv))
        {
            fprintf(outi, "@    xaxes scale Logarithmic\n");
        }
        ymax = -1;
        ymin = 1e300;
        j    = index[molind[1]-1] - index[molind[0]]; /* Polymer length -1. */
        for (i = 0; i < j; i++)
        {
            intd[i] /= (i + 1) * frame * nmol;
            if (intd[i] > ymax)
            {
                ymax = intd[i];
            }
            if (intd[i] < ymin)
            {
                ymin = intd[i];
            }
        }
        xvgr_world(outi, 1, ymin, j, ymax, oenv);
        for (i = 0; i < j; i++)
        {
            fprintf(outi, "%d  %8.4f\n", i+1, intd[i]);
        }
        xvgrclose(outi);
    }

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    if (opt2bSet("-v", NFILE, fnm))
    {
        do_view(oenv, opt2fn("-v", NFILE, fnm), "-nxy");
    }
    if (opt2bSet("-p", NFILE, fnm))
    {
        do_view(oenv, opt2fn("-p", NFILE, fnm), "-nxy");
    }

    return 0;
}
Example #22
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 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;
    real     fitparm[4];
    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 = pow(2, 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/(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;
            nb      = (int)(nbr+0.5);
            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/exp(1);
            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] = 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] = sqrt(tau1_est*(n-1)*dt);
                do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv,
                         bDebugMode(), effnERREST, fitparm, 0);
                fitparm[3] = 1-fitparm[1];
            }
            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",
                            sig[s]*anal_ee_inf(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(stderr, "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);
                    fitparm[3] = 1-fitparm[1];
                }
                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",
                                sig[s]*anal_ee_inf(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);
                    fitparm[3] = 1-fitparm[1];
                }
            }
            ee   = sig[s]*anal_ee_inf(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);
        fprintf(fp, "@ legend string %d \"av %f\"\n", 2*s, av[s]);
        fprintf(fp, "@ legend string %d \"ee %6g\"\n",
                2*s+1, sig[s]*anal_ee_inf(fitparm, n*dt));
        for (i = 0; i < nbs; i++)
        {
            fprintf(fp, "%g %g %g\n", tbs[i], sig[s]*sqrt(ybs[i]/(n*dt)),
                    sig[s]*sqrt(fit_function(effnERREST, fitparm, tbs[i])/(n*dt)));
        }

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

            snew(ac, n);
            for (i = 0; i < n; i++)
            {
                ac[i] = val[s][i] - av[s];
                if (i > 0)
                {
                    fitsig[i] = sqrt(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] = 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(), effnEXP3, ac_fit, 0);
            ac_fit[3] = 1 - ac_fit[1];

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

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

            sfree(ac);
        }
        if (s < nset-1)
        {
            fprintf(fp, "&\n");
        }
    }
    sfree(fitsig);
    sfree(ybs);
    sfree(tbs);
    ffclose(fp);
}
Example #23
0
int gmx_rms(int argc, char *argv[])
{
    const char     *desc[] =
    {
        "[THISMODULE] compares two structures by computing the root mean square",
        "deviation (RMSD), the size-independent [GRK]rho[grk] similarity parameter",
        "([TT]rho[tt]) or the scaled [GRK]rho[grk] ([TT]rhosc[tt]), ",
        "see Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).",
        "This is selected by [TT]-what[tt].[PAR]"

        "Each structure from a trajectory ([TT]-f[tt]) is compared to a",
        "reference structure. The reference structure",
        "is taken from the structure file ([TT]-s[tt]).[PAR]",

        "With option [TT]-mir[tt] also a comparison with the mirror image of",
        "the reference structure is calculated.",
        "This is useful as a reference for 'significant' values, see",
        "Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).[PAR]",

        "Option [TT]-prev[tt] produces the comparison with a previous frame",
        "the specified number of frames ago.[PAR]",

        "Option [TT]-m[tt] produces a matrix in [TT].xpm[tt] format of",
        "comparison values of each structure in the trajectory with respect to",
        "each other structure. This file can be visualized with for instance",
        "[TT]xv[tt] and can be converted to postscript with [gmx-xpm2ps].[PAR]",

        "Option [TT]-fit[tt] controls the least-squares fitting of",
        "the structures on top of each other: complete fit (rotation and",
        "translation), translation only, or no fitting at all.[PAR]",

        "Option [TT]-mw[tt] controls whether mass weighting is done or not.",
        "If you select the option (default) and ",
        "supply a valid [TT].tpr[tt] file masses will be taken from there, ",
        "otherwise the masses will be deduced from the [TT]atommass.dat[tt] file in",
        "[TT]GMXLIB[tt]. This is fine for proteins, but not",
        "necessarily for other molecules. A default mass of 12.011 amu (carbon)",
        "is assigned to unknown atoms. You can check whether this happend by",
        "turning on the [TT]-debug[tt] flag and inspecting the log file.[PAR]",

        "With [TT]-f2[tt], the 'other structures' are taken from a second",
        "trajectory, this generates a comparison matrix of one trajectory",
        "versus the other.[PAR]",

        "Option [TT]-bin[tt] does a binary dump of the comparison matrix.[PAR]",

        "Option [TT]-bm[tt] produces a matrix of average bond angle deviations",
        "analogously to the [TT]-m[tt] option. Only bonds between atoms in the",
        "comparison group are considered."
    };
    static gmx_bool bPBC              = TRUE, bFitAll = TRUE, bSplit = FALSE;
    static gmx_bool bDeltaLog         = FALSE;
    static int      prev              = 0, freq = 1, freq2 = 1, nlevels = 80, avl = 0;
    static real     rmsd_user_max     = -1, rmsd_user_min = -1, bond_user_max = -1,
                    bond_user_min     = -1, delta_maxy = 0.0;
    /* strings and things for selecting difference method */
    enum
    {
        ewSel, ewRMSD, ewRho, ewRhoSc, ewNR
    };
    int         ewhat;
    const char *what[ewNR + 1] =
    { NULL, "rmsd", "rho", "rhosc", NULL };
    const char *whatname[ewNR] =
    { NULL, "RMSD", "Rho", "Rho sc" };
    const char *whatlabel[ewNR] =
    { NULL, "RMSD (nm)", "Rho", "Rho sc" };
    const char *whatxvgname[ewNR] =
    { NULL, "RMSD", "\\8r\\4", "\\8r\\4\\ssc\\N" };
    const char *whatxvglabel[ewNR] =
    { NULL, "RMSD (nm)", "\\8r\\4", "\\8r\\4\\ssc\\N" };
    /* strings and things for fitting methods */
    enum
    {
        efSel, efFit, efReset, efNone, efNR
    };
    int             efit;
    const char     *fit[efNR + 1] =
    { NULL, "rot+trans", "translation", "none", NULL };
    const char     *fitgraphlabel[efNR + 1] =
    { NULL, "lsq fit", "translational fit", "no fit" };
    static int      nrms          = 1;
    static gmx_bool bMassWeighted = TRUE;
    t_pargs         pa[]          =
    {
        { "-what", FALSE, etENUM,
          { what }, "Structural difference measure" },
        { "-pbc", FALSE, etBOOL,
          { &bPBC }, "PBC check" },
        { "-fit", FALSE, etENUM,
          { fit }, "Fit to reference structure" },
        { "-prev", FALSE, etINT,
          { &prev }, "Compare with previous frame" },
        { "-split", FALSE, etBOOL,
          { &bSplit }, "Split graph where time is zero" },
        { "-fitall", FALSE, etBOOL,
          { &bFitAll }, "HIDDENFit all pairs of structures in matrix" },
        { "-skip", FALSE, etINT,
          { &freq }, "Only write every nr-th frame to matrix" },
        { "-skip2", FALSE, etINT,
          { &freq2 }, "Only write every nr-th frame to matrix" },
        { "-max", FALSE, etREAL,
          { &rmsd_user_max }, "Maximum level in comparison matrix" },
        { "-min", FALSE, etREAL,
          { &rmsd_user_min }, "Minimum level in comparison matrix" },
        { "-bmax", FALSE, etREAL,
          { &bond_user_max }, "Maximum level in bond angle matrix" },
        { "-bmin", FALSE, etREAL,
          { &bond_user_min }, "Minimum level in bond angle matrix" },
        { "-mw", FALSE, etBOOL,
          { &bMassWeighted }, "Use mass weighting for superposition" },
        { "-nlevels", FALSE, etINT,
          { &nlevels }, "Number of levels in the matrices" },
        { "-ng", FALSE, etINT,
          { &nrms }, "Number of groups to compute RMS between" },
        { "-dlog", FALSE, etBOOL,
          { &bDeltaLog },
          "HIDDENUse a log x-axis in the delta t matrix" },
        { "-dmax", FALSE, etREAL,
          { &delta_maxy }, "HIDDENMaximum level in delta matrix" },
        { "-aver", FALSE, etINT,
          { &avl },
          "HIDDENAverage over this distance in the RMSD matrix" }
    };
    int             natoms_trx, natoms_trx2, natoms;
    int             i, j, k, m, teller, teller2, tel_mat, tel_mat2;
#define NFRAME 5000
    int             maxframe = NFRAME, maxframe2 = NFRAME;
    real            t, *w_rls, *w_rms, *w_rls_m = NULL, *w_rms_m = NULL;
    gmx_bool        bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass;
    gmx_bool        bFit, bReset;
    t_topology      top;
    int             ePBC;
    t_iatom        *iatom = NULL;

    matrix          box;
    rvec           *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1,
                    vec2;
    t_trxstatus    *status;
    char            buf[256], buf2[256];
    int             ncons = 0;
    FILE           *fp;
    real            rlstot = 0, **rls, **rlsm = NULL, *time, *time2, *rlsnorm = NULL,
    **rmsd_mat             = NULL, **bond_mat = NULL, *axis, *axis2, *del_xaxis,
    *del_yaxis, rmsd_max, rmsd_min, rmsd_avg, bond_max, bond_min, ang;
    real       **rmsdav_mat = NULL, av_tot, weight, weight_tot;
    real       **delta      = NULL, delta_max, delta_scalex = 0, delta_scaley = 0,
    *delta_tot;
    int          delta_xsize = 0, del_lev = 100, mx, my, abs_my;
    gmx_bool     bA1, bA2, bPrev, bTop, *bInMat = NULL;
    int          ifit, *irms, ibond = 0, *ind_bond1 = NULL, *ind_bond2 = NULL, n_ind_m =
        0;
    atom_id     *ind_fit, **ind_rms, *ind_m = NULL, *rev_ind_m = NULL, *ind_rms_m =
        NULL;
    char        *gn_fit, **gn_rms;
    t_rgb        rlo, rhi;
    output_env_t oenv;
    gmx_rmpbc_t  gpbc = NULL;

    t_filenm     fnm[] =
    {
        { efTPS, NULL, NULL, ffREAD },
        { efTRX, "-f", NULL, ffREAD },
        { efTRX, "-f2", NULL, ffOPTRD },
        { efNDX, NULL, NULL, ffOPTRD },
        { efXVG, NULL, "rmsd", ffWRITE },
        { efXVG, "-mir", "rmsdmir", ffOPTWR },
        { efXVG, "-a", "avgrp", ffOPTWR },
        { efXVG, "-dist", "rmsd-dist", ffOPTWR },
        { efXPM, "-m", "rmsd", ffOPTWR },
        { efDAT, "-bin", "rmsd", ffOPTWR },
        { efXPM, "-bm", "bond", ffOPTWR }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW
                           | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL,
                           &oenv))
    {
        return 0;
    }
    /* parse enumerated options: */
    ewhat = nenum(what);
    if (ewhat == ewRho || ewhat == ewRhoSc)
    {
        please_cite(stdout, "Maiorov95");
    }
    efit   = nenum(fit);
    bFit   = efit == efFit;
    bReset = efit == efReset;
    if (bFit)
    {
        bReset = TRUE; /* for fit, reset *must* be set */
    }
    else
    {
        bFitAll = FALSE;
    }

    /* mark active cmdline options */
    bMirror = opt2bSet("-mir", NFILE, fnm); /* calc RMSD vs mirror of ref. */
    bFile2  = opt2bSet("-f2", NFILE, fnm);
    bMat    = opt2bSet("-m", NFILE, fnm);
    bBond   = opt2bSet("-bm", NFILE, fnm);
    bDelta  = (delta_maxy > 0); /* calculate rmsd vs delta t matrix from *
                                 *	your RMSD matrix (hidden option       */
    bNorm   = opt2bSet("-a", NFILE, fnm);
    bFreq2  = opt2parg_bSet("-skip2", asize(pa), pa);
    if (freq <= 0)
    {
        fprintf(stderr, "The number of frames to skip is <= 0. "
                "Writing out all frames.\n\n");
        freq = 1;
    }
    if (!bFreq2)
    {
        freq2 = freq;
    }
    else if (bFile2 && freq2 <= 0)
    {
        fprintf(stderr,
                "The number of frames to skip in second trajectory is <= 0.\n"
                "  Writing out all frames.\n\n");
        freq2 = 1;
    }

    bPrev = (prev > 0);
    if (bPrev)
    {
        prev = abs(prev);
        if (freq != 1)
        {
            fprintf(stderr, "WARNING: option -skip also applies to -prev\n");
        }
    }

    if (bFile2 && !bMat && !bBond)
    {
        fprintf(
                stderr,
                "WARNING: second trajectory (-f2) useless when not calculating matrix (-m/-bm),\n"
                "         will not read from %s\n", opt2fn("-f2", NFILE,
                                                           fnm));
        bFile2 = FALSE;
    }

    if (bDelta)
    {
        bMat = TRUE;
        if (bFile2)
        {
            fprintf(stderr,
                    "WARNING: second trajectory (-f2) useless when making delta matrix,\n"
                    "         will not read from %s\n", opt2fn("-f2",
                                                               NFILE, fnm));
            bFile2 = FALSE;
        }
    }

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &xp,
                         NULL, box, TRUE);
    snew(w_rls, top.atoms.nr);
    snew(w_rms, top.atoms.nr);

    if (!bTop && bBond)
    {
        fprintf(stderr,
                "WARNING: Need a run input file for bond angle matrix,\n"
                "         will not calculate bond angle matrix.\n");
        bBond = FALSE;
    }

    if (bReset)
    {
        fprintf(stderr, "Select group for %s fit\n", bFit ? "least squares"
                : "translational");
        get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &ifit,
                  &ind_fit, &gn_fit);
    }
    else
    {
        ifit = 0;
    }

    if (bReset)
    {
        if (bFit && ifit < 3)
        {
            gmx_fatal(FARGS, "Need >= 3 points to fit!\n" );
        }

        bMass = FALSE;
        for (i = 0; i < ifit; i++)
        {
            if (bMassWeighted)
            {
                w_rls[ind_fit[i]] = top.atoms.atom[ind_fit[i]].m;
            }
            else
            {
                w_rls[ind_fit[i]] = 1;
            }
            bMass = bMass || (top.atoms.atom[ind_fit[i]].m != 0);
        }
        if (!bMass)
        {
            fprintf(stderr, "All masses in the fit group are 0, using masses of 1\n");
            for (i = 0; i < ifit; i++)
            {
                w_rls[ind_fit[i]] = 1;
            }
        }
    }

    if (bMat || bBond)
    {
        nrms = 1;
    }

    snew(gn_rms, nrms);
    snew(ind_rms, nrms);
    snew(irms, nrms);

    fprintf(stderr, "Select group%s for %s calculation\n",
            (nrms > 1) ? "s" : "", whatname[ewhat]);
    get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm),
              nrms, irms, ind_rms, gn_rms);

    if (bNorm)
    {
        snew(rlsnorm, irms[0]);
    }
    snew(rls, nrms);
    for (j = 0; j < nrms; j++)
    {
        snew(rls[j], maxframe);
    }
    if (bMirror)
    {
        snew(rlsm, nrms);
        for (j = 0; j < nrms; j++)
        {
            snew(rlsm[j], maxframe);
        }
    }
    snew(time, maxframe);
    for (j = 0; j < nrms; j++)
    {
        bMass = FALSE;
        for (i = 0; i < irms[j]; i++)
        {
            if (bMassWeighted)
            {
                w_rms[ind_rms[j][i]] = top.atoms.atom[ind_rms[j][i]].m;
            }
            else
            {
                w_rms[ind_rms[j][i]] = 1.0;
            }
            bMass = bMass || (top.atoms.atom[ind_rms[j][i]].m != 0);
        }
        if (!bMass)
        {
            fprintf(stderr, "All masses in group %d are 0, using masses of 1\n", j);
            for (i = 0; i < irms[j]; i++)
            {
                w_rms[ind_rms[j][i]] = 1;
            }
        }
    }
    /* Prepare reference frame */
    if (bPBC)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr);
        gmx_rmpbc(gpbc, top.atoms.nr, box, xp);
    }
    if (bReset)
    {
        reset_x(ifit, ind_fit, top.atoms.nr, NULL, xp, w_rls);
    }
    if (bMirror)
    {
        /* generate reference structure mirror image: */
        snew(xm, top.atoms.nr);
        for (i = 0; i < top.atoms.nr; i++)
        {
            copy_rvec(xp[i], xm[i]);
            xm[i][XX] = -xm[i][XX];
        }
    }
    if (ewhat == ewRhoSc)
    {
        norm_princ(&top.atoms, ifit, ind_fit, top.atoms.nr, xp);
    }

    /* read first frame */
    natoms_trx = read_first_x(oenv, &status, opt2fn("-f", NFILE, fnm), &t, &x, box);
    if (natoms_trx != top.atoms.nr)
    {
        fprintf(stderr,
                "\nWARNING: topology has %d atoms, whereas trajectory has %d\n",
                top.atoms.nr, natoms_trx);
    }
    natoms = min(top.atoms.nr, natoms_trx);
    if (bMat || bBond || bPrev)
    {
        snew(mat_x, NFRAME);

        if (bPrev)
        {
            /* With -prev we use all atoms for simplicity */
            n_ind_m = natoms;
        }
        else
        {
            /* Check which atoms we need (fit/rms) */
            snew(bInMat, natoms);
            for (i = 0; i < ifit; i++)
            {
                bInMat[ind_fit[i]] = TRUE;
            }
            n_ind_m = ifit;
            for (i = 0; i < irms[0]; i++)
            {
                if (!bInMat[ind_rms[0][i]])
                {
                    bInMat[ind_rms[0][i]] = TRUE;
                    n_ind_m++;
                }
            }
        }
        /* Make an index of needed atoms */
        snew(ind_m, n_ind_m);
        snew(rev_ind_m, natoms);
        j = 0;
        for (i = 0; i < natoms; i++)
        {
            if (bPrev || bInMat[i])
            {
                ind_m[j]     = i;
                rev_ind_m[i] = j;
                j++;
            }
        }
        snew(w_rls_m, n_ind_m);
        snew(ind_rms_m, irms[0]);
        snew(w_rms_m, n_ind_m);
        for (i = 0; i < ifit; i++)
        {
            w_rls_m[rev_ind_m[ind_fit[i]]] = w_rls[ind_fit[i]];
        }
        for (i = 0; i < irms[0]; i++)
        {
            ind_rms_m[i]          = rev_ind_m[ind_rms[0][i]];
            w_rms_m[ind_rms_m[i]] = w_rms[ind_rms[0][i]];
        }
        sfree(bInMat);
    }

    if (bBond)
    {
        ncons = 0;
        for (k = 0; k < F_NRE; k++)
        {
            if (IS_CHEMBOND(k))
            {
                iatom  = top.idef.il[k].iatoms;
                ncons += top.idef.il[k].nr/3;
            }
        }
        fprintf(stderr, "Found %d bonds in topology\n", ncons);
        snew(ind_bond1, ncons);
        snew(ind_bond2, ncons);
        ibond = 0;
        for (k = 0; k < F_NRE; k++)
        {
            if (IS_CHEMBOND(k))
            {
                iatom = top.idef.il[k].iatoms;
                ncons = top.idef.il[k].nr/3;
                for (i = 0; i < ncons; i++)
                {
                    bA1 = FALSE;
                    bA2 = FALSE;
                    for (j = 0; j < irms[0]; j++)
                    {
                        if (iatom[3*i+1] == ind_rms[0][j])
                        {
                            bA1 = TRUE;
                        }
                        if (iatom[3*i+2] == ind_rms[0][j])
                        {
                            bA2 = TRUE;
                        }
                    }
                    if (bA1 && bA2)
                    {
                        ind_bond1[ibond] = rev_ind_m[iatom[3*i+1]];
                        ind_bond2[ibond] = rev_ind_m[iatom[3*i+2]];
                        ibond++;
                    }
                }
            }
        }
        fprintf(stderr, "Using %d bonds for bond angle matrix\n", ibond);
        if (ibond == 0)
        {
            gmx_fatal(FARGS, "0 bonds found");
        }
    }

    /* start looping over frames: */
    tel_mat = 0;
    teller  = 0;
    do
    {
        if (bPBC)
        {
            gmx_rmpbc(gpbc, natoms, box, x);
        }

        if (bReset)
        {
            reset_x(ifit, ind_fit, natoms, NULL, x, w_rls);
        }
        if (ewhat == ewRhoSc)
        {
            norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
        }

        if (bFit)
        {
            /*do the least squares fit to original structure*/
            do_fit(natoms, w_rls, xp, x);
        }

        if (teller % freq == 0)
        {
            /* keep frame for matrix calculation */
            if (bMat || bBond || bPrev)
            {
                if (tel_mat >= NFRAME)
                {
                    srenew(mat_x, tel_mat+1);
                }
                snew(mat_x[tel_mat], n_ind_m);
                for (i = 0; i < n_ind_m; i++)
                {
                    copy_rvec(x[ind_m[i]], mat_x[tel_mat][i]);
                }
            }
            tel_mat++;
        }

        /*calculate energy of root_least_squares*/
        if (bPrev)
        {
            j = tel_mat-prev-1;
            if (j < 0)
            {
                j = 0;
            }
            for (i = 0; i < n_ind_m; i++)
            {
                copy_rvec(mat_x[j][i], xp[ind_m[i]]);
            }
            if (bReset)
            {
                reset_x(ifit, ind_fit, natoms, NULL, xp, w_rls);
            }
            if (bFit)
            {
                do_fit(natoms, w_rls, x, xp);
            }
        }
        for (j = 0; (j < nrms); j++)
        {
            rls[j][teller] =
                calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xp);
        }
        if (bNorm)
        {
            for (j = 0; (j < irms[0]); j++)
            {
                rlsnorm[j] +=
                    calc_similar_ind(ewhat != ewRMSD, 1, &(ind_rms[0][j]), w_rms, x, xp);
            }
        }

        if (bMirror)
        {
            if (bFit)
            {
                /*do the least squares fit to mirror of original structure*/
                do_fit(natoms, w_rls, xm, x);
            }

            for (j = 0; j < nrms; j++)
            {
                rlsm[j][teller] =
                    calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xm);
            }
        }
        time[teller] = output_env_conv_time(oenv, t);

        teller++;
        if (teller >= maxframe)
        {
            maxframe += NFRAME;
            srenew(time, maxframe);
            for (j = 0; (j < nrms); j++)
            {
                srenew(rls[j], maxframe);
            }
            if (bMirror)
            {
                for (j = 0; (j < nrms); j++)
                {
                    srenew(rlsm[j], maxframe);
                }
            }
        }
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);

    if (bFile2)
    {
        snew(time2, maxframe2);

        fprintf(stderr, "\nWill read second trajectory file\n");
        snew(mat_x2, NFRAME);
        natoms_trx2 =
            read_first_x(oenv, &status, opt2fn("-f2", NFILE, fnm), &t, &x, box);
        if (natoms_trx2 != natoms_trx)
        {
            gmx_fatal(FARGS,
                      "Second trajectory (%d atoms) does not match the first one"
                      " (%d atoms)", natoms_trx2, natoms_trx);
        }
        tel_mat2 = 0;
        teller2  = 0;
        do
        {
            if (bPBC)
            {
                gmx_rmpbc(gpbc, natoms, box, x);
            }

            if (bReset)
            {
                reset_x(ifit, ind_fit, natoms, NULL, x, w_rls);
            }
            if (ewhat == ewRhoSc)
            {
                norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
            }

            if (bFit)
            {
                /*do the least squares fit to original structure*/
                do_fit(natoms, w_rls, xp, x);
            }

            if (teller2 % freq2 == 0)
            {
                /* keep frame for matrix calculation */
                if (bMat)
                {
                    if (tel_mat2 >= NFRAME)
                    {
                        srenew(mat_x2, tel_mat2+1);
                    }
                    snew(mat_x2[tel_mat2], n_ind_m);
                    for (i = 0; i < n_ind_m; i++)
                    {
                        copy_rvec(x[ind_m[i]], mat_x2[tel_mat2][i]);
                    }
                }
                tel_mat2++;
            }

            time2[teller2] = output_env_conv_time(oenv, t);

            teller2++;
            if (teller2 >= maxframe2)
            {
                maxframe2 += NFRAME;
                srenew(time2, maxframe2);
            }
        }
        while (read_next_x(oenv, status, &t, x, box));
        close_trj(status);
    }
    else
    {
        mat_x2   = mat_x;
        time2    = time;
        tel_mat2 = tel_mat;
        freq2    = freq;
    }
    gmx_rmpbc_done(gpbc);

    if (bMat || bBond)
    {
        /* calculate RMS matrix */
        fprintf(stderr, "\n");
        if (bMat)
        {
            fprintf(stderr, "Building %s matrix, %dx%d elements\n",
                    whatname[ewhat], tel_mat, tel_mat2);
            snew(rmsd_mat, tel_mat);
        }
        if (bBond)
        {
            fprintf(stderr, "Building bond angle matrix, %dx%d elements\n",
                    tel_mat, tel_mat2);
            snew(bond_mat, tel_mat);
        }
        snew(axis, tel_mat);
        snew(axis2, tel_mat2);
        rmsd_max = 0;
        if (bFile2)
        {
            rmsd_min = 1e10;
        }
        else
        {
            rmsd_min = 0;
        }
        rmsd_avg = 0;
        bond_max = 0;
        bond_min = 1e10;
        for (j = 0; j < tel_mat2; j++)
        {
            axis2[j] = time2[freq2*j];
        }
        if (bDelta)
        {
            if (bDeltaLog)
            {
                delta_scalex = 8.0/log(2.0);
                delta_xsize  = (int)(log(tel_mat/2)*delta_scalex+0.5)+1;
            }
            else
            {
                delta_xsize = tel_mat/2;
            }
            delta_scaley = 1.0/delta_maxy;
            snew(delta, delta_xsize);
            for (j = 0; j < delta_xsize; j++)
            {
                snew(delta[j], del_lev+1);
            }
            if (avl > 0)
            {
                snew(rmsdav_mat, tel_mat);
                for (j = 0; j < tel_mat; j++)
                {
                    snew(rmsdav_mat[j], tel_mat);
                }
            }
        }

        if (bFitAll)
        {
            snew(mat_x2_j, natoms);
        }
        for (i = 0; i < tel_mat; i++)
        {
            axis[i] = time[freq*i];
            fprintf(stderr, "\r element %5d; time %5.2f  ", i, axis[i]);
            if (bMat)
            {
                snew(rmsd_mat[i], tel_mat2);
            }
            if (bBond)
            {
                snew(bond_mat[i], tel_mat2);
            }
            for (j = 0; j < tel_mat2; j++)
            {
                if (bFitAll)
                {
                    for (k = 0; k < n_ind_m; k++)
                    {
                        copy_rvec(mat_x2[j][k], mat_x2_j[k]);
                    }
                    do_fit(n_ind_m, w_rls_m, mat_x[i], mat_x2_j);
                }
                else
                {
                    mat_x2_j = mat_x2[j];
                }
                if (bMat)
                {
                    if (bFile2 || (i < j))
                    {
                        rmsd_mat[i][j] =
                            calc_similar_ind(ewhat != ewRMSD, irms[0], ind_rms_m,
                                             w_rms_m, mat_x[i], mat_x2_j);
                        if (rmsd_mat[i][j] > rmsd_max)
                        {
                            rmsd_max = rmsd_mat[i][j];
                        }
                        if (rmsd_mat[i][j] < rmsd_min)
                        {
                            rmsd_min = rmsd_mat[i][j];
                        }
                        rmsd_avg += rmsd_mat[i][j];
                    }
                    else
                    {
                        rmsd_mat[i][j] = rmsd_mat[j][i];
                    }
                }
                if (bBond)
                {
                    if (bFile2 || (i <= j))
                    {
                        ang = 0.0;
                        for (m = 0; m < ibond; m++)
                        {
                            rvec_sub(mat_x[i][ind_bond1[m]], mat_x[i][ind_bond2[m]], vec1);
                            rvec_sub(mat_x2_j[ind_bond1[m]], mat_x2_j[ind_bond2[m]], vec2);
                            ang += acos(cos_angle(vec1, vec2));
                        }
                        bond_mat[i][j] = ang*180.0/(M_PI*ibond);
                        if (bond_mat[i][j] > bond_max)
                        {
                            bond_max = bond_mat[i][j];
                        }
                        if (bond_mat[i][j] < bond_min)
                        {
                            bond_min = bond_mat[i][j];
                        }
                    }
                    else
                    {
                        bond_mat[i][j] = bond_mat[j][i];
                    }
                }
            }
        }
        if (bFile2)
        {
            rmsd_avg /= tel_mat*tel_mat2;
        }
        else
        {
            rmsd_avg /= tel_mat*(tel_mat - 1)/2;
        }
        if (bMat && (avl > 0))
        {
            rmsd_max = 0.0;
            rmsd_min = 0.0;
            rmsd_avg = 0.0;
            for (j = 0; j < tel_mat-1; j++)
            {
                for (i = j+1; i < tel_mat; i++)
                {
                    av_tot     = 0;
                    weight_tot = 0;
                    for (my = -avl; my <= avl; my++)
                    {
                        if ((j+my >= 0) && (j+my < tel_mat))
                        {
                            abs_my = abs(my);
                            for (mx = -avl; mx <= avl; mx++)
                            {
                                if ((i+mx >= 0) && (i+mx < tel_mat))
                                {
                                    weight      = (real)(avl+1-max(abs(mx), abs_my));
                                    av_tot     += weight*rmsd_mat[i+mx][j+my];
                                    weight_tot += weight;
                                }
                            }
                        }
                    }
                    rmsdav_mat[i][j] = av_tot/weight_tot;
                    rmsdav_mat[j][i] = rmsdav_mat[i][j];
                    if (rmsdav_mat[i][j] > rmsd_max)
                    {
                        rmsd_max = rmsdav_mat[i][j];
                    }
                }
            }
            rmsd_mat = rmsdav_mat;
        }

        if (bMat)
        {
            fprintf(stderr, "\n%s: Min %f, Max %f, Avg %f\n",
                    whatname[ewhat], rmsd_min, rmsd_max, rmsd_avg);
            rlo.r = 1; rlo.g = 1; rlo.b = 1;
            rhi.r = 0; rhi.g = 0; rhi.b = 0;
            if (rmsd_user_max != -1)
            {
                rmsd_max = rmsd_user_max;
            }
            if (rmsd_user_min != -1)
            {
                rmsd_min = rmsd_user_min;
            }
            if ((rmsd_user_max !=  -1) || (rmsd_user_min != -1))
            {
                fprintf(stderr, "Min and Max value set to resp. %f and %f\n",
                        rmsd_min, rmsd_max);
            }
            sprintf(buf, "%s %s matrix", gn_rms[0], whatname[ewhat]);
            write_xpm(opt2FILE("-m", NFILE, fnm, "w"), 0, buf, whatlabel[ewhat],
                      output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2,
                      axis, axis2, rmsd_mat, rmsd_min, rmsd_max, rlo, rhi, &nlevels);
            /* Print the distribution of RMSD values */
            if (opt2bSet("-dist", NFILE, fnm))
            {
                low_rmsd_dist(opt2fn("-dist", NFILE, fnm), rmsd_max, tel_mat, rmsd_mat, oenv);
            }

            if (bDelta)
            {
                snew(delta_tot, delta_xsize);
                for (j = 0; j < tel_mat-1; j++)
                {
                    for (i = j+1; i < tel_mat; i++)
                    {
                        mx = i-j;
                        if (mx < tel_mat/2)
                        {
                            if (bDeltaLog)
                            {
                                mx = (int)(log(mx)*delta_scalex+0.5);
                            }
                            my             = (int)(rmsd_mat[i][j]*delta_scaley*del_lev+0.5);
                            delta_tot[mx] += 1.0;
                            if ((rmsd_mat[i][j] >= 0) && (rmsd_mat[i][j] <= delta_maxy))
                            {
                                delta[mx][my] += 1.0;
                            }
                        }
                    }
                }
                delta_max = 0;
                for (i = 0; i < delta_xsize; i++)
                {
                    if (delta_tot[i] > 0.0)
                    {
                        delta_tot[i] = 1.0/delta_tot[i];
                        for (j = 0; j <= del_lev; j++)
                        {
                            delta[i][j] *= delta_tot[i];
                            if (delta[i][j] > delta_max)
                            {
                                delta_max = delta[i][j];
                            }
                        }
                    }
                }
                fprintf(stderr, "Maximum in delta matrix: %f\n", delta_max);
                snew(del_xaxis, delta_xsize);
                snew(del_yaxis, del_lev+1);
                for (i = 0; i < delta_xsize; i++)
                {
                    del_xaxis[i] = axis[i]-axis[0];
                }
                for (i = 0; i < del_lev+1; i++)
                {
                    del_yaxis[i] = delta_maxy*i/del_lev;
                }
                sprintf(buf, "%s %s vs. delta t", gn_rms[0], whatname[ewhat]);
                fp = gmx_ffopen("delta.xpm", "w");
                write_xpm(fp, 0, buf, "density", output_env_get_time_label(oenv), whatlabel[ewhat],
                          delta_xsize, del_lev+1, del_xaxis, del_yaxis,
                          delta, 0.0, delta_max, rlo, rhi, &nlevels);
                gmx_ffclose(fp);
            }
            if (opt2bSet("-bin", NFILE, fnm))
            {
                /* NB: File must be binary if we use fwrite */
                fp = ftp2FILE(efDAT, NFILE, fnm, "wb");
                for (i = 0; i < tel_mat; i++)
                {
                    if (fwrite(rmsd_mat[i], sizeof(**rmsd_mat), tel_mat2, fp) != tel_mat2)
                    {
                        gmx_fatal(FARGS, "Error writing to output file");
                    }
                }
                gmx_ffclose(fp);
            }
        }
        if (bBond)
        {
            fprintf(stderr, "\nMin. angle: %f, Max. angle: %f\n", bond_min, bond_max);
            if (bond_user_max != -1)
            {
                bond_max = bond_user_max;
            }
            if (bond_user_min != -1)
            {
                bond_min = bond_user_min;
            }
            if ((bond_user_max !=  -1) || (bond_user_min != -1))
            {
                fprintf(stderr, "Bond angle Min and Max set to:\n"
                        "Min. angle: %f, Max. angle: %f\n", bond_min, bond_max);
            }
            rlo.r = 1; rlo.g = 1; rlo.b = 1;
            rhi.r = 0; rhi.g = 0; rhi.b = 0;
            sprintf(buf, "%s av. bond angle deviation", gn_rms[0]);
            write_xpm(opt2FILE("-bm", NFILE, fnm, "w"), 0, buf, "degrees",
                      output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2,
                      axis, axis2, bond_mat, bond_min, bond_max, rlo, rhi, &nlevels);
        }
    }

    bAv = opt2bSet("-a", NFILE, fnm);

    /* Write the RMSD's to file */
    if (!bPrev)
    {
        sprintf(buf, "%s", whatxvgname[ewhat]);
    }
    else
    {
        sprintf(buf, "%s with frame %g %s ago", whatxvgname[ewhat],
                time[prev*freq]-time[0], output_env_get_time_label(oenv));
    }
    fp = xvgropen(opt2fn("-o", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv),
                  whatxvglabel[ewhat], oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"%s%s after %s%s%s\"\n",
                (nrms == 1) ? "" : "of ", gn_rms[0], fitgraphlabel[efit],
                bFit     ? " to " : "", bFit ? gn_fit : "");
    }
    if (nrms != 1)
    {
        xvgr_legend(fp, nrms, (const char**)gn_rms, oenv);
    }
    for (i = 0; (i < teller); i++)
    {
        if (bSplit && i > 0 &&
            abs(time[bPrev ? freq*i : i]/output_env_get_time_factor(oenv)) < 1e-5)
        {
            fprintf(fp, "&\n");
        }
        fprintf(fp, "%12.7f", time[bPrev ? freq*i : i]);
        for (j = 0; (j < nrms); j++)
        {
            fprintf(fp, " %12.7f", rls[j][i]);
            if (bAv)
            {
                rlstot += rls[j][i];
            }
        }
        fprintf(fp, "\n");
    }
    gmx_ffclose(fp);

    if (bMirror)
    {
        /* Write the mirror RMSD's to file */
        sprintf(buf, "%s with Mirror", whatxvgname[ewhat]);
        sprintf(buf2, "Mirror %s", whatxvglabel[ewhat]);
        fp = xvgropen(opt2fn("-mir", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv),
                      buf2, oenv);
        if (nrms == 1)
        {
            if (output_env_get_print_xvgr_codes(oenv))
            {
                fprintf(fp, "@ subtitle \"of %s after lsq fit to mirror of %s\"\n",
                        gn_rms[0], gn_fit);
            }
        }
        else
        {
            if (output_env_get_print_xvgr_codes(oenv))
            {
                fprintf(fp, "@ subtitle \"after lsq fit to mirror %s\"\n", gn_fit);
            }
            xvgr_legend(fp, nrms, (const char**)gn_rms, oenv);
        }
        for (i = 0; (i < teller); i++)
        {
            if (bSplit && i > 0 && abs(time[i]) < 1e-5)
            {
                fprintf(fp, "&\n");
            }
            fprintf(fp, "%12.7f", time[i]);
            for (j = 0; (j < nrms); j++)
            {
                fprintf(fp, " %12.7f", rlsm[j][i]);
            }
            fprintf(fp, "\n");
        }
        gmx_ffclose(fp);
    }

    if (bAv)
    {
        sprintf(buf, "Average %s", whatxvgname[ewhat]);
        sprintf(buf2, "Average %s", whatxvglabel[ewhat]);
        fp = xvgropen(opt2fn("-a", NFILE, fnm), buf, "Residue", buf2, oenv);
        for (j = 0; (j < nrms); j++)
        {
            fprintf(fp, "%10d  %10g\n", j, rlstot/teller);
        }
        gmx_ffclose(fp);
    }

    if (bNorm)
    {
        fp = xvgropen("aver.xvg", gn_rms[0], "Residue", whatxvglabel[ewhat], oenv);
        for (j = 0; (j < irms[0]); j++)
        {
            fprintf(fp, "%10d  %10g\n", j, rlsnorm[j]/teller);
        }
        gmx_ffclose(fp);
    }
    do_view(oenv, opt2fn_null("-a", NFILE, fnm), "-graphtype bar");
    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);
    do_view(oenv, opt2fn_null("-mir", NFILE, fnm), NULL);
    do_view(oenv, opt2fn_null("-m", NFILE, fnm), NULL);
    do_view(oenv, opt2fn_null("-bm", NFILE, fnm), NULL);
    do_view(oenv, opt2fn_null("-dist", NFILE, fnm), NULL);

    return 0;
}
Example #24
0
int gmx_sorient(int argc, char *argv[])
{
    t_topology        top;
    int               ePBC = -1;
    t_trxstatus      *status;
    int               natoms;
    real              t;
    rvec             *xtop, *x;
    matrix            box;

    FILE             *fp;
    int               i, p, sa0, sa1, sa2, n, ntot, nf, m, *hist1, *hist2, *histn, nbin1, nbin2, nrbin;
    real             *histi1, *histi2, invbw, invrbw;
    double            sum1, sum2;
    int              *isize, nrefgrp, nrefat;
    int             **index;
    char            **grpname;
    real              inp, outp, nav, normfac, rmin2, rmax2, rcut, rcut2, r2, r;
    real              c1, c2;
    char              str[STRLEN];
    gmx_bool          bTPS;
    rvec              xref, dx, dxh1, dxh2, outer;
    gmx_rmpbc_t       gpbc = NULL;
    t_pbc             pbc;
    const char       *legr[] = {
        "<cos(\\8q\\4\\s1\\N)>",
        "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>"
    };
    const char       *legc[] = {
        "cos(\\8q\\4\\s1\\N)",
        "3cos\\S2\\N(\\8q\\4\\s2\\N)-1"
    };

    const char       *desc[] = {
        "[THISMODULE] analyzes solvent orientation around solutes.",
        "It calculates two angles between the vector from one or more",
        "reference positions to the first atom of each solvent molecule:",
        "",
        " * [GRK]theta[grk][SUB]1[sub]: the angle with the vector from the first atom of the solvent",
        "   molecule to the midpoint between atoms 2 and 3.",
        " * [GRK]theta[grk][SUB]2[sub]: the angle with the normal of the solvent plane, defined by the",
        "   same three atoms, or, when the option [TT]-v23[tt] is set, ",
        "   the angle with the vector between atoms 2 and 3.",
        "",
        "The reference can be a set of atoms or",
        "the center of mass of a set of atoms. The group of solvent atoms should",
        "consist of 3 atoms per solvent molecule.",
        "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are",
        "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]",
        "[TT]-o[tt]: distribtion of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] for rmin<=r<=rmax.[PAR]",
        "[TT]-no[tt]: distribution of [MATH][COS][GRK]theta[grk][SUB]2[sub][cos][math] for rmin<=r<=rmax.[PAR]",
        "[TT]-ro[tt]: [MATH][CHEVRON][COS][GRK]theta[grk][SUB]1[sub][cos][chevron][math] and [MATH][CHEVRON]3[COS]^2[GRK]theta[grk][SUB]2[sub][cos]-1[chevron][math] as a function of the",
        "distance.[PAR]",
        "[TT]-co[tt]: the sum over all solvent molecules within distance r",
        "of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] and [MATH]3[COS]^2([GRK]theta[grk][SUB]2[sub])-1[cos][math] as a function of r.[PAR]",
        "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r"
    };

    gmx_output_env_t *oenv;
    static gmx_bool   bCom = FALSE, bVec23 = FALSE, bPBC = FALSE;
    static real       rmin = 0.0, rmax = 0.5, binwidth = 0.02, rbinw = 0.02;
    t_pargs           pa[] = {
        {   "-com",  FALSE, etBOOL,  {&bCom},
            "Use the center of mass as the reference postion"
        },
        {   "-v23",  FALSE, etBOOL,  {&bVec23},
            "Use the vector between atoms 2 and 3"
        },
        { "-rmin",  FALSE, etREAL, {&rmin}, "Minimum distance (nm)" },
        { "-rmax",  FALSE, etREAL, {&rmax}, "Maximum distance (nm)" },
        { "-cbin",  FALSE, etREAL, {&binwidth}, "Binwidth for the cosine" },
        { "-rbin",  FALSE, etREAL, {&rbinw}, "Binwidth for r (nm)" },
        { "-pbc",   FALSE, etBOOL, {&bPBC}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." }
    };

    t_filenm          fnm[] = {
        { efTRX, NULL,  NULL,  ffREAD },
        { efTPS, NULL,  NULL,  ffREAD },
        { efNDX, NULL,  NULL,  ffOPTRD },
        { efXVG, NULL,  "sori",   ffWRITE },
        { efXVG, "-no", "snor",   ffWRITE },
        { efXVG, "-ro", "sord",   ffWRITE },
        { efXVG, "-co", "scum",   ffWRITE },
        { efXVG, "-rc", "scount", ffWRITE }
    };
#define NFILE asize(fnm)

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

    bTPS = (opt2bSet("-s", NFILE, fnm) || !opt2bSet("-n", NFILE, fnm) || bCom);
    if (bTPS)
    {
        read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, NULL, box,
                      bCom);
    }

    /* get index groups */
    printf("Select a group of reference particles and a solvent group:\n");
    snew(grpname, 2);
    snew(index, 2);
    snew(isize, 2);
    if (bTPS)
    {
        get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname);
    }
    else
    {
        get_index(NULL, ftp2fn(efNDX, NFILE, fnm), 2, isize, index, grpname);
    }

    if (bCom)
    {
        nrefgrp = 1;
        nrefat  = isize[0];
    }
    else
    {
        nrefgrp = isize[0];
        nrefat  = 1;
    }

    if (isize[1] % 3)
    {
        gmx_fatal(FARGS, "The number of solvent atoms (%d) is not a multiple of 3",
                  isize[1]);
    }

    /* initialize reading trajectory:                         */
    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    rmin2 = sqr(rmin);
    rmax2 = sqr(rmax);
    rcut  = 0.99*std::sqrt(max_cutoff2(guess_ePBC(box), box));
    if (rcut == 0)
    {
        rcut = 10*rmax;
    }
    rcut2 = sqr(rcut);

    invbw = 1/binwidth;
    nbin1 = 1+static_cast<int>(2*invbw + 0.5);
    nbin2 = 1+static_cast<int>(invbw + 0.5);

    invrbw = 1/rbinw;

    snew(hist1, nbin1);
    snew(hist2, nbin2);
    nrbin = 1+static_cast<int>(rcut/rbinw);
    if (nrbin == 0)
    {
        nrbin = 1;
    }
    snew(histi1, nrbin);
    snew(histi2, nrbin);
    snew(histn, nrbin);

    ntot = 0;
    nf   = 0;
    sum1 = 0;
    sum2 = 0;

    if (bTPS)
    {
        /* make molecules whole again */
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    }
    /* start analysis of trajectory */
    do
    {
        if (bTPS)
        {
            /* make molecules whole again */
            gmx_rmpbc(gpbc, natoms, box, x);
        }

        set_pbc(&pbc, ePBC, box);
        n    = 0;
        inp  = 0;
        for (p = 0; (p < nrefgrp); p++)
        {
            if (bCom)
            {
                calc_com_pbc(nrefat, &top, x, &pbc, index[0], xref, bPBC);
            }
            else
            {
                copy_rvec(x[index[0][p]], xref);
            }

            for (m = 0; m < isize[1]; m += 3)
            {
                sa0 = index[1][m];
                sa1 = index[1][m+1];
                sa2 = index[1][m+2];
                range_check(sa0, 0, natoms);
                range_check(sa1, 0, natoms);
                range_check(sa2, 0, natoms);
                pbc_dx(&pbc, x[sa0], xref, dx);
                r2  = norm2(dx);
                if (r2 < rcut2)
                {
                    r = std::sqrt(r2);
                    if (!bVec23)
                    {
                        /* Determine the normal to the plain */
                        rvec_sub(x[sa1], x[sa0], dxh1);
                        rvec_sub(x[sa2], x[sa0], dxh2);
                        rvec_inc(dxh1, dxh2);
                        svmul(1/r, dx, dx);
                        unitv(dxh1, dxh1);
                        inp = iprod(dx, dxh1);
                        cprod(dxh1, dxh2, outer);
                        unitv(outer, outer);
                        outp = iprod(dx, outer);
                    }
                    else
                    {
                        /* Use the vector between the 2nd and 3rd atom */
                        rvec_sub(x[sa2], x[sa1], dxh2);
                        unitv(dxh2, dxh2);
                        outp = iprod(dx, dxh2)/r;
                    }
                    {
                        int ii = static_cast<int>(invrbw*r);
                        range_check(ii, 0, nrbin);
                        histi1[ii] += inp;
                        histi2[ii] += 3*sqr(outp) - 1;
                        histn[ii]++;
                    }
                    if ((r2 >= rmin2) && (r2 < rmax2))
                    {
                        int ii1 = static_cast<int>(invbw*(inp + 1));
                        int ii2 = static_cast<int>(invbw*std::abs(outp));

                        range_check(ii1, 0, nbin1);
                        range_check(ii2, 0, nbin2);
                        hist1[ii1]++;
                        hist2[ii2]++;
                        sum1 += inp;
                        sum2 += outp;
                        n++;
                    }
                }
            }
        }
        ntot += n;
        nf++;

    }
    while (read_next_x(oenv, status, &t, x, box));

    /* clean up */
    sfree(x);
    close_trj(status);
    gmx_rmpbc_done(gpbc);

    /* Add the bin for the exact maximum to the previous bin */
    hist1[nbin1-1] += hist1[nbin1];
    hist2[nbin2-1] += hist2[nbin2];

    nav     = static_cast<real>(ntot)/(nrefgrp*nf);
    normfac = invbw/ntot;

    fprintf(stderr,  "Average nr of molecules between %g and %g nm: %.1f\n",
            rmin, rmax, nav);
    if (ntot > 0)
    {
        sum1 /= ntot;
        sum2 /= ntot;
        fprintf(stderr, "Average cos(theta1)     between %g and %g nm: %6.3f\n",
                rmin, rmax, sum1);
        fprintf(stderr, "Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n",
                rmin, rmax, sum2);
    }

    sprintf(str, "Solvent orientation between %g and %g nm", rmin, rmax);
    fp = xvgropen(opt2fn("-o", NFILE, fnm), str, "cos(\\8q\\4\\s1\\N)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav);
    }
    for (i = 0; i < nbin1; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*binwidth-1, 2*normfac*hist1[i]);
    }
    xvgrclose(fp);

    sprintf(str, "Solvent normal orientation between %g and %g nm", rmin, rmax);
    fp = xvgropen(opt2fn("-no", NFILE, fnm), str, "cos(\\8q\\4\\s2\\N)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav);
    }
    for (i = 0; i < nbin2; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*binwidth, normfac*hist2[i]);
    }
    xvgrclose(fp);


    sprintf(str, "Solvent orientation");
    fp = xvgropen(opt2fn("-ro", NFILE, fnm), str, "r (nm)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    xvgr_legend(fp, 2, legr, oenv);
    for (i = 0; i < nrbin; i++)
    {
        fprintf(fp, "%g %g %g\n", (i+0.5)*rbinw,
                histn[i] ? histi1[i]/histn[i] : 0,
                histn[i] ? histi2[i]/histn[i] : 0);
    }
    xvgrclose(fp);

    sprintf(str, "Cumulative solvent orientation");
    fp = xvgropen(opt2fn("-co", NFILE, fnm), str, "r (nm)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    xvgr_legend(fp, 2, legc, oenv);
    normfac = 1.0/(nrefgrp*nf);
    c1      = 0;
    c2      = 0;
    fprintf(fp, "%g %g %g\n", 0.0, c1, c2);
    for (i = 0; i < nrbin; i++)
    {
        c1 += histi1[i]*normfac;
        c2 += histi2[i]*normfac;
        fprintf(fp, "%g %g %g\n", (i+1)*rbinw, c1, c2);
    }
    xvgrclose(fp);

    sprintf(str, "Solvent distribution");
    fp = xvgropen(opt2fn("-rc", NFILE, fnm), str, "r (nm)", "molecules/nm", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    normfac = 1.0/(rbinw*nf);
    for (i = 0; i < nrbin; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*rbinw, histn[i]*normfac);
    }
    xvgrclose(fp);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-no", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-ro", NFILE, fnm), "-nxy");
    do_view(oenv, opt2fn("-co", NFILE, fnm), "-nxy");

    return 0;
}
Example #25
0
int gmx_bundle(int argc,char *argv[])
{
  const char *desc[] = {
    "g_bundle analyzes bundles of axes. The axes can be for instance",
    "helix axes. The program reads two index groups and divides both",
    "of them in [TT]-na[tt] parts. The centers of mass of these parts",
    "define the tops and bottoms of the axes.",
    "Several quantities are written to file:",
    "the axis length, the distance and the z-shift of the axis mid-points",
    "with respect to the average center of all axes, the total tilt,",
    "the radial tilt and the lateral tilt with respect to the average axis.",
    "[PAR]",
    "With options [TT]-ok[tt], [TT]-okr[tt] and [TT]-okl[tt] the total,",
    "radial and lateral kinks of the axes are plotted. An extra index",
    "group of kink atoms is required, which is also divided into [TT]-na[tt]",
    "parts. The kink angle is defined as the angle between the kink-top and",
    "the bottom-kink vectors.",
    "[PAR]",
    "With option [TT]-oa[tt] the top, mid (or kink when [TT]-ok[tt] is set)",
    "and bottom points of each axis",
    "are written to a pdb file each frame. The residue numbers correspond",
    "to the axis numbers. When viewing this file with [TT]rasmol[tt], use the",
    "command line option [TT]-nmrpdb[tt], and type [TT]set axis true[tt] to",
    "display the reference axis."
  };
  static int  n=0;
  static gmx_bool bZ=FALSE;
  t_pargs pa[] = {
    { "-na", FALSE, etINT, {&n},
	"Number of axes" },
    { "-z", FALSE, etBOOL, {&bZ},
	"Use the Z-axis as reference iso the average axis" }
  };
  FILE       *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl;
  FILE       *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL;
  t_trxstatus *status;
  t_trxstatus *fpdb;
  t_topology top;
  int        ePBC;
  rvec       *xtop;
  matrix     box;
  t_trxframe fr;
  t_atoms    outatoms;
  real       t,comp;
  int        natoms;
  char       *grpname[MAX_ENDS],title[256];
  /* FIXME: The constness should not be cast away */
  char       *anm=(char *)"CA",*rnm=(char *)"GLY";
  int        i,j,gnx[MAX_ENDS];
  atom_id    *index[MAX_ENDS];
  t_bundle   bun;
  gmx_bool       bKink;
  rvec       va,vb,vc,vr,vl;
  output_env_t oenv;
  gmx_rmpbc_t  gpbc=NULL;
  
#define NLEG asize(leg) 
  t_filenm fnm[] = { 
    { efTRX, "-f", NULL, ffREAD }, 
    { efTPS, NULL, NULL, ffREAD }, 
    { efNDX, NULL, NULL, ffOPTRD },
    { efXVG, "-ol", "bun_len", ffWRITE },
    { efXVG, "-od", "bun_dist", ffWRITE },
    { efXVG, "-oz", "bun_z", ffWRITE },
    { efXVG, "-ot", "bun_tilt", ffWRITE },
    { efXVG, "-otr", "bun_tiltr", ffWRITE },
    { efXVG, "-otl", "bun_tiltl", ffWRITE },
    { efXVG, "-ok", "bun_kink", ffOPTWR },
    { efXVG, "-okr", "bun_kinkr", ffOPTWR },
    { efXVG, "-okl", "bun_kinkl", ffOPTWR },
    { efPDB, "-oa", "axes", ffOPTWR }
  }; 
#define NFILE asize(fnm) 

  CopyRight(stderr,argv[0]); 
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); 

  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,TRUE);

  bKink = opt2bSet("-ok",NFILE,fnm) || opt2bSet("-okr",NFILE,fnm) 
    || opt2bSet("-okl",NFILE,fnm);
  if (bKink)
    bun.nend = 3;
  else
    bun.nend = 2;
  
  fprintf(stderr,"Select a group of top and a group of bottom ");
  if (bKink)
    fprintf(stderr,"and a group of kink ");
  fprintf(stderr,"atoms\n");
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),bun.nend,
	    gnx,index,grpname);

  if (n<=0 || gnx[0] % n || gnx[1] % n || (bKink && gnx[2] % n))
    gmx_fatal(FARGS,
		"The size of one of your index groups is not a multiple of n");
  bun.n = n;
  snew(bun.end[0],n);
  snew(bun.end[1],n);
  if (bKink)
    snew(bun.end[2],n);
  snew(bun.mid,n);
  snew(bun.dir,n);
  snew(bun.len,n);

  flen   = xvgropen(opt2fn("-ol",NFILE,fnm),"Axis lengths",
		    output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
  fdist  = xvgropen(opt2fn("-od",NFILE,fnm),"Distance of axis centers",
		    output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
  fz     = xvgropen(opt2fn("-oz",NFILE,fnm),"Z-shift of axis centers",
		    output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
  ftilt  = xvgropen(opt2fn("-ot",NFILE,fnm),"Axis tilts",
		    output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
  ftiltr = xvgropen(opt2fn("-otr",NFILE,fnm),"Radial axis tilts",
		    output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
  ftiltl = xvgropen(opt2fn("-otl",NFILE,fnm),"Lateral axis tilts",
		    output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
  
  if (bKink) {
    fkink  = xvgropen(opt2fn("-ok",NFILE,fnm),"Kink angles",
		      output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
    fkinkr = xvgropen(opt2fn("-okr",NFILE,fnm),"Radial kink angles",
		      output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
    if (output_env_get_print_xvgr_codes(oenv))
      fprintf(fkinkr,"@ subtitle \"+ = ) (   - = ( )\"\n");
    fkinkl = xvgropen(opt2fn("-okl",NFILE,fnm),"Lateral kink angles",
		      output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
  }

  if (opt2bSet("-oa",NFILE,fnm)) {
    init_t_atoms(&outatoms,3*n,FALSE);
    outatoms.nr = 3*n;
    for(i=0; i<3*n; i++) {
      outatoms.atomname[i] = &anm;
      outatoms.atom[i].resind = i/3;
      outatoms.resinfo[i/3].name = &rnm;
      outatoms.resinfo[i/3].nr   = i/3 + 1;
      outatoms.resinfo[i/3].ic   = ' ';
    }
    fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
  } else
    fpdb = NULL;
  
  read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X); 
  gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);

  do {
    gmx_rmpbc_trxfr(gpbc,&fr);
    calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
    t = output_env_conv_time(oenv,fr.time);
    fprintf(flen," %10g",t);
    fprintf(fdist," %10g",t);
    fprintf(fz," %10g",t);
    fprintf(ftilt," %10g",t);
    fprintf(ftiltr," %10g",t);
    fprintf(ftiltl," %10g",t);
    if (bKink) {
      fprintf(fkink," %10g",t);
      fprintf(fkinkr," %10g",t);
      fprintf(fkinkl," %10g",t);
    }

    for(i=0; i<bun.n; i++) {
      fprintf(flen," %6g",bun.len[i]);
      fprintf(fdist," %6g",norm(bun.mid[i]));
      fprintf(fz," %6g",bun.mid[i][ZZ]);
      fprintf(ftilt," %6g",RAD2DEG*acos(bun.dir[i][ZZ]));
      comp = bun.mid[i][XX]*bun.dir[i][XX]+bun.mid[i][YY]*bun.dir[i][YY];
      fprintf(ftiltr," %6g",RAD2DEG*
	      asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
      comp = bun.mid[i][YY]*bun.dir[i][XX]-bun.mid[i][XX]*bun.dir[i][YY];
      fprintf(ftiltl," %6g",RAD2DEG*
	      asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
      if (bKink) {
	rvec_sub(bun.end[0][i],bun.end[2][i],va);
	rvec_sub(bun.end[2][i],bun.end[1][i],vb);
	unitv_no_table(va,va);
	unitv_no_table(vb,vb);
	fprintf(fkink," %6g",RAD2DEG*acos(iprod(va,vb)));
	cprod(va,vb,vc);
	copy_rvec(bun.mid[i],vr);
	vr[ZZ] = 0;
	unitv_no_table(vr,vr);
	fprintf(fkinkr," %6g",RAD2DEG*asin(iprod(vc,vr)));
	vl[XX] = vr[YY];
	vl[YY] = -vr[XX];
	vl[ZZ] = 0;
	fprintf(fkinkl," %6g",RAD2DEG*asin(iprod(vc,vl)));
      }
    }
    fprintf(flen,"\n");
    fprintf(fdist,"\n");
    fprintf(fz,"\n");
    fprintf(ftilt,"\n");
    fprintf(ftiltr,"\n");
    fprintf(ftiltl,"\n");
    if (bKink) {
      fprintf(fkink,"\n");
      fprintf(fkinkr,"\n");
      fprintf(fkinkl,"\n");
    }
    if (fpdb )
      dump_axes(fpdb,&fr,&outatoms,&bun);
  } while(read_next_frame(oenv,status,&fr));
  gmx_rmpbc_done(gpbc);

  close_trx(status);
  
  if (fpdb )
    close_trx(fpdb);
  ffclose(flen);
  ffclose(fdist);
  ffclose(fz);
  ffclose(ftilt);
  ffclose(ftiltr);
  ffclose(ftiltl);
  if (bKink) {
    ffclose(fkink);
    ffclose(fkinkr);
    ffclose(fkinkl);
  }
  
  thanx(stderr);
  
  return 0;
}
int gmx_vanhove(int argc, char *argv[])
{
    const char *desc[] = {
        "[THISMODULE] computes the Van Hove correlation function.",
        "The Van Hove G(r,t) is the probability that a particle that is at r[SUB]0[sub]",
        "at time zero can be found at position r[SUB]0[sub]+r at time t.",
        "[THISMODULE] determines G not for a vector r, but for the length of r.",
        "Thus it gives the probability that a particle moves a distance of r",
        "in time t.",
        "Jumps across the periodic boundaries are removed.",
        "Corrections are made for scaling due to isotropic",
        "or anisotropic pressure coupling.",
        "[PAR]",
        "With option [TT]-om[tt] the whole matrix can be written as a function",
        "of t and r or as a function of [SQRT]t[sqrt] and r (option [TT]-sqrt[tt]).",
        "[PAR]",
        "With option [TT]-or[tt] the Van Hove function is plotted for one",
        "or more values of t. Option [TT]-nr[tt] sets the number of times,",
        "option [TT]-fr[tt] the number spacing between the times.",
        "The binwidth is set with option [TT]-rbin[tt]. The number of bins",
        "is determined automatically.",
        "[PAR]",
        "With option [TT]-ot[tt] the integral up to a certain distance",
        "(option [TT]-rt[tt]) is plotted as a function of time.",
        "[PAR]",
        "For all frames that are read the coordinates of the selected particles",
        "are stored in memory. Therefore the program may use a lot of memory.",
        "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.",
        "This is because the calculation scales as the number of frames times",
        "[TT]-fm[tt] or [TT]-ft[tt].",
        "Note that with the [TT]-dt[tt] option the memory usage and calculation",
        "time can be reduced."
    };
    static int  fmmax = 0, ftmax = 0, nlev = 81, nr = 1, fshift = 0;
    static real sbin  = 0, rmax = 2, rbin = 0.01, mmax = 0, rint = 0;
    t_pargs     pa[]  = {
        { "-sqrt",    FALSE, etREAL, {&sbin},
          "Use [SQRT]t[sqrt] on the matrix axis which binspacing # in [SQRT]ps[sqrt]" },
        { "-fm",      FALSE, etINT, {&fmmax},
          "Number of frames in the matrix, 0 is plot all" },
        { "-rmax",    FALSE, etREAL, {&rmax},
          "Maximum r in the matrix (nm)" },
        { "-rbin",    FALSE, etREAL, {&rbin},
          "Binwidth in the matrix and for [TT]-or[tt] (nm)" },
        { "-mmax",    FALSE, etREAL, {&mmax},
          "Maximum density in the matrix, 0 is calculate (1/nm)" },
        { "-nlevels", FALSE, etINT,  {&nlev},
          "Number of levels in the matrix" },
        { "-nr",      FALSE, etINT, {&nr},
          "Number of curves for the [TT]-or[tt] output" },
        { "-fr",      FALSE, etINT, {&fshift},
          "Frame spacing for the [TT]-or[tt] output" },
        { "-rt",      FALSE, etREAL, {&rint},
          "Integration limit for the [TT]-ot[tt] output (nm)" },
        { "-ft",      FALSE, etINT, {&ftmax},
          "Number of frames in the [TT]-ot[tt] output, 0 is plot all" }
    };
#define NPA asize(pa)

    t_filenm fnm[] = {
        { efTRX, NULL, NULL,  ffREAD },
        { efTPS, NULL, NULL,  ffREAD },
        { efNDX, NULL, NULL,  ffOPTRD },
        { efXPM, "-om", "vanhove", ffOPTWR },
        { efXVG, "-or", "vanhove_r", ffOPTWR },
        { efXVG, "-ot", "vanhove_t", ffOPTWR }
    };
#define NFILE asize(fnm)

    output_env_t oenv;
    const char  *matfile, *otfile, *orfile;
    char         title[256];
    t_topology   top;
    int          ePBC;
    matrix       boxtop, box, *sbox, avbox, corr;
    rvec        *xtop, *x, **sx;
    int          isize, nalloc, nallocn, natom;
    t_trxstatus *status;
    atom_id     *index;
    char        *grpname;
    int          nfr, f, ff, i, m, mat_nx = 0, nbin = 0, bin, mbin, fbin;
    real        *time, t, invbin = 0, rmax2 = 0, rint2 = 0, d2;
    real         invsbin = 0, matmax, normfac, dt, *tickx, *ticky;
    char         buf[STRLEN], **legend;
    real       **mat = NULL;
    int         *pt  = NULL, **pr = NULL, *mcount = NULL, *tcount = NULL, *rcount = NULL;
    FILE        *fp;
    t_rgb        rlo = {1, 1, 1}, rhi = {0, 0, 0};

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

    matfile = opt2fn_null("-om", NFILE, fnm);
    if (opt2parg_bSet("-fr", NPA, pa))
    {
        orfile  = opt2fn("-or", NFILE, fnm);
    }
    else
    {
        orfile  = opt2fn_null("-or", NFILE, fnm);
    }
    if (opt2parg_bSet("-rt", NPA, pa))
    {
        otfile  = opt2fn("-ot", NFILE, fnm);
    }
    else
    {
        otfile  = opt2fn_null("-ot", NFILE, fnm);
    }

    if (!matfile && !otfile && !orfile)
    {
        fprintf(stderr,
                "For output set one (or more) of the output file options\n");
        exit(0);
    }

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, boxtop,
                  FALSE);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);

    nalloc = 0;
    time   = NULL;
    sbox   = NULL;
    sx     = NULL;
    clear_mat(avbox);

    natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    nfr   = 0;
    do
    {
        if (nfr >= nalloc)
        {
            nalloc += 100;
            srenew(time, nalloc);
            srenew(sbox, nalloc);
            srenew(sx, nalloc);
        }

        time[nfr] = t;
        copy_mat(box, sbox[nfr]);
        /* This assumes that the off-diagonal box elements
         * are not affected by jumps across the periodic boundaries.
         */
        m_add(avbox, box, avbox);
        snew(sx[nfr], isize);
        for (i = 0; i < isize; i++)
        {
            copy_rvec(x[index[i]], sx[nfr][i]);
        }

        nfr++;
    }
    while (read_next_x(oenv, status, &t, x, box));

    /* clean up */
    sfree(x);
    close_trj(status);

    fprintf(stderr, "Read %d frames\n", nfr);

    dt = (time[nfr-1] - time[0])/(nfr - 1);
    /* Some ugly rounding to get nice nice times in the output */
    dt = (int)(10000.0*dt + 0.5)/10000.0;

    invbin = 1.0/rbin;

    if (matfile)
    {
        if (fmmax <= 0 || fmmax >= nfr)
        {
            fmmax = nfr - 1;
        }
        snew(mcount, fmmax);
        nbin = (int)(rmax*invbin + 0.5);
        if (sbin == 0)
        {
            mat_nx = fmmax + 1;
        }
        else
        {
            invsbin = 1.0/sbin;
            mat_nx  = sqrt(fmmax*dt)*invsbin + 1;
        }
        snew(mat, mat_nx);
        for (f = 0; f < mat_nx; f++)
        {
            snew(mat[f], nbin);
        }
        rmax2 = sqr(nbin*rbin);
        /* Initialize time zero */
        mat[0][0]  = nfr*isize;
        mcount[0] += nfr;
    }
    else
    {
        fmmax = 0;
    }

    if (orfile)
    {
        snew(pr, nr);
        nalloc = 0;
        snew(rcount, nr);
    }

    if (otfile)
    {
        if (ftmax <= 0)
        {
            ftmax = nfr - 1;
        }
        snew(tcount, ftmax);
        snew(pt, nfr);
        rint2 = rint*rint;
        /* Initialize time zero */
        pt[0]      = nfr*isize;
        tcount[0] += nfr;
    }
    else
    {
        ftmax = 0;
    }

    msmul(avbox, 1.0/nfr, avbox);
    for (f = 0; f < nfr; f++)
    {
        if (f % 100 == 0)
        {
            fprintf(stderr, "\rProcessing frame %d", f);
        }
        /* Scale all the configuration to the average box */
        m_inv_ur0(sbox[f], corr);
        mmul_ur0(avbox, corr, corr);
        for (i = 0; i < isize; i++)
        {
            mvmul_ur0(corr, sx[f][i], sx[f][i]);
            if (f > 0)
            {
                /* Correct for periodic jumps */
                for (m = DIM-1; m >= 0; m--)
                {
                    while (sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m])
                    {
                        rvec_dec(sx[f][i], avbox[m]);
                    }
                    while (sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m])
                    {
                        rvec_inc(sx[f][i], avbox[m]);
                    }
                }
            }
        }
        for (ff = 0; ff < f; ff++)
        {
            fbin = f - ff;
            if (fbin <= fmmax || fbin <= ftmax)
            {
                if (sbin == 0)
                {
                    mbin = fbin;
                }
                else
                {
                    mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5);
                }
                for (i = 0; i < isize; i++)
                {
                    d2 = distance2(sx[f][i], sx[ff][i]);
                    if (mbin < mat_nx && d2 < rmax2)
                    {
                        bin = (int)(sqrt(d2)*invbin + 0.5);
                        if (bin < nbin)
                        {
                            mat[mbin][bin] += 1;
                        }
                    }
                    if (fbin <= ftmax && d2 <= rint2)
                    {
                        pt[fbin]++;
                    }
                }
                if (matfile)
                {
                    mcount[mbin]++;
                }
                if (otfile)
                {
                    tcount[fbin]++;
                }
            }
        }
        if (orfile)
        {
            for (fbin = 0; fbin < nr; fbin++)
            {
                ff = f - (fbin + 1)*fshift;
                if (ff >= 0)
                {
                    for (i = 0; i < isize; i++)
                    {
                        d2  = distance2(sx[f][i], sx[ff][i]);
                        bin = (int)(sqrt(d2)*invbin + 0.5);
                        if (bin >= nalloc)
                        {
                            nallocn = 10*(bin/10) + 11;
                            for (m = 0; m < nr; m++)
                            {
                                srenew(pr[m], nallocn);
                                for (i = nalloc; i < nallocn; i++)
                                {
                                    pr[m][i] = 0;
                                }
                            }
                            nalloc = nallocn;
                        }
                        pr[fbin][bin]++;
                    }
                    rcount[fbin]++;
                }
            }
        }
    }
    fprintf(stderr, "\n");

    if (matfile)
    {
        matmax = 0;
        for (f = 0; f < mat_nx; f++)
        {
            normfac = 1.0/(mcount[f]*isize*rbin);
            for (i = 0; i < nbin; i++)
            {
                mat[f][i] *= normfac;
                if (mat[f][i] > matmax && (f != 0 || i != 0))
                {
                    matmax = mat[f][i];
                }
            }
        }
        fprintf(stdout, "Value at (0,0): %.3f, maximum of the rest %.3f\n",
                mat[0][0], matmax);
        if (mmax > 0)
        {
            matmax = mmax;
        }
        snew(tickx, mat_nx);
        for (f = 0; f < mat_nx; f++)
        {
            if (sbin == 0)
            {
                tickx[f] = f*dt;
            }
            else
            {
                tickx[f] = f*sbin;
            }
        }
        snew(ticky, nbin+1);
        for (i = 0; i <= nbin; i++)
        {
            ticky[i] = i*rbin;
        }
        fp = gmx_ffopen(matfile, "w");
        write_xpm(fp, MAT_SPATIAL_Y, "Van Hove function", "G (1/nm)",
                  sbin == 0 ? "time (ps)" : "sqrt(time) (ps^1/2)", "r (nm)",
                  mat_nx, nbin, tickx, ticky, mat, 0, matmax, rlo, rhi, &nlev);
        gmx_ffclose(fp);
    }

    if (orfile)
    {
        fp = xvgropen(orfile, "Van Hove function", "r (nm)", "G (nm\\S-1\\N)", oenv);
        if (output_env_get_print_xvgr_codes(oenv))
        {
            fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname);
        }
        snew(legend, nr);
        for (fbin = 0; fbin < nr; fbin++)
        {
            sprintf(buf, "%g ps", (fbin + 1)*fshift*dt);
            legend[fbin] = strdup(buf);
        }
        xvgr_legend(fp, nr, (const char**)legend, oenv);
        for (i = 0; i < nalloc; i++)
        {
            fprintf(fp, "%g", i*rbin);
            for (fbin = 0; fbin < nr; fbin++)
            {
                fprintf(fp, " %g",
                        (real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i == 0 ? 0.5 : 1)));
            }
            fprintf(fp, "\n");
        }
        gmx_ffclose(fp);
    }

    if (otfile)
    {
        sprintf(buf, "Probability of moving less than %g nm", rint);
        fp = xvgropen(otfile, buf, "t (ps)", "", oenv);
        if (output_env_get_print_xvgr_codes(oenv))
        {
            fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname);
        }
        for (f = 0; f <= ftmax; f++)
        {
            fprintf(fp, "%g %g\n", f*dt, (real)pt[f]/(tcount[f]*isize));
        }
        gmx_ffclose(fp);
    }

    do_view(oenv, matfile, NULL);
    do_view(oenv, orfile, NULL);
    do_view(oenv, otfile, NULL);

    return 0;
}
Example #27
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);
}
Example #28
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;
}
Example #29
0
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac,
                         real rho, real wt, const char *fn_trans,
                         const char *fn_tca, const char *fn_tc,
                         const char *fn_tcf, const char *fn_cub,
                         const char *fn_vk, const gmx_output_env_t *oenv)
{
    FILE  *fp, *fp_vk, *fp_cub = NULL;
    int    nk, ntc;
    real **tcaf, **tcafc = NULL, eta, *sig;
    int    i, j, k, kc;
    int    ncorr;
    double fitparms[3];

    nk  = kset_c[nkc];
    ntc = nk*NPK;

    if (fn_trans)
    {
        fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)",
                      oenv);
        for (i = 0; i < nframes; i++)
        {
            fprintf(fp, "%g", i*dt);
            for (j = 0; j < ntc; j++)
            {
                fprintf(fp, " %g", tc[j][i]);
            }
            fprintf(fp, "\n");
        }
        xvgrclose(fp);
        do_view(oenv, fn_trans, "-nxy");
    }

    ncorr = (nframes+1)/2;
    if (ncorr > static_cast<int>(5*wt/dt+0.5))
    {
        ncorr = static_cast<int>(5*wt/dt+0.5)+1;
    }
    snew(tcaf, nk);
    for (k = 0; k < nk; k++)
    {
        snew(tcaf[k], ncorr);
    }
    if (fn_cub)
    {
        snew(tcafc, nkc);
        for (k = 0; k < nkc; k++)
        {
            snew(tcafc[k], ncorr);
        }
    }
    snew(sig, ncorr);
    for (i = 0; i < ncorr; i++)
    {
        sig[i] = std::exp(0.5*i*dt/wt);
    }

    low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions",
                    nframes, ntc, ncorr, tc, dt, eacNormal,
                    1, FALSE, FALSE, FALSE, 0, 0, 0);
    do_view(oenv, fn_tca, "-nxy");

    fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions",
                  "Time (ps)", "TCAF", oenv);
    for (i = 0; i < ncorr; i++)
    {
        kc = 0;
        fprintf(fp, "%g", i*dt);
        for (k = 0; k < nk; k++)
        {
            for (j = 0; j < NPK; j++)
            {
                tcaf[k][i] += tc[NPK*k+j][i];
            }
            if (fn_cub)
            {
                for (j = 0; j < NPK; j++)
                {
                    tcafc[kc][i] += tc[NPK*k+j][i];
                }
            }
            if (i == 0)
            {
                fprintf(fp, " %g", 1.0);
            }
            else
            {
                tcaf[k][i] /= tcaf[k][0];
                fprintf(fp, " %g", tcaf[k][i]);
            }
            if (k+1 == kset_c[kc+1])
            {
                kc++;
            }
        }
        fprintf(fp, "\n");
    }
    xvgrclose(fp);
    do_view(oenv, fn_tc, "-nxy");

    if (fn_cub)
    {
        fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv);
        for (kc = 0; kc < nkc; kc++)
        {
            fprintf(fp_cub, "%g %g\n", 0.0, 1.0);
            for (i = 1; i < ncorr; i++)
            {
                tcafc[kc][i] /= tcafc[kc][0];
                fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]);
            }
            fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            tcafc[kc][0] = 1.0;
        }
    }

    fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)",
                     "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp_vk, "@    s0 symbol 2\n");
        fprintf(fp_vk, "@    s0 symbol color 1\n");
        fprintf(fp_vk, "@    s0 linestyle 0\n");
        if (fn_cub)
        {
            fprintf(fp_vk, "@    s1 symbol 3\n");
            fprintf(fp_vk, "@    s1 symbol color 2\n");
        }
    }
    fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv);
    for (k = 0; k < nk; k++)
    {
        tcaf[k][0]   = 1.0;
        fitparms[0]  = 1;
        fitparms[1]  = 1;
        do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt,
                 oenv, bDebugMode(), effnVAC, fitparms, 0, NULL);
        eta = 1000*fitparms[1]*rho/
            (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO));
        fprintf(stdout, "k %6.3f  tau %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                norm(kfac[k]), fitparms[0], eta);
        fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta);
        for (i = 0; i < ncorr; i++)
        {
            fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
        }
        fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
    }
    xvgrclose(fp);
    do_view(oenv, fn_tcf, "-nxy");

    if (fn_cub)
    {
        fprintf(stdout, "Averaged over k-vectors:\n");
        fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        for (k = 0; k < nkc; k++)
        {
            tcafc[k][0]  = 1.0;
            fitparms[0]  = 1;
            fitparms[1]  = 1;
            do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt,
                     oenv, bDebugMode(), effnVAC, fitparms, 0, NULL);
            eta = 1000*fitparms[1]*rho/
                (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO));
            fprintf(stdout,
                    "k %6.3f  tau %6.3f  Omega %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                    norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta);
            fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta);
            for (i = 0; i < ncorr; i++)
            {
                fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
            }
            fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        }
        fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
        xvgrclose(fp_cub);
        do_view(oenv, fn_cub, "-nxy");
    }
    xvgrclose(fp_vk);
    do_view(oenv, fn_vk, "-nxy");
}
Example #30
0
void dist_plot(const char *fn, const char *afile, const char *dfile,
               const char *nfile, const char *rfile, const char *xfile,
               real rcut, gmx_bool bMat, t_atoms *atoms,
               int ng, atom_id *index[], int gnx[], char *grpn[], gmx_bool bSplit,
               gmx_bool bMin, int nres, atom_id *residue, gmx_bool bPBC, int ePBC,
               gmx_bool bGroup, gmx_bool bEachResEachTime, gmx_bool bPrintResName,
               const output_env_t oenv)
{
    FILE            *atm, *dist, *num;
    t_trxstatus     *trxout;
    char             buf[256];
    char           **leg;
    real             t, dmin, dmax, **mindres = NULL, **maxdres = NULL;
    int              nmin, nmax;
    t_trxstatus     *status;
    int              i = -1, j, k, natoms;
    int              min1, min2, max1, max2, min1r, min2r, max1r, max2r;
    atom_id          oindex[2];
    rvec            *x0;
    matrix           box;
    t_trxframe       frout;
    gmx_bool         bFirst;
    FILE            *respertime = NULL;

    if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0)
    {
        gmx_fatal(FARGS, "Could not read coordinates from statusfile\n");
    }

    sprintf(buf, "%simum Distance", bMin ? "Min" : "Max");
    dist = xvgropen(dfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv);
    sprintf(buf, "Number of Contacts %s %g nm", bMin ? "<" : ">", rcut);
    num    = nfile ? xvgropen(nfile, buf, output_env_get_time_label(oenv), "Number", oenv) : NULL;
    atm    = afile ? gmx_ffopen(afile, "w") : NULL;
    trxout = xfile ? open_trx(xfile, "w") : NULL;

    if (bMat)
    {
        if (ng == 1)
        {
            snew(leg, 1);
            sprintf(buf, "Internal in %s", grpn[0]);
            leg[0] = gmx_strdup(buf);
            xvgr_legend(dist, 0, (const char**)leg, oenv);
            if (num)
            {
                xvgr_legend(num, 0, (const char**)leg, oenv);
            }
        }
        else
        {
            snew(leg, (ng*(ng-1))/2);
            for (i = j = 0; (i < ng-1); i++)
            {
                for (k = i+1; (k < ng); k++, j++)
                {
                    sprintf(buf, "%s-%s", grpn[i], grpn[k]);
                    leg[j] = gmx_strdup(buf);
                }
            }
            xvgr_legend(dist, j, (const char**)leg, oenv);
            if (num)
            {
                xvgr_legend(num, j, (const char**)leg, oenv);
            }
        }
    }
    else
    {
        snew(leg, ng-1);
        for (i = 0; (i < ng-1); i++)
        {
            sprintf(buf, "%s-%s", grpn[0], grpn[i+1]);
            leg[i] = gmx_strdup(buf);
        }
        xvgr_legend(dist, ng-1, (const char**)leg, oenv);
        if (num)
        {
            xvgr_legend(num, ng-1, (const char**)leg, oenv);
        }
    }

    if (bEachResEachTime)
    {
        sprintf(buf, "%simum Distance", bMin ? "Min" : "Max");
        respertime = xvgropen(rfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv);
        xvgr_legend(respertime, ng-1, (const char**)leg, oenv);
        if (bPrintResName)
        {
            fprintf(respertime, "# ");
        }
        for (j = 0; j < nres; j++)
        {
            fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind);
        }
        fprintf(respertime, "\n");

    }

    j = 0;
    if (nres)
    {
        snew(mindres, ng-1);
        snew(maxdres, ng-1);
        for (i = 1; i < ng; i++)
        {
            snew(mindres[i-1], nres);
            snew(maxdres[i-1], nres);
            for (j = 0; j < nres; j++)
            {
                mindres[i-1][j] = 1e6;
            }
            /* maxdres[*][*] is already 0 */
        }
    }
    bFirst = TRUE;
    do
    {
        if (bSplit && !bFirst && fabs(t/output_env_get_time_factor(oenv)) < 1e-5)
        {
            fprintf(dist, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            if (num)
            {
                fprintf(num, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            }
            if (atm)
            {
                fprintf(atm, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
            }
        }
        fprintf(dist, "%12e", output_env_conv_time(oenv, t));
        if (num)
        {
            fprintf(num, "%12e", output_env_conv_time(oenv, t));
        }

        if (bMat)
        {
            if (ng == 1)
            {
                calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup,
                          &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
                fprintf(dist, "  %12e", bMin ? dmin : dmax);
                if (num)
                {
                    fprintf(num, "  %8d", bMin ? nmin : nmax);
                }
            }
            else
            {
                for (i = 0; (i < ng-1); i++)
                {
                    for (k = i+1; (k < ng); k++)
                    {
                        calc_dist(rcut, bPBC, ePBC, box, x0, gnx[i], gnx[k], index[i], index[k],
                                  bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
                        fprintf(dist, "  %12e", bMin ? dmin : dmax);
                        if (num)
                        {
                            fprintf(num, "  %8d", bMin ? nmin : nmax);
                        }
                    }
                }
            }
        }
        else
        {
            for (i = 1; (i < ng); i++)
            {
                calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup,
                          &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
                fprintf(dist, "  %12e", bMin ? dmin : dmax);
                if (num)
                {
                    fprintf(num, "  %8d", bMin ? nmin : nmax);
                }
                if (nres)
                {
                    for (j = 0; j < nres; j++)
                    {
                        calc_dist(rcut, bPBC, ePBC, box, x0, residue[j+1]-residue[j], gnx[i],
                                  &(index[0][residue[j]]), index[i], bGroup,
                                  &dmin, &dmax, &nmin, &nmax, &min1r, &min2r, &max1r, &max2r);
                        mindres[i-1][j] = min(mindres[i-1][j], dmin);
                        maxdres[i-1][j] = max(maxdres[i-1][j], dmax);
                    }
                }
            }
        }
        fprintf(dist, "\n");
        if (num)
        {
            fprintf(num, "\n");
        }
        if ( (bMin ? min1 : max1) != -1)
        {
            if (atm)
            {
                fprintf(atm, "%12e  %12d  %12d\n",
                        output_env_conv_time(oenv, t), 1+(bMin ? min1 : max1),
                        1+(bMin ? min2 : max2));
            }
        }

        if (trxout)
        {
            oindex[0] = bMin ? min1 : max1;
            oindex[1] = bMin ? min2 : max2;
            write_trx(trxout, 2, oindex, atoms, i, t, box, x0, NULL, NULL);
        }
        bFirst = FALSE;
        /*dmin should be minimum distance for residue and group*/
        if (bEachResEachTime)
        {
            fprintf(respertime, "%12e", t);
            for (i = 1; i < ng; i++)
            {
                for (j = 0; j < nres; j++)
                {
                    fprintf(respertime, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]);
                    /*reset distances for next time point*/
                    mindres[i-1][j] = 1e6;
                    maxdres[i-1][j] = 0;
                }
            }
            fprintf(respertime, "\n");
        }
    }
    while (read_next_x(oenv, status, &t, x0, box));

    close_trj(status);
    gmx_ffclose(dist);
    if (num)
    {
        gmx_ffclose(num);
    }
    if (atm)
    {
        gmx_ffclose(atm);
    }
    if (trxout)
    {
        close_trx(trxout);
    }

    if (nres && !bEachResEachTime)
    {
        FILE *res;

        sprintf(buf, "%simum Distance", bMin ? "Min" : "Max");
        res = xvgropen(rfile, buf, "Residue (#)", "Distance (nm)", oenv);
        xvgr_legend(res, ng-1, (const char**)leg, oenv);
        for (j = 0; j < nres; j++)
        {
            fprintf(res, "%4d", j+1);
            for (i = 1; i < ng; i++)
            {
                fprintf(res, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]);
            }
            fprintf(res, "\n");
        }
    }

    sfree(x0);
}