Example #1
0
int gmx_traj(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] plots coordinates, velocities, forces and/or the box.",
        "With [TT]-com[tt] the coordinates, velocities and forces are",
        "calculated for the center of mass of each group.",
        "When [TT]-mol[tt] is set, the numbers in the index file are",
        "interpreted as molecule numbers and the same procedure as with",
        "[TT]-com[tt] is used for each molecule.[PAR]",
        "Option [TT]-ot[tt] plots the temperature of each group,",
        "provided velocities are present in the trajectory file.",
        "No corrections are made for constrained degrees of freedom!",
        "This implies [TT]-com[tt].[PAR]",
        "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and",
        "rotational kinetic energy of each group,",
        "provided velocities are present in the trajectory file.",
        "This implies [TT]-com[tt].[PAR]",
        "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities",
        "and average forces as temperature factors to a [REF].pdb[ref] file with",
        "the average coordinates or the coordinates at [TT]-ctime[tt].",
        "The temperature factors are scaled such that the maximum is 10.",
        "The scaling can be changed with the option [TT]-scale[tt].",
        "To get the velocities or forces of one",
        "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of",
        "desired frame. When averaging over frames you might need to use",
        "the [TT]-nojump[tt] option to obtain the correct average coordinates.",
        "If you select either of these option the average force and velocity",
        "for each atom are written to an [REF].xvg[ref] file as well",
        "(specified with [TT]-av[tt] or [TT]-af[tt]).[PAR]",
        "Option [TT]-vd[tt] computes a velocity distribution, i.e. the",
        "norm of the vector is plotted. In addition in the same graph",
        "the kinetic energy distribution is given."
    };
    static gmx_bool   bMol    = FALSE, bCom = FALSE, bPBC = TRUE, bNoJump = FALSE;
    static gmx_bool   bX      = TRUE, bY = TRUE, bZ = TRUE, bNorm = FALSE, bFP = FALSE;
    static int        ngroups = 1;
    static real       ctime   = -1, scale = 0, binwidth = 1;
    t_pargs           pa[]    = {
        { "-com", FALSE, etBOOL, {&bCom},
          "Plot data for the com of each group" },
        { "-pbc", FALSE, etBOOL, {&bPBC},
          "Make molecules whole for COM" },
        { "-mol", FALSE, etBOOL, {&bMol},
          "Index contains molecule numbers iso atom numbers" },
        { "-nojump", FALSE, etBOOL, {&bNoJump},
          "Remove jumps of atoms across the box" },
        { "-x", FALSE, etBOOL, {&bX},
          "Plot X-component" },
        { "-y", FALSE, etBOOL, {&bY},
          "Plot Y-component" },
        { "-z", FALSE, etBOOL, {&bZ},
          "Plot Z-component" },
        { "-ng",       FALSE, etINT, {&ngroups},
          "Number of groups to consider" },
        { "-len", FALSE, etBOOL, {&bNorm},
          "Plot vector length" },
        { "-fp", FALSE, etBOOL, {&bFP},
          "Full precision output" },
        { "-bin", FALSE, etREAL, {&binwidth},
          "Binwidth for velocity histogram (nm/ps)" },
        { "-ctime", FALSE, etREAL, {&ctime},
          "Use frame at this time for x in [TT]-cv[tt] and [TT]-cf[tt] instead of the average x" },
        { "-scale", FALSE, etREAL, {&scale},
          "Scale factor for [REF].pdb[ref] output, 0 is autoscale" }
    };
    FILE             *outx   = NULL, *outv = NULL, *outf = NULL, *outb = NULL, *outt = NULL;
    FILE             *outekt = NULL, *outekr = NULL;
    t_topology        top;
    int               ePBC;
    real             *mass, time;
    const char       *indexfn;
    t_trxframe        fr, frout;
    int               flags, nvhisto = 0, *vhisto = NULL;
    rvec             *xtop, *xp = NULL;
    rvec             *sumx = NULL, *sumv = NULL, *sumf = NULL;
    matrix            topbox;
    t_trxstatus      *status;
    t_trxstatus      *status_out = NULL;
    gmx_rmpbc_t       gpbc       = NULL;
    int               i, j;
    int               nr_xfr, nr_vfr, nr_ffr;
    char            **grpname;
    int              *isize0, *isize;
    int             **index0, **index;
    int              *atndx;
    t_block          *mols;
    gmx_bool          bTop, bOX, bOXT, bOV, bOF, bOB, bOT, bEKT, bEKR, bCV, bCF;
    gmx_bool          bDim[4], bDum[4], bVD;
    char              sffmt[STRLEN], sffmt6[STRLEN];
    const char       *box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };
    gmx_output_env_t *oenv;

    t_filenm          fnm[] = {
        { efTRX, "-f", NULL, ffREAD },
        { efTPS, NULL, NULL, ffREAD },
        { efNDX, NULL, NULL, ffOPTRD },
        { efXVG, "-ox",  "coord",     ffOPTWR },
        { efTRX, "-oxt", "coord",     ffOPTWR },
        { efXVG, "-ov",  "veloc",     ffOPTWR },
        { efXVG, "-of",  "force",     ffOPTWR },
        { efXVG, "-ob",  "box",       ffOPTWR },
        { efXVG, "-ot",  "temp",      ffOPTWR },
        { efXVG, "-ekt", "ektrans",   ffOPTWR },
        { efXVG, "-ekr", "ekrot",     ffOPTWR },
        { efXVG, "-vd",  "veldist",   ffOPTWR },
        { efPDB, "-cv",  "veloc",     ffOPTWR },
        { efPDB, "-cf",  "force",     ffOPTWR },
        { efXVG, "-av",  "all_veloc", ffOPTWR },
        { efXVG, "-af",  "all_force", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    if (bMol)
    {
        fprintf(stderr, "Interpreting indexfile entries as molecules.\n"
                "Using center of mass.\n");
    }

    bOX  = opt2bSet("-ox", NFILE, fnm);
    bOXT = opt2bSet("-oxt", NFILE, fnm);
    bOV  = opt2bSet("-ov", NFILE, fnm);
    bOF  = opt2bSet("-of", NFILE, fnm);
    bOB  = opt2bSet("-ob", NFILE, fnm);
    bOT  = opt2bSet("-ot", NFILE, fnm);
    bEKT = opt2bSet("-ekt", NFILE, fnm);
    bEKR = opt2bSet("-ekr", NFILE, fnm);
    bCV  = opt2bSet("-cv", NFILE, fnm) || opt2bSet("-av", NFILE, fnm);
    bCF  = opt2bSet("-cf", NFILE, fnm) || opt2bSet("-af", NFILE, fnm);
    bVD  = opt2bSet("-vd", NFILE, fnm) || opt2parg_bSet("-bin", asize(pa), pa);
    if (bMol || bOT || bEKT || bEKR)
    {
        bCom = TRUE;
    }

    bDim[XX]  = bX;
    bDim[YY]  = bY;
    bDim[ZZ]  = bZ;
    bDim[DIM] = bNorm;

    if (bFP)
    {
        sprintf(sffmt, "\t%s", gmx_real_fullprecision_pfmt);
    }
    else
    {
        sprintf(sffmt, "\t%%g");
    }
    sprintf(sffmt6, "%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC,
                         &xtop, NULL, topbox,
                         bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR));
    sfree(xtop);
    if ((bMol || bCV || bCF) && !bTop)
    {
        gmx_fatal(FARGS, "Need a run input file for option -mol, -cv or -cf");
    }

    if (bMol)
    {
        indexfn = ftp2fn(efNDX, NFILE, fnm);
    }
    else
    {
        indexfn = ftp2fn_null(efNDX, NFILE, fnm);
    }

    if (!(bCom && !bMol))
    {
        ngroups = 1;
    }
    snew(grpname, ngroups);
    snew(isize0, ngroups);
    snew(index0, ngroups);
    get_index(&(top.atoms), indexfn, ngroups, isize0, index0, grpname);

    if (bMol)
    {
        mols    = &(top.mols);
        atndx   = mols->index;
        ngroups = isize0[0];
        snew(isize, ngroups);
        snew(index, ngroups);
        for (i = 0; i < ngroups; i++)
        {
            if (index0[0][i] < 0 || index0[0][i] >= mols->nr)
            {
                gmx_fatal(FARGS, "Molecule index (%d) is out of range (%d-%d)",
                          index0[0][i]+1, 1, mols->nr);
            }
            isize[i] = atndx[index0[0][i]+1] - atndx[index0[0][i]];
            snew(index[i], isize[i]);
            for (j = 0; j < isize[i]; j++)
            {
                index[i][j] = atndx[index0[0][i]] + j;
            }
        }
    }
    else
    {
        isize = isize0;
        index = index0;
    }
    if (bCom)
    {
        snew(mass, top.atoms.nr);
        for (i = 0; i < top.atoms.nr; i++)
        {
            mass[i] = top.atoms.atom[i].m;
        }
    }
    else
    {
        mass = NULL;
    }

    flags = 0;
    if (bOX)
    {
        flags = flags | TRX_READ_X;
        outx  = xvgropen(opt2fn("-ox", NFILE, fnm),
                         bCom ? "Center of mass" : "Coordinate",
                         output_env_get_xvgr_tlabel(oenv), "Coordinate (nm)", oenv);
        make_legend(outx, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOXT)
    {
        flags      = flags | TRX_READ_X;
        status_out = open_trx(opt2fn("-oxt", NFILE, fnm), "w");
    }
    if (bOV)
    {
        flags = flags | TRX_READ_V;
        outv  = xvgropen(opt2fn("-ov", NFILE, fnm),
                         bCom ? "Center of mass velocity" : "Velocity",
                         output_env_get_xvgr_tlabel(oenv), "Velocity (nm/ps)", oenv);
        make_legend(outv, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOF)
    {
        flags = flags | TRX_READ_F;
        outf  = xvgropen(opt2fn("-of", NFILE, fnm), "Force",
                         output_env_get_xvgr_tlabel(oenv), "Force (kJ mol\\S-1\\N nm\\S-1\\N)",
                         oenv);
        make_legend(outf, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOB)
    {
        outb = xvgropen(opt2fn("-ob", NFILE, fnm), "Box vector elements",
                        output_env_get_xvgr_tlabel(oenv), "(nm)", oenv);

        xvgr_legend(outb, 6, box_leg, oenv);
    }
    if (bOT)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_V;
        outt      = xvgropen(opt2fn("-ot", NFILE, fnm), "Temperature",
                             output_env_get_xvgr_tlabel(oenv), "(K)", oenv);
        make_legend(outt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bEKT)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_V;
        outekt    = xvgropen(opt2fn("-ekt", NFILE, fnm), "Center of mass translation",
                             output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv);
        make_legend(outekt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bEKR)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_X | TRX_READ_V;
        outekr    = xvgropen(opt2fn("-ekr", NFILE, fnm), "Center of mass rotation",
                             output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv);
        make_legend(outekr, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bVD)
    {
        flags = flags | TRX_READ_V;
    }
    if (bCV)
    {
        flags = flags | TRX_READ_X | TRX_READ_V;
    }
    if (bCF)
    {
        flags = flags | TRX_READ_X | TRX_READ_F;
    }
    if ((flags == 0) && !bOB)
    {
        fprintf(stderr, "Please select one or more output file options\n");
        exit(0);
    }

    read_first_frame(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &fr, flags);


    if ((bOV || bOF) && fn2ftp(ftp2fn(efTRX, NFILE, fnm)) == efXTC)
    {
        gmx_fatal(FARGS, "Cannot extract velocities or forces since your input XTC file does not contain them.");
    }

    if (bCV || bCF)
    {
        snew(sumx, fr.natoms);
    }
    if (bCV)
    {
        snew(sumv, fr.natoms);
    }
    if (bCF)
    {
        snew(sumf, fr.natoms);
    }
    nr_xfr = 0;
    nr_vfr = 0;
    nr_ffr = 0;

    if (bCom && bPBC)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);
    }

    do
    {
        time = output_env_conv_time(oenv, fr.time);

        if (fr.bX && bNoJump && fr.bBox)
        {
            if (xp)
            {
                remove_jump(fr.box, fr.natoms, xp, fr.x);
            }
            else
            {
                snew(xp, fr.natoms);
            }
            for (i = 0; i < fr.natoms; i++)
            {
                copy_rvec(fr.x[i], xp[i]);
            }
        }

        if (fr.bX && bCom && bPBC)
        {
            gmx_rmpbc_trxfr(gpbc, &fr);
        }

        if (bVD && fr.bV)
        {
            update_histo(isize[0], index[0], fr.v, &nvhisto, &vhisto, binwidth);
        }

        if (bOX && fr.bX)
        {
            print_data(outx, time, fr.x, mass, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOXT && fr.bX)
        {
            frout = fr;
            if (!frout.bAtoms)
            {
                frout.atoms  = &top.atoms;
                frout.bAtoms = TRUE;
            }
            write_trx_x(status_out, &frout, mass, bCom, ngroups, isize, index);
        }
        if (bOV && fr.bV)
        {
            print_data(outv, time, fr.v, mass, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOF && fr.bF)
        {
            print_data(outf, time, fr.f, NULL, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOB && fr.bBox)
        {
            fprintf(outb, "\t%g", fr.time);
            fprintf(outb, sffmt6,
                    fr.box[XX][XX], fr.box[YY][YY], fr.box[ZZ][ZZ],
                    fr.box[YY][XX], fr.box[ZZ][XX], fr.box[ZZ][YY]);
            fprintf(outb, "\n");
        }
        if (bOT && fr.bV)
        {
            fprintf(outt, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outt, sffmt, temp(fr.v, mass, isize[i], index[i]));
            }
            fprintf(outt, "\n");
        }
        if (bEKT && fr.bV)
        {
            fprintf(outekt, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outekt, sffmt, ektrans(fr.v, mass, isize[i], index[i]));
            }
            fprintf(outekt, "\n");
        }
        if (bEKR && fr.bX && fr.bV)
        {
            fprintf(outekr, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outekr, sffmt, ekrot(fr.x, fr.v, mass, isize[i], index[i]));
            }
            fprintf(outekr, "\n");
        }
        if ((bCV || bCF) && fr.bX &&
            (ctime < 0 || (fr.time >= ctime*0.999999 &&
                           fr.time <= ctime*1.000001)))
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumx[i], fr.x[i]);
            }
            nr_xfr++;
        }
        if (bCV && fr.bV)
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumv[i], fr.v[i]);
            }
            nr_vfr++;
        }
        if (bCF && fr.bF)
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumf[i], fr.f[i]);
            }
            nr_ffr++;
        }

    }
    while (read_next_frame(oenv, status, &fr));

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

    /* clean up a bit */
    close_trj(status);

    if (bOX)
    {
        xvgrclose(outx);
    }
    if (bOXT)
    {
        close_trx(status_out);
    }
    if (bOV)
    {
        xvgrclose(outv);
    }
    if (bOF)
    {
        xvgrclose(outf);
    }
    if (bOB)
    {
        xvgrclose(outb);
    }
    if (bOT)
    {
        xvgrclose(outt);
    }
    if (bEKT)
    {
        xvgrclose(outekt);
    }
    if (bEKR)
    {
        xvgrclose(outekr);
    }

    if (bVD)
    {
        print_histo(opt2fn("-vd", NFILE, fnm), nvhisto, vhisto, binwidth, oenv);
    }

    if (bCV || bCF)
    {
        if (nr_xfr > 1)
        {
            if (ePBC != epbcNONE && !bNoJump)
            {
                fprintf(stderr, "\nWARNING: More than one frame was used for option -cv or -cf\n"
                        "If atoms jump across the box you should use the -nojump or -ctime option\n\n");
            }
            for (i = 0; i < isize[0]; i++)
            {
                svmul(1.0/nr_xfr, sumx[index[0][i]], sumx[index[0][i]]);
            }
        }
        else if (nr_xfr == 0)
        {
            fprintf(stderr, "\nWARNING: No coordinate frames found for option -cv or -cf\n\n");
        }
    }
    if (bCV)
    {
        write_pdb_bfac(opt2fn("-cv", NFILE, fnm),
                       opt2fn("-av", NFILE, fnm), "average velocity", &(top.atoms),
                       ePBC, topbox, isize[0], index[0], nr_xfr, sumx,
                       nr_vfr, sumv, bDim, scale, oenv);
    }
    if (bCF)
    {
        write_pdb_bfac(opt2fn("-cf", NFILE, fnm),
                       opt2fn("-af", NFILE, fnm), "average force", &(top.atoms),
                       ePBC, topbox, isize[0], index[0], nr_xfr, sumx,
                       nr_ffr, sumf, bDim, scale, oenv);
    }

    /* view it */
    view_all(oenv, NFILE, fnm);

    return 0;
}
int gmx_traj(int argc,char *argv[])
{
  static char *desc[] = {
    "g_traj plots coordinates, velocities, forces and/or the box.",
    "With [TT]-com[tt] the coordinates, velocities and forces are",
    "calculated for the center of mass of each group.",
    "When [TT]-mol[tt] is set, the numbers in the index file are",
    "interpreted as molecule numbers and the same procedure as with",
    "[TT]-com[tt] is used for each molecule.[PAR]",
    "Option [TT]-ot[tt] plots the temperature of each group,",
    "provided velocities are present in the trajectory file.",
    "No corrections are made for constrained degrees of freedom!",
    "This implies [TT]-com[tt].[PAR]",
    "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and",
    "rotational kinetic energy of each group,", 
    "provided velocities are present in the trajectory file.",
    "This implies [TT]-com[tt].[PAR]",
    "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities",
    "and average forces as temperature factors to a pdb file with",
    "the average coordinates. The temperature factors are scaled such",
    "that the maximum is 10. The scaling can be changed with the option",
    "[TT]-scale[tt]. To get the velocities or forces of one",
    "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of",
    "desired frame. When averaging over frames you might need to use",
    "the [TT]-nojump[tt] option to obtain the correct average coordinates.",
    "If you select either of these option the average force and velocity",
    "for each atom are written to an xvg file as well",
    "(specified with [TT]-av[tt] or [TT]-af[tt]).[PAR]",
    "Option [TT]-vd[tt] computes a velocity distribution, i.e. the",
    "norm of the vector is plotted. In addition in the same graph",
    "the kinetic energy distribution is given."
  };
  static bool bMol=FALSE,bCom=FALSE,bNoJump=FALSE;
  static bool bX=TRUE,bY=TRUE,bZ=TRUE,bNorm=FALSE;
  static int  ngroups=1;
  static real scale=0,binwidth=1;
  t_pargs pa[] = {
    { "-com", FALSE, etBOOL, {&bCom},
      "Plot data for the com of each group" },
    { "-mol", FALSE, etBOOL, {&bMol},
      "Index contains molecule numbers iso atom numbers" },
    { "-nojump", FALSE, etBOOL, {&bNoJump},
      "Remove jumps of atoms across the box" },
    { "-x", FALSE, etBOOL, {&bX},
      "Plot X-component" },
    { "-y", FALSE, etBOOL, {&bY},
      "Plot Y-component" },
    { "-z", FALSE, etBOOL, {&bZ},
      "Plot Z-component" },
    { "-ng",       FALSE, etINT, {&ngroups},
      "Number of groups to consider" },
    { "-len", FALSE, etBOOL, {&bNorm},
      "Plot vector length" },
    { "-bin", FALSE, etREAL, {&binwidth},
      "Binwidth for velocity histogram (nm/ps)" },
    { "-scale", FALSE, etREAL, {&scale},
      "Scale factor for pdb output, 0 is autoscale" }
    
  };
  FILE       *outx=NULL,*outv=NULL,*outf=NULL,*outb=NULL,*outt=NULL;
  FILE       *outekt=NULL,*outekr=NULL;
  t_topology top;
  int        ePBC;
  real       *mass,time;
  char       title[STRLEN],*indexfn;
  t_trxframe fr,frout;
  int        flags,nvhisto=0,*vhisto=NULL;
  rvec       *xtop,*xp=NULL;
  rvec       *sumxv=NULL,*sumv=NULL,*sumxf=NULL,*sumf=NULL;
  matrix     topbox;
  int        status,status_out=-1;
  int        i,j,n;
  int        nr_xfr,nr_vfr,nr_ffr;
  char       **grpname;
  int        *isize0,*isize;
  atom_id    **index0,**index;
  atom_id    *atndx;
  t_block    *mols;
  bool       bTop,bOX,bOXT,bOV,bOF,bOB,bOT,bEKT,bEKR,bCV,bCF;
  bool       bDim[4],bDum[4],bVD;
  char       *box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };

  t_filenm fnm[] = {
    { efTRX, "-f", NULL, ffREAD },
    { efTPS, NULL, NULL, ffREAD },
    { efNDX, NULL, NULL, ffOPTRD },
    { efXVG, "-ox", "coord.xvg", ffOPTWR },
    { efTRX, "-oxt","coord.xtc", ffOPTWR },
    { efXVG, "-ov", "veloc.xvg", ffOPTWR },
    { efXVG, "-of", "force.xvg", ffOPTWR },
    { efXVG, "-ob", "box.xvg",   ffOPTWR },
    { efXVG, "-ot", "temp.xvg",  ffOPTWR },
    { efXVG, "-ekt","ektrans.xvg", ffOPTWR },
    { efXVG, "-ekr","ekrot.xvg", ffOPTWR },
    { efXVG, "-vd", "veldist.xvg", ffOPTWR },
    { efPDB, "-cv", "veloc.pdb", ffOPTWR },
    { efPDB, "-cf", "force.pdb", ffOPTWR },
    { efXVG, "-av", "all_veloc.xvg", ffOPTWR },
    { efXVG, "-af", "all_force.xvg", ffOPTWR }
  };
