Exemple #1
0
int gmx_rmsf(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes the root mean square fluctuation (RMSF, i.e. standard ",
        "deviation) of atomic positions in the trajectory (supplied with [TT]-f[tt])",
        "after (optionally) fitting to a reference frame (supplied with [TT]-s[tt]).[PAR]",
        "With option [TT]-oq[tt] the RMSF values are converted to B-factor",
        "values, which are written to a [REF].pdb[ref] file with the coordinates, of the",
        "structure file, or of a [REF].pdb[ref] file when [TT]-q[tt] is specified.",
        "Option [TT]-ox[tt] writes the B-factors to a file with the average",
        "coordinates.[PAR]",
        "With the option [TT]-od[tt] the root mean square deviation with",
        "respect to the reference structure is calculated.[PAR]",
        "With the option [TT]-aniso[tt], [THISMODULE] will compute anisotropic",
        "temperature factors and then it will also output average coordinates",
        "and a [REF].pdb[ref] file with ANISOU records (corresonding to the [TT]-oq[tt]",
        "or [TT]-ox[tt] option). Please note that the U values",
        "are orientation-dependent, so before comparison with experimental data",
        "you should verify that you fit to the experimental coordinates.[PAR]",
        "When a [REF].pdb[ref] input file is passed to the program and the [TT]-aniso[tt]",
        "flag is set",
        "a correlation plot of the Uij will be created, if any anisotropic",
        "temperature factors are present in the [REF].pdb[ref] file.[PAR]",
        "With option [TT]-dir[tt] the average MSF (3x3) matrix is diagonalized.",
        "This shows the directions in which the atoms fluctuate the most and",
        "the least."
    };
    static gmx_bool   bRes    = FALSE, bAniso = FALSE, bFit = TRUE;
    t_pargs           pargs[] = {
        { "-res", FALSE, etBOOL, {&bRes},
          "Calculate averages for each residue" },
        { "-aniso", FALSE, etBOOL, {&bAniso},
          "Compute anisotropic termperature factors" },
        { "-fit", FALSE, etBOOL, {&bFit},
          "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." }
    };
    int               natom;
    int               i, m, teller = 0;
    real              t, *w_rls;

    t_topology        top;
    int               ePBC;
    t_atoms          *pdbatoms, *refatoms;

    matrix            box, pdbbox;
    rvec             *x, *pdbx, *xref;
    t_trxstatus      *status;
    const char       *label;

    FILE             *fp;         /* the graphics file */
    const char       *devfn, *dirfn;
    int               resind;

    gmx_bool          bReadPDB;
    int              *index;
    int               isize;
    char             *grpnames;

    real              bfac, pdb_bfac, *Uaver;
    double          **U, *xav;
    int               aid;
    rvec             *rmsd_x = nullptr;
    double           *rmsf, invcount, totmass;
    int               d;
    real              count = 0;
    rvec              xcm;
    gmx_rmpbc_t       gpbc = nullptr;

    gmx_output_env_t *oenv;

    const char       *leg[2] = { "MD", "X-Ray" };

    t_filenm          fnm[] = {
        { efTRX, "-f",  nullptr,     ffREAD  },
        { efTPS, nullptr,  nullptr,     ffREAD  },
        { efNDX, nullptr,  nullptr,     ffOPTRD },
        { efPDB, "-q",  nullptr,     ffOPTRD },
        { efPDB, "-oq", "bfac",   ffOPTWR },
        { efPDB, "-ox", "xaver",  ffOPTWR },
        { efXVG, "-o",  "rmsf",   ffWRITE },
        { efXVG, "-od", "rmsdev", ffOPTWR },
        { efXVG, "-oc", "correl", ffOPTWR },
        { efLOG, "-dir", "rmsf",  ffOPTWR }
    };
#define NFILE asize(fnm)

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

    bReadPDB = ftp2bSet(efPDB, NFILE, fnm);
    devfn    = opt2fn_null("-od", NFILE, fnm);
    dirfn    = opt2fn_null("-dir", NFILE, fnm);

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xref, nullptr, box, TRUE);
    const char *title = *top.name;
    snew(w_rls, top.atoms.nr);

    fprintf(stderr, "Select group(s) for root mean square calculation\n");
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpnames);

    /* Set the weight */
    for (i = 0; i < isize; i++)
    {
        w_rls[index[i]] = top.atoms.atom[index[i]].m;
    }

    /* Malloc the rmsf arrays */
    snew(xav, isize*DIM);
    snew(U, isize);
    for (i = 0; i < isize; i++)
    {
        snew(U[i], DIM*DIM);
    }
    snew(rmsf, isize);
    if (devfn)
    {
        snew(rmsd_x, isize);
    }

    if (bReadPDB)
    {
        t_topology *top_pdb;
        snew(top_pdb, 1);
        /* Read coordinates twice */
        read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, nullptr, nullptr, pdbbox, FALSE);
        snew(pdbatoms, 1);
        *pdbatoms = top_pdb->atoms;
        read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, &pdbx, nullptr, pdbbox, FALSE);
        /* TODO Should this assert that top_pdb->atoms.nr == top.atoms.nr?
         * See discussion at https://gerrit.gromacs.org/#/c/6430/1 */
        title = *top_pdb->name;
        snew(refatoms, 1);
        *refatoms = top_pdb->atoms;
        sfree(top_pdb);
    }
    else
    {
        pdbatoms  = &top.atoms;
        refatoms  = &top.atoms;
        pdbx      = xref;
        snew(pdbatoms->pdbinfo, pdbatoms->nr);
        pdbatoms->havePdbInfo = TRUE;
        copy_mat(box, pdbbox);
    }

    if (bFit)
    {
        sub_xcm(xref, isize, index, top.atoms.atom, xcm, FALSE);
    }

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

    if (bFit)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natom);
    }

    /* Now read the trj again to compute fluctuations */
    teller = 0;
    do
    {
        if (bFit)
        {
            /* Remove periodic boundary */
            gmx_rmpbc(gpbc, natom, box, x);

            /* Set center of mass to zero */
            sub_xcm(x, isize, index, top.atoms.atom, xcm, FALSE);

            /* Fit to reference structure */
            do_fit(natom, w_rls, xref, x);
        }

        /* Calculate Anisotropic U Tensor */
        for (i = 0; i < isize; i++)
        {
            aid = index[i];
            for (d = 0; d < DIM; d++)
            {
                xav[i*DIM + d] += x[aid][d];
                for (m = 0; m < DIM; m++)
                {
                    U[i][d*DIM + m] += x[aid][d]*x[aid][m];
                }
            }
        }

        if (devfn)
        {
            /* Calculate RMS Deviation */
            for (i = 0; (i < isize); i++)
            {
                aid = index[i];
                for (d = 0; (d < DIM); d++)
                {
                    rmsd_x[i][d] += gmx::square(x[aid][d]-xref[aid][d]);
                }
            }
        }
        count += 1.0;
        teller++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trx(status);

    if (bFit)
    {
        gmx_rmpbc_done(gpbc);
    }


    invcount = 1.0/count;
    snew(Uaver, DIM*DIM);
    totmass = 0;
    for (i = 0; i < isize; i++)
    {
        for (d = 0; d < DIM; d++)
        {
            xav[i*DIM + d] *= invcount;
        }
        for (d = 0; d < DIM; d++)
        {
            for (m = 0; m < DIM; m++)
            {
                U[i][d*DIM + m] = U[i][d*DIM + m]*invcount
                    - xav[i*DIM + d]*xav[i*DIM + m];
                Uaver[3*d+m] += top.atoms.atom[index[i]].m*U[i][d*DIM + m];
            }
        }
        totmass += top.atoms.atom[index[i]].m;
    }
    for (d = 0; d < DIM*DIM; d++)
    {
        Uaver[d] /= totmass;
    }

    if (bRes)
    {
        for (d = 0; d < DIM*DIM; d++)
        {
            average_residues(nullptr, U, d, isize, index, w_rls, &top.atoms);
        }
    }

    if (bAniso)
    {
        for (i = 0; i < isize; i++)
        {
            aid = index[i];
            pdbatoms->pdbinfo[aid].bAnisotropic = TRUE;
            pdbatoms->pdbinfo[aid].uij[U11]     = static_cast<int>(1e6*U[i][XX*DIM + XX]);
            pdbatoms->pdbinfo[aid].uij[U22]     = static_cast<int>(1e6*U[i][YY*DIM + YY]);
            pdbatoms->pdbinfo[aid].uij[U33]     = static_cast<int>(1e6*U[i][ZZ*DIM + ZZ]);
            pdbatoms->pdbinfo[aid].uij[U12]     = static_cast<int>(1e6*U[i][XX*DIM + YY]);
            pdbatoms->pdbinfo[aid].uij[U13]     = static_cast<int>(1e6*U[i][XX*DIM + ZZ]);
            pdbatoms->pdbinfo[aid].uij[U23]     = static_cast<int>(1e6*U[i][YY*DIM + ZZ]);
        }
    }
    if (bRes)
    {
        label = "Residue";
    }
    else
    {
        label = "Atom";
    }

    for (i = 0; i < isize; i++)
    {
        rmsf[i] = U[i][XX*DIM + XX] + U[i][YY*DIM + YY] + U[i][ZZ*DIM + ZZ];
    }

    if (dirfn)
    {
        fprintf(stdout, "\n");
        print_dir(stdout, Uaver);
        fp = gmx_ffopen(dirfn, "w");
        print_dir(fp, Uaver);
        gmx_ffclose(fp);
    }

    for (i = 0; i < isize; i++)
    {
        sfree(U[i]);
    }
    sfree(U);

    /* Write RMSF output */
    if (bReadPDB)
    {
        bfac = 8.0*M_PI*M_PI/3.0*100;
        fp   = xvgropen(ftp2fn(efXVG, NFILE, fnm), "B-Factors",
                        label, "(A\\b\\S\\So\\N\\S2\\N)", oenv);
        xvgr_legend(fp, 2, leg, oenv);
        for (i = 0; (i < isize); i++)
        {
            if (!bRes || i+1 == isize ||
                top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind)
            {
                resind    = top.atoms.atom[index[i]].resind;
                pdb_bfac  = find_pdb_bfac(pdbatoms, &top.atoms.resinfo[resind],
                                          *(top.atoms.atomname[index[i]]));

                fprintf(fp, "%5d  %10.5f  %10.5f\n",
                        bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, rmsf[i]*bfac,
                        pdb_bfac);
            }
        }
        xvgrclose(fp);
    }
    else
    {
        fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS fluctuation", label, "(nm)", oenv);
        for (i = 0; i < isize; i++)
        {
            if (!bRes || i+1 == isize ||
                top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind)
            {
                fprintf(fp, "%5d %8.4f\n",
                        bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i]));
            }
        }
        xvgrclose(fp);
    }

    for (i = 0; i < isize; i++)
    {
        pdbatoms->pdbinfo[index[i]].bfac = 800*M_PI*M_PI/3.0*rmsf[i];
    }

    if (devfn)
    {
        for (i = 0; i < isize; i++)
        {
            rmsf[i] = (rmsd_x[i][XX]+rmsd_x[i][YY]+rmsd_x[i][ZZ])/count;
        }
        if (bRes)
        {
            average_residues(rmsf, nullptr, 0, isize, index, w_rls, &top.atoms);
        }
        /* Write RMSD output */
        fp = xvgropen(devfn, "RMS Deviation", label, "(nm)", oenv);
        for (i = 0; i < isize; i++)
        {
            if (!bRes || i+1 == isize ||
                top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind)
            {
                fprintf(fp, "%5d %8.4f\n",
                        bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i]));
            }
        }
        xvgrclose(fp);
    }

    if (opt2bSet("-oq", NFILE, fnm))
    {
        /* Write a .pdb file with B-factors and optionally anisou records */
        for (i = 0; i < isize; i++)
        {
            rvec_inc(pdbx[index[i]], xcm);
        }
        write_sto_conf_indexed(opt2fn("-oq", NFILE, fnm), title, pdbatoms, pdbx,
                               nullptr, ePBC, pdbbox, isize, index);
    }
    if (opt2bSet("-ox", NFILE, fnm))
    {
        rvec *bFactorX;
        snew(bFactorX, top.atoms.nr);
        for (i = 0; i < isize; i++)
        {
            for (d = 0; d < DIM; d++)
            {
                bFactorX[index[i]][d] = xcm[d] + xav[i*DIM + d];
            }
        }
        /* Write a .pdb file with B-factors and optionally anisou records */
        write_sto_conf_indexed(opt2fn("-ox", NFILE, fnm), title, pdbatoms, bFactorX, nullptr,
                               ePBC, pdbbox, isize, index);
        sfree(bFactorX);
    }
    if (bAniso)
    {
        correlate_aniso(opt2fn("-oc", NFILE, fnm), refatoms, pdbatoms, oenv);
        do_view(oenv, opt2fn("-oc", NFILE, fnm), "-nxy");
    }
    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    if (devfn)
    {
        do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy");
    }

    return 0;
}
int gmx_rmsf(int argc,char *argv[])
{
  static char *desc[] = {
    "g_rmsf computes the root mean square fluctuation (RMSF, i.e. standard ",
    "deviation) of atomic positions ",
    "after (optionally) fitting to a reference frame.[PAR]",
    "With option [TT]-oq[tt] the RMSF values are converted to B-factor",
    "values, which are written to a pdb file with the coordinates, of the",
    "structure file, or of a pdb file when [TT]-q[tt] is specified.",
    "Option [TT]-ox[tt] writes the B-factors to a file with the average",
    "coordinates.[PAR]",
    "With the option [TT]-od[tt] the root mean square deviation with",
    "respect to the reference structure is calculated.[PAR]",
    "With the option [TT]aniso[tt] g_rmsf will compute anisotropic",
    "temperature factors and then it will also output average coordinates",
    "and a pdb file with ANISOU records (corresonding to the [TT]-oq[tt]",
    "or [TT]-ox[tt] option). Please note that the U values",
    "are orientation dependent, so before comparison with experimental data",
    "you should verify that you fit to the experimental coordinates.[PAR]",
    "When a pdb input file is passed to the program and the [TT]-aniso[tt]",
    "flag is set",
    "a correlation plot of the Uij will be created, if any anisotropic",
    "temperature factors are present in the pdb file.[PAR]",
    "With option [TT]-dir[tt] the average MSF (3x3) matrix is diagonalized.",
    "This shows the directions in which the atoms fluctuate the most and",
    "the least."
  };
  static bool bRes=FALSE,bAniso=FALSE,bdevX=FALSE,bFit=TRUE;
  t_pargs pargs[] = { 
    { "-res", FALSE, etBOOL, {&bRes},
      "Calculate averages for each residue" },
    { "-aniso",FALSE, etBOOL, {&bAniso},
      "Compute anisotropic termperature factors" },
    { "-fit", FALSE, etBOOL, {&bFit},
      "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." }
  };
  int          step,nre,natom,natoms,i,g,m,teller=0;
  real         t,lambda,*w_rls,*w_rms;
  
  t_tpxheader  header;
  t_inputrec   ir;
  t_topology   top;
  int          ePBC;
  t_atoms      *pdbatoms,*refatoms;
  bool         bCont;

  matrix       box,pdbbox;
  rvec         *x,*pdbx,*xref;
  int          status,npdbatoms,res0;
  char         buf[256],*label;
  char         title[STRLEN];
  
  FILE         *fp;               /* the graphics file */
  char         *devfn,*dirfn;
  int          resnr;

  bool         bReadPDB;  
  atom_id      *index;
  int          isize;
  char         *grpnames;

  real         bfac,pdb_bfac,*Uaver;
  double       **U,*xav;
  atom_id      aid;
  rvec         *rmsd_x=NULL;
  real         *rmsf,invcount,totmass;
  int          d;
  real         count=0;
  rvec         xcm;

  char         *leg[2] = { "MD", "X-Ray" };

  t_filenm fnm[] = {
    { efTRX, "-f",  NULL,     ffREAD  },
    { efTPS, NULL,  NULL,     ffREAD  },
    { efNDX, NULL,  NULL,     ffOPTRD },
    { efPDB, "-q",  NULL,     ffOPTRD },
    { efPDB, "-oq", "bfac",   ffOPTWR },
    { efPDB, "-ox", "xaver",  ffOPTWR },
    { efXVG, "-o",  "rmsf",   ffWRITE },
    { efXVG, "-od", "rmsdev", ffOPTWR },
    { efXVG, "-oc", "correl", ffOPTWR },
    { efLOG, "-dir", "rmsf",  ffOPTWR }
  };
#define NFILE asize(fnm)
 
  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE ,
		    NFILE,fnm,asize(pargs),pargs,asize(desc),desc,0,NULL);

  bReadPDB = ftp2bSet(efPDB,NFILE,fnm);
  devfn    = opt2fn_null("-od",NFILE,fnm);
  dirfn    = opt2fn_null("-dir",NFILE,fnm);

  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xref,NULL,box,TRUE);
  snew(w_rls,top.atoms.nr);

  fprintf(stderr,"Select group(s) for root mean square calculation\n");
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpnames);

  /* Set the weight */
  for(i=0; i<isize; i++) 
    w_rls[index[i]]=top.atoms.atom[index[i]].m;

  /* Malloc the rmsf arrays */
  snew(xav,isize*DIM);
  snew(U,isize);
  for(i=0; i<isize; i++)
    snew(U[i],DIM*DIM);
  snew(rmsf,isize);
  if (devfn)
    snew(rmsd_x, isize);
  
  if (bReadPDB) {
    get_stx_coordnum(opt2fn("-q",NFILE,fnm),&npdbatoms);
    snew(pdbatoms,1);
    snew(refatoms,1);
    init_t_atoms(pdbatoms,npdbatoms,TRUE);
    init_t_atoms(refatoms,npdbatoms,TRUE);
    snew(pdbx,npdbatoms);
    /* Read coordinates twice */
    read_stx_conf(opt2fn("-q",NFILE,fnm),title,pdbatoms,pdbx,NULL,NULL,pdbbox);
    read_stx_conf(opt2fn("-q",NFILE,fnm),title,refatoms,pdbx,NULL,NULL,pdbbox);
  } else {
    pdbatoms  = &top.atoms;
    refatoms  = &top.atoms;
    pdbx      = xref;
    npdbatoms = pdbatoms->nr;
    snew(pdbatoms->pdbinfo,npdbatoms);
    copy_mat(box,pdbbox);
  }
  
  if (bFit)
    sub_xcm(xref,isize,index,top.atoms.atom,xcm,FALSE);
  
  natom = read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
    
  /* Now read the trj again to compute fluctuations */
  teller = 0;
  do {
    if (bFit) {
      /* Remove periodic boundary */
      rm_pbc(&(top.idef),ePBC,natom,box,x,x);
      
      /* Set center of mass to zero */
      sub_xcm(x,isize,index,top.atoms.atom,xcm,FALSE);
      
      /* Fit to reference structure */
      do_fit(natom,w_rls,xref,x);
    }
     
    /* Calculate Anisotropic U Tensor */  
    for(i=0; i<isize; i++) {
      aid = index[i];
      for(d=0; d<DIM; d++) {
	xav[i*DIM + d] += x[aid][d];
	for(m=0; m<DIM; m++)
	  U[i][d*DIM + m] += x[aid][d]*x[aid][m];
      }
    }
    
    if (devfn) {
      /* Calculate RMS Deviation */
      for(i=0;(i<isize);i++) {
	aid = index[i];
	for(d=0;(d<DIM);d++) {
	  rmsd_x[i][d] += sqr(x[aid][d]-xref[aid][d]);
	}
      }
    } 
    count += 1.0;
    teller++;
  } while(read_next_x(status,&t,natom,x,box));
  close_trj(status);
  
  invcount = 1.0/count;
  snew(Uaver,DIM*DIM);
  totmass = 0;
  for(i=0; i<isize; i++) {
    for(d=0; d<DIM; d++)
      xav[i*DIM + d] *= invcount;
    for(d=0; d<DIM; d++)
      for(m=0; m<DIM; m++) {
	U[i][d*DIM + m] = U[i][d*DIM + m]*invcount 
	  - xav[i*DIM + d]*xav[i*DIM + m];
	Uaver[3*d+m] += top.atoms.atom[index[i]].m*U[i][d*DIM + m];
      }
    totmass += top.atoms.atom[index[i]].m;
  }
  for(d=0; d<DIM*DIM; d++)
    Uaver[d] /= totmass;

  if (bAniso) {
    for(i=0; i<isize; i++) {
      aid = index[i];
      pdbatoms->pdbinfo[aid].bAnisotropic = TRUE;
      pdbatoms->pdbinfo[aid].uij[U11] = 1e6*U[i][XX*DIM + XX];
      pdbatoms->pdbinfo[aid].uij[U22] = 1e6*U[i][YY*DIM + YY];
      pdbatoms->pdbinfo[aid].uij[U33] = 1e6*U[i][ZZ*DIM + ZZ];
      pdbatoms->pdbinfo[aid].uij[U12] = 1e6*U[i][XX*DIM + YY];
      pdbatoms->pdbinfo[aid].uij[U13] = 1e6*U[i][XX*DIM + ZZ];
      pdbatoms->pdbinfo[aid].uij[U23] = 1e6*U[i][YY*DIM + ZZ];
    }
  }
  if (bRes) {
    average_residues(rmsf,isize,index,w_rls,&top.atoms);
    label = "Residue";
  } else
    label = "Atom";

  for(i=0; i<isize; i++)
    rmsf[i] = U[i][XX*DIM + XX] + U[i][YY*DIM + YY] + U[i][ZZ*DIM + ZZ];
  
  if (dirfn) {
    fprintf(stdout,"\n");
    print_dir(stdout,Uaver);
    fp = ffopen(dirfn,"w");
    print_dir(fp,Uaver);
    fclose(fp);
  }

  for(i=0; i<isize; i++)
    sfree(U[i]);
  sfree(U);

  /* Write RMSF output */
  if (bReadPDB) {
    bfac = 8.0*M_PI*M_PI/3.0*100;
    fp   = xvgropen(ftp2fn(efXVG,NFILE,fnm),"B-Factors",
		    label,"(A\\b\\S\\So\\N\\S2\\N)");
    xvgr_legend(fp,2,leg);
    for(i=0;(i<isize);i++) {
      if (!bRes || i+1==isize ||
	  top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr) {
	resnr    = top.atoms.atom[index[i]].resnr;
	pdb_bfac = find_pdb_bfac(pdbatoms,*(top.atoms.resname[resnr]),resnr,
				 *(top.atoms.atomname[index[i]]));
	
	fprintf(fp,"%5d  %10.5f  %10.5f\n",
		bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,rmsf[i]*bfac,
		pdb_bfac);
      }
    }
    fclose(fp);
  } else {
    fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),"RMS fluctuation",label,"(nm)");
    for(i=0; i<isize; i++)
      if (!bRes || i+1==isize ||
	  top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr)
	fprintf(fp,"%5d %8.4f\n",
		bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,sqrt(rmsf[i]));
    fclose(fp);
  }
  
  for(i=0; i<isize; i++)
    pdbatoms->pdbinfo[index[i]].bfac = 800*M_PI*M_PI/3.0*rmsf[i];

  if (devfn) {
    for(i=0; i<isize; i++)
      rmsf[i] = (rmsd_x[i][XX]+rmsd_x[i][YY]+rmsd_x[i][ZZ])/count;
    if (bRes)
      average_residues(rmsf,isize,index,w_rls,&top.atoms); 
    /* Write RMSD output */
    fp = xvgropen(devfn,"RMS Deviation",label,"(nm)");
    for(i=0; i<isize; i++)
      if (!bRes || i+1==isize ||
	  top.atoms.atom[index[i]].resnr!=top.atoms.atom[index[i+1]].resnr)
	fprintf(fp,"%5d %8.4f\n",
		bRes ? top.atoms.atom[index[i]].resnr+1 : i+1,sqrt(rmsf[i]));
    fclose(fp);
  }

  if (opt2bSet("-oq",NFILE,fnm)) {
    /* Write a pdb file with B-factors and optionally anisou records */
    for(i=0; i<isize; i++)
      rvec_inc(xref[index[i]],xcm);
    write_sto_conf_indexed(opt2fn("-oq",NFILE,fnm),title,pdbatoms,pdbx,
			   NULL,ePBC,pdbbox,isize,index);
  }
  if (opt2bSet("-ox",NFILE,fnm)) {
    /* Misuse xref as a temporary array */
    for(i=0; i<isize; i++)
      for(d=0; d<DIM; d++)
	xref[index[i]][d] = xcm[d] + xav[i*DIM + d];
    /* Write a pdb file with B-factors and optionally anisou records */
    write_sto_conf_indexed(opt2fn("-ox",NFILE,fnm),title,pdbatoms,xref,NULL,
			   ePBC,pdbbox,isize,index);
  }
  if (bAniso) { 
    correlate_aniso(opt2fn("-oc",NFILE,fnm),refatoms,pdbatoms);
    do_view(opt2fn("-oc",NFILE,fnm),"-nxy");
  }
  do_view(opt2fn("-o",NFILE,fnm),"-nxy");
  if (devfn)
    do_view(opt2fn("-od",NFILE,fnm),"-nxy");
    
  thanx(stderr);
  
  return 0;
}