#define NFILE asize(fnm)

  CopyRight(stderr,argv[0]);
  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);

  if (bMol)
    fprintf(stderr,"Interpreting indexfile entries as molecules.\n"
	    "Using center of mass.\n");
  
  bOX  = opt2bSet("-ox",NFILE,fnm);
  bOXT = opt2bSet("-oxt",NFILE,fnm);
  bOV  = opt2bSet("-ov",NFILE,fnm);
  bOF  = opt2bSet("-of",NFILE,fnm);
  bOB  = opt2bSet("-ob",NFILE,fnm);
  bOT  = opt2bSet("-ot",NFILE,fnm);
  bEKT = opt2bSet("-ekt",NFILE,fnm);
  bEKR = opt2bSet("-ekr",NFILE,fnm);
  bCV  = opt2bSet("-cv",NFILE,fnm) || opt2bSet("-av",NFILE,fnm);
  bCF  = opt2bSet("-cf",NFILE,fnm) || opt2bSet("-af",NFILE,fnm);
  bVD  = opt2bSet("-vd",NFILE,fnm) || opt2parg_bSet("-bin",asize(pa),pa);
  if (bMol || bOT || bEKT || bEKR)
    bCom = TRUE;

  bDim[XX] = bX;
  bDim[YY] = bY;
  bDim[ZZ] = bZ;
  bDim[DIM] = bNorm;

  bTop = read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,
		       &xtop,NULL,topbox,
		       bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR));
  sfree(xtop);
  if ((bMol || bCV || bCF) && !bTop)
    gmx_fatal(FARGS,"Need a run input file for option -mol, -cv or -cf");

  if (bMol)
    indexfn = ftp2fn(efNDX,NFILE,fnm);
  else
    indexfn = ftp2fn_null(efNDX,NFILE,fnm);

  if (!(bCom && !bMol))
    ngroups = 1;
  snew(grpname,ngroups);
  snew(isize0,ngroups);
  snew(index0,ngroups);
  get_index(&(top.atoms),indexfn,ngroups,isize0,index0,grpname);
  
  if (bMol) {
    mols=&(top.mols);
    atndx = mols->index;
    ngroups = isize0[0];
    snew(isize,ngroups);
    snew(index,ngroups);
    for (i=0; i<ngroups; i++) {
      if (index0[0][i] < 0 || index0[0][i] >= mols->nr)
	gmx_fatal(FARGS,"Molecule index (%d) is out of range (%d-%d)",
		  index0[0][i]+1,1,mols->nr);
      isize[i] = atndx[index0[0][i]+1] - atndx[index0[0][i]];
      snew(index[i],isize[i]);
      for(j=0; j<isize[i]; j++)
	index[i][j] = atndx[index0[0][i]] + j;
    }
  } else {
    isize = isize0;
    index = index0;
  }
  if (bCom) {
    snew(mass,top.atoms.nr);
    for(i=0; i<top.atoms.nr; i++)
      mass[i] = top.atoms.atom[i].m;
  } else
    mass = NULL;

  flags = 0;
  if (bOX) {
    flags = flags | TRX_READ_X;
    outx = xvgropen(opt2fn("-ox",NFILE,fnm),
		    bCom ? "Center of mass" : "Coordinate",
		    xvgr_tlabel(),"Coordinate (nm)");
    make_legend(outx,ngroups,isize0[0],index0[0],grpname,bCom,bMol,bDim);
  }
  if (bOXT) {
    flags = flags | TRX_READ_X;
    status_out = open_trx(opt2fn("-oxt",NFILE,fnm),"w");
  }
  if (bOV) {
    flags = flags | TRX_READ_V;
    outv = xvgropen(opt2fn("-ov",NFILE,fnm),
		    bCom ? "Center of mass velocity" : "Velocity",
		    xvgr_tlabel(),"Velocity (nm/ps)");
   make_legend(outv,ngroups,isize0[0],index0[0],grpname,bCom,bMol,bDim); 
  }
  if (bOF) {
    flags = flags | TRX_READ_F;
    outf = xvgropen(opt2fn("-of",NFILE,fnm),"Force",
		    xvgr_tlabel(),"Force (kJ mol\\S-1\\N nm\\S-1\\N)");
    make_legend(outf,ngroups,isize0[0],index0[0],grpname,bCom,bMol,bDim);
  }
  if (bOB) {
    outb = xvgropen(opt2fn("-ob",NFILE,fnm),"Box vector elements",
		    xvgr_tlabel(),"(nm)");
   
    xvgr_legend(outb,6,box_leg);
  }
  if (bOT) {
    bDum[XX] = FALSE;
    bDum[YY] = FALSE;
    bDum[ZZ] = FALSE;
    bDum[DIM] = TRUE;
    flags = flags | TRX_READ_V;
    outt = xvgropen(opt2fn("-ot",NFILE,fnm),"Temperature",xvgr_tlabel(),"(K)");
    make_legend(outt,ngroups,isize[0],index[0],grpname,bCom,bMol,bDum);
  }
  if (bEKT) {
    bDum[XX] = FALSE;
    bDum[YY] = FALSE;
    bDum[ZZ] = FALSE;
    bDum[DIM] = TRUE;
    flags = flags | TRX_READ_V;
    outekt = xvgropen(opt2fn("-ekt",NFILE,fnm),"Center of mass translation",
		      xvgr_tlabel(),"Energy (kJ mol\\S-1\\N)");
    make_legend(outekt,ngroups,isize[0],index[0],grpname,bCom,bMol,bDum);
  }
  if (bEKR) {
    bDum[XX] = FALSE;
    bDum[YY] = FALSE;
    bDum[ZZ] = FALSE;
    bDum[DIM] = TRUE;
    flags = flags | TRX_READ_X | TRX_READ_V;
    outekr = xvgropen(opt2fn("-ekr",NFILE,fnm),"Center of mass rotation",
		      xvgr_tlabel(),"Energy (kJ mol\\S-1\\N)");
    make_legend(outekr,ngroups,isize[0],index[0],grpname,bCom,bMol,bDum);
  }
  if (bVD)
    flags = flags | TRX_READ_V;
  if (bCV)
    flags = flags | TRX_READ_X | TRX_READ_V;
  if (bCF)
    flags = flags | TRX_READ_X | TRX_READ_F;
  if ((flags == 0) && !bOB) {
    fprintf(stderr,"Please select one or more output file options\n");
    exit(0);
  }

  read_first_frame(&status,ftp2fn(efTRX,NFILE,fnm),&fr,flags);

  if (bCV) {
    snew(sumxv,fr.natoms);
    snew(sumv,fr.natoms);
  }
  if (bCF) {
    snew(sumxf,fr.natoms);
    snew(sumf,fr.natoms);
  }
  nr_xfr = 0;
  nr_vfr = 0;
  nr_ffr = 0;
  
  do {
    time = convert_time(fr.time);

    if (fr.bX && bNoJump && fr.bBox) {
      if (xp)
	remove_jump(fr.box,fr.natoms,xp,fr.x);
      else 
	snew(xp,fr.natoms);
      for(i=0; i<fr.natoms; i++)
	copy_rvec(fr.x[i],xp[i]);
    }
    
    if (fr.bX && bCom)
      rm_pbc(&(top.idef),ePBC,fr.natoms,fr.box,fr.x,fr.x);

    if (bVD && fr.bV) 
      update_histo(isize[0],index[0],fr.v,&nvhisto,&vhisto,binwidth);
      
    if (bOX && fr.bX)
      print_data(outx,time,fr.x,mass,bCom,ngroups,isize,index,bDim);
    if (bOXT && fr.bX) {
      frout = fr;
      if (!frout.bAtoms) {
	frout.atoms  = &top.atoms;
	frout.bAtoms = TRUE;
      }
      write_trx_x(status_out,&frout,mass,bCom,ngroups,isize,index);
    }
    if (bOV && fr.bV)
      print_data(outv,time,fr.v,mass,bCom,ngroups,isize,index,bDim);
    if (bOF && fr.bF)
      print_data(outf,time,fr.f,NULL,bCom,ngroups,isize,index,bDim);
    if (bOB && fr.bBox)
      fprintf(outb,"\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",fr.time,
	      fr.box[XX][XX],fr.box[YY][YY],fr.box[ZZ][ZZ],
	      fr.box[YY][XX],fr.box[ZZ][XX],fr.box[ZZ][YY]);
    if (bOT && fr.bV) {
      fprintf(outt," %g",time);
      for(i=0; i<ngroups; i++)
	fprintf(outt,"\t%g",temp(fr.v,mass,isize[i],index[i]));
      fprintf(outt,"\n");
    }
    if (bEKT && fr.bV) {
      fprintf(outekt," %g",time);
      for(i=0; i<ngroups; i++)
	fprintf(outekt,"\t%g",ektrans(fr.v,mass,isize[i],index[i]));
      fprintf(outekt,"\n");
    }
    if (bEKR && fr.bX && fr.bV) {
      fprintf(outekr," %g",time);
      for(i=0; i<ngroups; i++)
	fprintf(outekr,"\t%g",ekrot(fr.x,fr.v,mass,isize[i],index[i]));
      fprintf(outekr,"\n");
    }
    if (bCV) {
      if (fr.bX) {
	for(i=0; i<fr.natoms; i++)
	  rvec_inc(sumxv[i],fr.x[i]);
	nr_xfr++;
      }
      if (fr.bV) {
	for(i=0; i<fr.natoms; i++)
	  rvec_inc(sumv[i],fr.v[i]);
	nr_vfr++;
      }
    }
    if (bCF) {
      if (fr.bX) {
	for(i=0; i<fr.natoms; i++)
	  rvec_inc(sumxf[i],fr.x[i]);
	nr_xfr++;
      }
      if (fr.bF) {
	for(i=0; i<fr.natoms; i++)
	  rvec_inc(sumf[i],fr.f[i]);
	nr_ffr++;
      }
    }
    
  } while(read_next_frame(status,&fr));
  

  /* clean up a bit */
  close_trj(status);
  
  if (bOX) fclose(outx);
  if (bOXT) close_trx(status_out);
  if (bOV) fclose(outv);
  if (bOF) fclose(outf);
  if (bOB) fclose(outb);
  if (bOT) fclose(outt);
  if (bEKT) fclose(outekt);
  if (bEKR) fclose(outekr);

  if (bVD)
    print_histo(opt2fn("-vd",NFILE,fnm),nvhisto,vhisto,binwidth);
    
  if ((bCV || bCF) && (nr_vfr>1 || nr_ffr>1) && !bNoJump)
    fprintf(stderr,"WARNING: More than one frame was used for option -cv or -cf\n"
	    "If atoms jump across the box you should use the -nojump option\n");

  if (bCV)
    write_pdb_bfac(opt2fn("-cv",NFILE,fnm),
		   opt2fn("-av",NFILE,fnm),"average velocity",&(top.atoms),
		   ePBC,topbox,isize[0],index[0],nr_xfr,sumxv,
		   nr_vfr,sumv,bDim,scale);
  if (bCF)
    write_pdb_bfac(opt2fn("-cf",NFILE,fnm),
		   opt2fn("-af",NFILE,fnm),"average force",&(top.atoms),
		   ePBC,topbox,isize[0],index[0],nr_xfr,sumxf,
		   nr_ffr,sumf,bDim,scale);

  /* view it */
  view_all(NFILE, fnm);
  
  thanx(stderr);
  
  return 0;
}