Ejemplo n.º 1
0
static void do_rdf(char *fnNDX,char *fnTPS,char *fnTRX,
		   char *fnRDF,char *fnCNRDF, char *fnHQ,
		   bool bCM,char **rdft,bool bXY,bool bPBC,bool bNormalize,
		   real cutoff,real binwidth,real fade,int ng)
{
  FILE       *fp;
  int        status;
  char       outf1[STRLEN],outf2[STRLEN];
  char       title[STRLEN],gtitle[STRLEN];
  int        g,natoms,i,j,k,nbin,j0,j1,n,nframes;
  int        **count;
  char       **grpname;
  int        *isize,isize_cm=0,nrdf=0,max_i,isize0,isize_g;
  atom_id    **index,*index_cm=NULL;
#if (defined SIZEOF_LONG_LONG_INT) && (SIZEOF_LONG_LONG_INT >= 8)    
  long long int *sum;
#else
  double     *sum;
#endif
  real       t,rmax2,cut2,r,r2,invhbinw,normfac;
  real       segvol,spherevol,prev_spherevol,**rdf;
  rvec       *x,dx,*x0=NULL,*x_i1,xi;
  real       *inv_segvol,invvol,invvol_sum,rho;
  bool       *bExcl,bTop,bNonSelfExcl;
  matrix     box,box_pbc;
  int        **npairs;
  atom_id    ix,jx,***pairs;
  t_topology *top=NULL;
  int        ePBC=-1;
  t_block    *mols=NULL;
  t_blocka   *excl;
  t_atom     *atom=NULL;
  t_pbc      pbc;

  int        *is=NULL,**coi=NULL,cur,mol,i1,res,a;

  excl=NULL;
  
  if (fnTPS) {
    snew(top,1);
    bTop=read_tps_conf(fnTPS,title,top,&ePBC,&x,NULL,box,TRUE);
    if (bTop && !bCM)
      /* get exclusions from topology */
      excl = &(top->excls);
  }
  snew(grpname,ng+1);
  snew(isize,ng+1);
  snew(index,ng+1);
  fprintf(stderr,"\nSelect a reference group and %d group%s\n",
	  ng,ng==1?"":"s");
  if (fnTPS) {
    get_index(&(top->atoms),fnNDX,ng+1,isize,index,grpname);
    atom = top->atoms.atom;
  } else {
    rd_index(fnNDX,ng+1,isize,index,grpname);
  }

  if (rdft[0][0] != 'a') {
    /* Split up all the groups in molecules or residues */
    switch (rdft[0][0]) {
    case 'm':
      mols = &top->mols;
      break;
    case 'r':
      atom = top->atoms.atom;
      break;
    default:
      gmx_fatal(FARGS,"Unknown rdf option '%s'",rdft[0]);
    }
    snew(is,ng+1);
    snew(coi,ng+1);
    for(g=(bCM ? 1 : 0); g<ng+1; g++) {
      snew(coi[g],isize[g]+1);
      is[g] = 0;
      cur = -1;
      mol = 0;
      for(i=0; i<isize[g]; i++) {
	a = index[g][i];
	if (rdft[0][0] == 'm') {
	  /* Check if the molecule number has changed */
	  i1 = mols->index[mol+1];
	  while(a >= i1) {
	    mol++;
	    i1 = mols->index[mol+1];
	  }
	  if (mol != cur) {
	    coi[g][is[g]++] = i;
	    cur = mol;
	  }
	} else if (rdft[0][0] == 'r') {
	  /* Check if the residue number has changed */
	  res = atom[a].resnr;
	  if (res != cur) {
	    coi[g][is[g]++] = i;
	    cur = res;
	  }
	}
      }
      coi[g][is[g]] = i;
      srenew(coi[g],is[g]+1);
      printf("Group '%s' of %d atoms consists of %d %s\n",
	     grpname[g],isize[g],is[g],
	     (rdft[0][0]=='m' ? "molecules" : "residues"));
    }
  } else if (bCM) {
    snew(is,1);
    snew(coi,1);
  }
  
  if (bCM) {
    is[0] = 1;
    snew(coi[0],is[0]+1);
    coi[0][0] = 0;
    coi[0][1] = isize[0];
    isize0 = is[0];
    snew(x0,isize0);
  } else if (rdft[0][0] != 'a') {
    isize0 = is[0];
    snew(x0,isize0);
  } else {
    isize0 = isize[0];
  }
  
  natoms=read_first_x(&status,fnTRX,&t,&x,box);
  if ( !natoms )
    gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
  if (fnTPS)
    /* check with topology */
    if ( natoms > top->atoms.nr ) 
      gmx_fatal(FARGS,"Trajectory (%d atoms) does not match topology (%d atoms)",
		  natoms,top->atoms.nr);
  /* check with index groups */
  for (i=0; i<ng+1; i++)
    for (j=0; j<isize[i]; j++)
      if ( index[i][j] >= natoms )
	gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) larger "
		  "than number of atoms in trajectory (%d atoms)",
		  index[i][j],grpname[i],isize[i],natoms);
  
  /* initialize some handy things */
  copy_mat(box,box_pbc);
  if (bXY) {
    check_box_c(box);
    /* Make sure the z-height does not influence the cut-off */
    box_pbc[ZZ][ZZ] = 2*max(box[XX][XX],box[YY][YY]);
  }
  if (bPBC)
    rmax2   = 0.99*0.99*max_cutoff2(bXY ? epbcXY : epbcXYZ,box_pbc);
  else
    rmax2   = sqr(3*max(box[XX][XX],max(box[YY][YY],box[ZZ][ZZ])));
  if (debug)
    fprintf(debug,"rmax2 = %g\n",rmax2);

  /* We use the double amount of bins, so we can correctly
   * write the rdf and rdf_cn output at i*binwidth values.
   */
  nbin     = (int)(sqrt(rmax2) * 2 / binwidth);
  invhbinw = 2.0 / binwidth;
  cut2   = sqr(cutoff);

  snew(count,ng);
  snew(pairs,ng);
  snew(npairs,ng);

  snew(bExcl,natoms);
  max_i = 0;
  for(g=0; g<ng; g++) {
    if (isize[g+1] > max_i)
      max_i = isize[g+1];

    /* this is THE array */
    snew(count[g],nbin+1);
  
    /* make pairlist array for groups and exclusions */
    snew(pairs[g],isize[0]);
    snew(npairs[g],isize[0]);
    for(i=0; i<isize[0]; i++) {
      /* We can only have exclusions with atomic rdfs */
      if (!(bCM || rdft[0][0] != 'a')) {
	ix = index[0][i];
	for(j=0; j < natoms; j++)
	  bExcl[j] = FALSE;
	/* exclusions? */
	if (excl)
	  for( j = excl->index[ix]; j < excl->index[ix+1]; j++)
	    bExcl[excl->a[j]]=TRUE;
	k = 0;
	snew(pairs[g][i], isize[g+1]);
	bNonSelfExcl = FALSE;
	for(j=0; j<isize[g+1]; j++) {
	  jx = index[g+1][j];
	  if (!bExcl[jx])
	    pairs[g][i][k++]=jx;
	  else if (ix != jx)
	    /* Check if we have exclusions other than self exclusions */
	    bNonSelfExcl = TRUE;
	}
	if (bNonSelfExcl) {
	  npairs[g][i]=k;
	  srenew(pairs[g][i],npairs[g][i]);
	} else {
	  /* Save a LOT of memory and some cpu cycles */
	  npairs[g][i]=-1;
	  sfree(pairs[g][i]);
	}
      } else {
	npairs[g][i]=-1;
      }
    }
  }
  sfree(bExcl);

  snew(x_i1,max_i);
  nframes = 0;
  invvol_sum = 0;
  do {
    /* Must init pbc every step because of pressure coupling */
    copy_mat(box,box_pbc);
    if (bPBC) {
      if (top != NULL)
	rm_pbc(&top->idef,ePBC,natoms,box,x,x);
      if (bXY) {
	check_box_c(box);
	clear_rvec(box_pbc[ZZ]);
      }
      set_pbc(&pbc,ePBC,box_pbc);

      if (bXY)
	/* Set z-size to 1 so we get the surface iso the volume */
	box_pbc[ZZ][ZZ] = 1;
    }
    invvol = 1/det(box_pbc);
    invvol_sum += invvol;

    if (bCM) {
      /* Calculate center of mass of the whole group */
      calc_comg(is[0],coi[0],index[0],TRUE           ,atom,x,x0);
    } else if (rdft[0][0] != 'a') {
      calc_comg(is[0],coi[0],index[0],rdft[0][6]=='m',atom,x,x0);
    }

    for(g=0; g<ng; g++) {
      if (rdft[0][0] == 'a') {
	/* Copy the indexed coordinates to a continuous array */
	for(i=0; i<isize[g+1]; i++)
	  copy_rvec(x[index[g+1][i]],x_i1[i]);
      } else {
	/* Calculate the COMs/COGs and store in x_i1 */
	calc_comg(is[g+1],coi[g+1],index[g+1],rdft[0][6]=='m',atom,x,x_i1);
      }
    
      for(i=0; i<isize0; i++) {
	if (bCM || rdft[0][0] != 'a') {
	  copy_rvec(x0[i],xi);
	} else {
	  copy_rvec(x[index[0][i]],xi);
	}
	if (rdft[0][0] == 'a' && npairs[g][i] >= 0) {
	  /* Expensive loop, because of indexing */
	  for(j=0; j<npairs[g][i]; j++) {
	    jx=pairs[g][i][j];
	    if (bPBC)
	      pbc_dx(&pbc,xi,x[jx],dx);
	    else
	      rvec_sub(xi,x[jx],dx);
	      
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	} else {
	  /* Cheaper loop, no exclusions */
	  if (rdft[0][0] == 'a')
	    isize_g = isize[g+1];
	  else
	    isize_g = is[g+1];
	  for(j=0; j<isize_g; j++) {
	    if (bPBC)
	      pbc_dx(&pbc,xi,x_i1[j],dx);
	    else
	      rvec_sub(xi,x_i1[j],dx);
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	}
      }
    }
    nframes++;
  } while (read_next_x(status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  close_trj(status);
  
  sfree(x);
  
  /* Average volume */
  invvol = invvol_sum/nframes;

  /* Calculate volume of sphere segments or length of circle segments */
  snew(inv_segvol,(nbin+1)/2);
  prev_spherevol=0;
  for(i=0; (i<(nbin+1)/2); i++) {
    r = (i + 0.5)*binwidth;
    if (bXY) {
      spherevol=M_PI*r*r;
    } else {
      spherevol=(4.0/3.0)*M_PI*r*r*r;
    }
    segvol=spherevol-prev_spherevol;
    inv_segvol[i]=1.0/segvol;
    prev_spherevol=spherevol;
  }
  
  snew(rdf,ng);
  for(g=0; g<ng; g++) {
    /* We have to normalize by dividing by the number of frames */
    if (rdft[0][0] == 'a')
      normfac = 1.0/(nframes*invvol*isize0*isize[g+1]);
    else
      normfac = 1.0/(nframes*invvol*isize0*is[g+1]);
      
    /* Do the normalization */
    nrdf = max((nbin+1)/2,1+2*fade/binwidth);
    snew(rdf[g],nrdf);
    for(i=0; i<(nbin+1)/2; i++) {
      r = i*binwidth;
      if (i == 0)
	j = count[g][0];
      else
	j = count[g][i*2-1] + count[g][i*2];
      if ((fade > 0) && (r >= fade))
	rdf[g][i] = 1 + (j*inv_segvol[i]*normfac-1)*exp(-16*sqr(r/fade-1));
      else {
	if (bNormalize)
	  rdf[g][i] = j*inv_segvol[i]*normfac;
	else
	  rdf[g][i] = j/(binwidth*isize0*nframes);
      }
    }
    for( ; (i<nrdf); i++)
      rdf[g][i] = 1.0;
  }

  if (rdft[0][0] == 'a') {
    sprintf(gtitle,"Radial distribution");
  } else {
    sprintf(gtitle,"Radial distribution of %s %s",
	    rdft[0][0]=='m' ? "molecule" : "residue",
	    rdft[0][6]=='m' ? "COM" : "COG");
  }
  fp=xvgropen(fnRDF,gtitle,"r","");
  if (ng==1) {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"%s%s - %s\"\n",
	      grpname[0],bCM ? " COM" : "",grpname[1]);
  }
  else {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"reference %s%s\"\n",
	      grpname[0],bCM ? " COM" : "");
    xvgr_legend(fp,ng,grpname+1);
  }
  for(i=0; (i<nrdf); i++) {
    fprintf(fp,"%10g",i*binwidth);
    for(g=0; g<ng; g++)
      fprintf(fp," %10g",rdf[g][i]);
    fprintf(fp,"\n");
  }
  ffclose(fp);
  
  do_view(fnRDF,NULL);

  /* h(Q) function: fourier transform of rdf */  
  if (fnHQ) {
    int nhq = 401;
    real *hq,*integrand,Q;
    
    /* Get a better number density later! */
    rho = isize[1]*invvol;
    snew(hq,nhq);
    snew(integrand,nrdf);
    for(i=0; (i<nhq); i++) {
      Q = i*0.5;
      integrand[0] = 0;
      for(j=1; (j<nrdf); j++) {
	r = j*binwidth;
	integrand[j]  = (Q == 0) ? 1.0 : sin(Q*r)/(Q*r);
	integrand[j] *= 4.0*M_PI*rho*r*r*(rdf[0][j]-1.0);
      }
      hq[i] = print_and_integrate(debug,nrdf,binwidth,integrand,NULL,0);
    }
    fp=xvgropen(fnHQ,"h(Q)","Q(/nm)","h(Q)");
    for(i=0; (i<nhq); i++) 
      fprintf(fp,"%10g %10g\n",i*0.5,hq[i]);
    ffclose(fp);
    do_view(fnHQ,NULL);
    sfree(hq);
    sfree(integrand);
  }
  
  if (fnCNRDF) {  
    normfac = 1.0/(isize0*nframes);
    fp=xvgropen(fnCNRDF,"Cumulative Number RDF","r","number");
    if (ng==1) {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"%s-%s\"\n",grpname[0],grpname[1]);
    }
    else {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"reference %s\"\n",grpname[0]);
      xvgr_legend(fp,ng,grpname+1);
    }
    snew(sum,ng);
    for(i=0; (i<=nbin/2); i++) {
      fprintf(fp,"%10g",i*binwidth);
      for(g=0; g<ng; g++) {
	fprintf(fp," %10g",(real)((double)sum[g]*normfac));
	if (i*2+1 < nbin)
	  sum[g] += count[g][i*2] + count[g][i*2+1];
      }
      fprintf(fp,"\n");
    }
    ffclose(fp);
    sfree(sum);
    
    do_view(fnCNRDF,NULL);
  }

  for(g=0; g<ng; g++)
    sfree(rdf[g]);
  sfree(rdf);
}
Ejemplo n.º 2
0
static void clust_size(const char *ndx, const char *trx, const char *xpm,
                       const char *xpmw, const char *ncl, const char *acl,
                       const char *mcl, const char *histo, const char *tempf,
                       const char *mcn, gmx_bool bMol, gmx_bool bPBC, const char *tpr,
                       real cut, int nskip, int nlevels,
                       t_rgb rmid, t_rgb rhi, int ndf,
                       const output_env_t oenv)
{
    FILE                 *fp, *gp, *hp, *tp;
    atom_id              *index = NULL;
    int                   nindex, natoms;
    t_trxstatus          *status;
    rvec                 *x = NULL, *v = NULL, dx;
    t_pbc                 pbc;
    char                 *gname;
    char                  timebuf[32];
    gmx_bool              bSame, bTPRwarn = TRUE;
    /* Topology stuff */
    t_trxframe            fr;
    t_tpxheader           tpxh;
    gmx_mtop_t           *mtop = NULL;
    int                   ePBC = -1;
    t_block              *mols = NULL;
    gmx_mtop_atomlookup_t alook;
    t_atom               *atom;
    int                   version, generation, ii, jj, nsame;
    real                  temp, tfac;
    /* Cluster size distribution (matrix) */
    real                **cs_dist = NULL;
    real                  tf, dx2, cut2, *t_x = NULL, *t_y, cmid, cmax, cav, ekin;
    int                   i, j, k, ai, aj, ak, ci, cj, nframe, nclust, n_x, n_y, max_size = 0;
    int                  *clust_index, *clust_size, max_clust_size, max_clust_ind, nav, nhisto;
    t_rgb                 rlo = { 1.0, 1.0, 1.0 };

    clear_trxframe(&fr, TRUE);
    sprintf(timebuf, "Time (%s)", output_env_get_time_unit(oenv));
    tf     = output_env_get_time_factor(oenv);
    fp     = xvgropen(ncl, "Number of clusters", timebuf, "N", oenv);
    gp     = xvgropen(acl, "Average cluster size", timebuf, "#molecules", oenv);
    hp     = xvgropen(mcl, "Max cluster size", timebuf, "#molecules", oenv);
    tp     = xvgropen(tempf, "Temperature of largest cluster", timebuf, "T (K)",
                      oenv);

    if (!read_first_frame(oenv, &status, trx, &fr, TRX_NEED_X | TRX_READ_V))
    {
        gmx_file(trx);
    }

    natoms = fr.natoms;
    x      = fr.x;

    if (tpr)
    {
        snew(mtop, 1);
        read_tpxheader(tpr, &tpxh, TRUE, &version, &generation);
        if (tpxh.natoms != natoms)
        {
            gmx_fatal(FARGS, "tpr (%d atoms) and xtc (%d atoms) do not match!",
                      tpxh.natoms, natoms);
        }
        ePBC = read_tpx(tpr, NULL, NULL, &natoms, NULL, NULL, NULL, mtop);
    }
    if (ndf <= -1)
    {
        tfac = 1;
    }
    else
    {
        tfac = ndf/(3.0*natoms);
    }

    if (bMol)
    {
        if (ndx)
        {
            printf("Using molecules rather than atoms. Not reading index file %s\n",
                   ndx);
        }
        mols = &(mtop->mols);

        /* Make dummy index */
        nindex = mols->nr;
        snew(index, nindex);
        for (i = 0; (i < nindex); i++)
        {
            index[i] = i;
        }
        gname = strdup("mols");
    }
    else
    {
        rd_index(ndx, 1, &nindex, &index, &gname);
    }

    alook = gmx_mtop_atomlookup_init(mtop);

    snew(clust_index, nindex);
    snew(clust_size, nindex);
    cut2   = cut*cut;
    nframe = 0;
    n_x    = 0;
    snew(t_y, nindex);
    for (i = 0; (i < nindex); i++)
    {
        t_y[i] = i+1;
    }
    max_clust_size = 1;
    max_clust_ind  = -1;
    do
    {
        if ((nskip == 0) || ((nskip > 0) && ((nframe % nskip) == 0)))
        {
            if (bPBC)
            {
                set_pbc(&pbc, ePBC, fr.box);
            }
            max_clust_size = 1;
            max_clust_ind  = -1;

            /* Put all atoms/molecules in their own cluster, with size 1 */
            for (i = 0; (i < nindex); i++)
            {
                /* Cluster index is indexed with atom index number */
                clust_index[i] = i;
                /* Cluster size is indexed with cluster number */
                clust_size[i]  = 1;
            }

            /* Loop over atoms */
            for (i = 0; (i < nindex); i++)
            {
                ai = index[i];
                ci = clust_index[i];

                /* Loop over atoms (only half a matrix) */
                for (j = i+1; (j < nindex); j++)
                {
                    cj = clust_index[j];

                    /* If they are not in the same cluster already */
                    if (ci != cj)
                    {
                        aj = index[j];

                        /* Compute distance */
                        if (bMol)
                        {
                            bSame = FALSE;
                            for (ii = mols->index[ai]; !bSame && (ii < mols->index[ai+1]); ii++)
                            {
                                for (jj = mols->index[aj]; !bSame && (jj < mols->index[aj+1]); jj++)
                                {
                                    if (bPBC)
                                    {
                                        pbc_dx(&pbc, x[ii], x[jj], dx);
                                    }
                                    else
                                    {
                                        rvec_sub(x[ii], x[jj], dx);
                                    }
                                    dx2   = iprod(dx, dx);
                                    bSame = (dx2 < cut2);
                                }
                            }
                        }
                        else
                        {
                            if (bPBC)
                            {
                                pbc_dx(&pbc, x[ai], x[aj], dx);
                            }
                            else
                            {
                                rvec_sub(x[ai], x[aj], dx);
                            }
                            dx2   = iprod(dx, dx);
                            bSame = (dx2 < cut2);
                        }
                        /* If distance less than cut-off */
                        if (bSame)
                        {
                            /* Merge clusters: check for all atoms whether they are in
                             * cluster cj and if so, put them in ci
                             */
                            for (k = 0; (k < nindex); k++)
                            {
                                if (clust_index[k] == cj)
                                {
                                    if (clust_size[cj] <= 0)
                                    {
                                        gmx_fatal(FARGS, "negative cluster size %d for element %d",
                                                  clust_size[cj], cj);
                                    }
                                    clust_size[cj]--;
                                    clust_index[k] = ci;
                                    clust_size[ci]++;
                                }
                            }
                        }
                    }
                }
            }
            n_x++;
            srenew(t_x, n_x);
            t_x[n_x-1] = fr.time*tf;
            srenew(cs_dist, n_x);
            snew(cs_dist[n_x-1], nindex);
            nclust = 0;
            cav    = 0;
            nav    = 0;
            for (i = 0; (i < nindex); i++)
            {
                ci = clust_size[i];
                if (ci > max_clust_size)
                {
                    max_clust_size = ci;
                    max_clust_ind  = i;
                }
                if (ci > 0)
                {
                    nclust++;
                    cs_dist[n_x-1][ci-1] += 1.0;
                    max_size              = max(max_size, ci);
                    if (ci > 1)
                    {
                        cav += ci;
                        nav++;
                    }
                }
            }
            fprintf(fp, "%14.6e  %10d\n", fr.time, nclust);
            if (nav > 0)
            {
                fprintf(gp, "%14.6e  %10.3f\n", fr.time, cav/nav);
            }
            fprintf(hp, "%14.6e  %10d\n", fr.time, max_clust_size);
        }
        /* Analyse velocities, if present */
        if (fr.bV)
        {
            if (!tpr)
            {
                if (bTPRwarn)
                {
                    printf("You need a [TT].tpr[tt] file to analyse temperatures\n");
                    bTPRwarn = FALSE;
                }
            }
            else
            {
                v = fr.v;
                /* Loop over clusters and for each cluster compute 1/2 m v^2 */
                if (max_clust_ind >= 0)
                {
                    ekin = 0;
                    for (i = 0; (i < nindex); i++)
                    {
                        if (clust_index[i] == max_clust_ind)
                        {
                            ai    = index[i];
                            gmx_mtop_atomnr_to_atom(alook, ai, &atom);
                            ekin += 0.5*atom->m*iprod(v[ai], v[ai]);
                        }
                    }
                    temp = (ekin*2.0)/(3.0*tfac*max_clust_size*BOLTZ);
                    fprintf(tp, "%10.3f  %10.3f\n", fr.time, temp);
                }
            }
        }
        nframe++;
    }
    while (read_next_frame(oenv, status, &fr));
    close_trx(status);
    ffclose(fp);
    ffclose(gp);
    ffclose(hp);
    ffclose(tp);

    gmx_mtop_atomlookup_destroy(alook);

    if (max_clust_ind >= 0)
    {
        fp = ffopen(mcn, "w");
        fprintf(fp, "[ max_clust ]\n");
        for (i = 0; (i < nindex); i++)
        {
            if (clust_index[i] == max_clust_ind)
            {
                if (bMol)
                {
                    for (j = mols->index[i]; (j < mols->index[i+1]); j++)
                    {
                        fprintf(fp, "%d\n", j+1);
                    }
                }
                else
                {
                    fprintf(fp, "%d\n", index[i]+1);
                }
            }
        }
        ffclose(fp);
    }

    /* Print the real distribution cluster-size/numer, averaged over the trajectory. */
    fp     = xvgropen(histo, "Cluster size distribution", "Cluster size", "()", oenv);
    nhisto = 0;
    fprintf(fp, "%5d  %8.3f\n", 0, 0.0);
    for (j = 0; (j < max_size); j++)
    {
        real nelem = 0;
        for (i = 0; (i < n_x); i++)
        {
            nelem += cs_dist[i][j];
        }
        fprintf(fp, "%5d  %8.3f\n", j+1, nelem/n_x);
        nhisto += (int)((j+1)*nelem/n_x);
    }
    fprintf(fp, "%5d  %8.3f\n", j+1, 0.0);
    ffclose(fp);

    fprintf(stderr, "Total number of atoms in clusters =  %d\n", nhisto);

    /* Look for the smallest entry that is not zero
     * This will make that zero is white, and not zero is coloured.
     */
    cmid = 100.0;
    cmax = 0.0;
    for (i = 0; (i < n_x); i++)
    {
        for (j = 0; (j < max_size); j++)
        {
            if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid))
            {
                cmid = cs_dist[i][j];
            }
            cmax = max(cs_dist[i][j], cmax);
        }
    }
    fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size);
    cmid = 1;
    fp   = ffopen(xpm, "w");
    write_xpm3(fp, 0, "Cluster size distribution", "# clusters", timebuf, "Size",
               n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax,
               rlo, rmid, rhi, &nlevels);
    ffclose(fp);
    cmid = 100.0;
    cmax = 0.0;
    for (i = 0; (i < n_x); i++)
    {
        for (j = 0; (j < max_size); j++)
        {
            cs_dist[i][j] *= (j+1);
            if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid))
            {
                cmid = cs_dist[i][j];
            }
            cmax = max(cs_dist[i][j], cmax);
        }
    }
    fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size);
    fp = ffopen(xpmw, "w");
    write_xpm3(fp, 0, "Weighted cluster size distribution", "Fraction", timebuf,
               "Size", n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax,
               rlo, rmid, rhi, &nlevels);
    ffclose(fp);

    sfree(clust_index);
    sfree(clust_size);
    sfree(index);
}
Ejemplo n.º 3
0
int gmx_g_angle(int argc, char *argv[])
{
    static const char *desc[] = {
        "[THISMODULE] 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, [THISMODULE] 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 [gmx-covar].[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               dt;
    int                isize;
    atom_id           *index;
    char              *grpname;
    real               maxang, S2, norm_fac, maxstat;
    unsigned long      mode;
    int                nframes, maxangstat, mult, *angstat;
    int                i, j, nangles, first, last;
    gmx_bool           bAver, bRb, bPeriodic,
                       bFrac,          /* calculate fraction too?  */
                       bTrans,         /* worry about transtions too? */
                       bCorr;          /* correlation function ? */
    real         aver, aver2, aversig; /* fraction trans dihedrals */
    double       tfrac = 0;
    char         title[256];
    real       **dih = NULL;      /* mega array with all dih. angles at all times*/
    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);
    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs,
                           &oenv))
    {
        return 0;
    }

    mult   = 4;
    maxang = 360.0;
    bRb    = FALSE;

    GMX_RELEASE_ASSERT(opt[0] != NULL, "Internal option inconsistency; opt[0]==NULL after processing");

    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 trr dump");
        }
        else
        {
            please_cite(stdout, "Mu2005a");
        }
    }

    /* Calculate bin size */
    maxangstat = static_cast<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", std::atan2(std::sin(dd), std::cos(dd))*RAD2DEG);
                    }
                    else
                    {
                        fprintf(out, "  %8.3f", dih[j][i]*RAD2DEG);
                    }
                }
            }
            fprintf(out, "\n");
        }
        xvgrclose(out);
    }
    if (opt2bSet("-or", NFILE, fnm))
    {
        dump_dih_trr(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];
        }
        xvgrclose(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   /= nframes;
    aver2  /= nframes;
    aversig = std::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 = std::max(maxstat, angstat[i]*norm_fac);
        }
        if (output_env_get_print_xvgr_codes(oenv))
        {
            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);
    }

    xvgrclose(out);

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

    return 0;
}
Ejemplo n.º 4
0
int gmx_potential(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] computes the electrostatical potential across the box. The potential is",
        "calculated by first summing the charges per slice and then integrating",
        "twice of this charge distribution. Periodic boundaries are not taken",
        "into account. Reference of potential is taken to be the left side of",
        "the box. It is also possible to calculate the potential in spherical",
        "coordinates as function of r by calculating a charge distribution in",
        "spherical slices and twice integrating them. epsilon_r is taken as 1,",
        "but 2 is more appropriate in many cases."
    };
    gmx_output_env_t  *oenv;
    static int         axis       = 2;       /* normal to memb. default z  */
    static const char *axtitle    = "Z";
    static int         nslices    = 10;      /* nr of slices defined       */
    static int         ngrps      = 1;
    static gmx_bool    bSpherical = FALSE;   /* default is bilayer types   */
    static real        fudge_z    = 0;       /* translate coordinates      */
    static gmx_bool    bCorrect   = 0;
    t_pargs            pa []      = {
        { "-d",   FALSE, etSTR, {&axtitle},
          "Take the normal on the membrane in direction X, Y or Z." },
        { "-sl",  FALSE, etINT, {&nslices},
          "Calculate potential as function of boxlength, dividing the box"
          " in this number of slices." },
        { "-cb",  FALSE, etINT, {&cb},
          "Discard this number of  first slices of box for integration" },
        { "-ce",  FALSE, etINT, {&ce},
          "Discard this number of last slices of box for integration" },
        { "-tz",  FALSE, etREAL, {&fudge_z},
          "Translate all coordinates by this distance in the direction of the box" },
        { "-spherical", FALSE, etBOOL, {&bSpherical},
          "Calculate spherical thingie" },
        { "-ng",       FALSE, etINT, {&ngrps},
          "Number of groups to consider" },
        { "-correct",  FALSE, etBOOL, {&bCorrect},
          "Assume net zero charge of groups to improve accuracy" }
    };
    const char        *bugs[] = {
        "Discarding slices for integration should not be necessary."
    };

    double           **potential,              /* potential per slice        */
    **charge,                                  /* total charge per slice     */
    **field,                                   /* field per slice            */
                       slWidth;                /* width of one slice         */
    char      **grpname;                       /* groupnames                 */
    int        *ngx;                           /* sizes of groups            */
    t_topology *top;                           /* topology        */
    int         ePBC;
    int       **index;                         /* indices for all groups     */
    t_filenm    fnm[] = {                      /* files for g_order       */
        { efTRX, "-f", NULL,  ffREAD },        /* trajectory file             */
        { efNDX, NULL, NULL,  ffREAD },        /* index file          */
        { efTPR, NULL, NULL,  ffREAD },        /* topology file               */
        { efXVG, "-o", "potential", ffWRITE }, /* xvgr output file    */
        { efXVG, "-oc", "charge", ffWRITE },   /* xvgr output file    */
        { efXVG, "-of", "field", ffWRITE },    /* xvgr output file    */
    };

#define NFILE asize(fnm)

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

    /* Calculate axis */
    axis = toupper(axtitle[0]) - 'X';

    top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */

    snew(grpname, ngrps);
    snew(index, ngrps);
    snew(ngx, ngrps);

    rd_index(ftp2fn(efNDX, NFILE, fnm), ngrps, ngx, index, grpname);


    calc_potential(ftp2fn(efTRX, NFILE, fnm), index, ngx,
                   &potential, &charge, &field,
                   &nslices, top, ePBC, axis, ngrps, &slWidth, fudge_z,
                   bSpherical, bCorrect, oenv);

    plot_potential(potential, charge, field, opt2fn("-o", NFILE, fnm),
                   opt2fn("-oc", NFILE, fnm), opt2fn("-of", NFILE, fnm),
                   nslices, ngrps, (const char**)grpname, slWidth, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);  /* view xvgr file */
    do_view(oenv, opt2fn("-oc", NFILE, fnm), NULL); /* view xvgr file */
    do_view(oenv, opt2fn("-of", NFILE, fnm), NULL); /* view xvgr file */

    return 0;
}
Ejemplo n.º 5
0
int gmx_rotacf(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_rotacf[tt] calculates the rotational correlation function",
        "for molecules. Atom triplets (i,j,k) must be given in the index",
        "file, defining two vectors ij and jk. The rotational ACF",
        "is calculated as the autocorrelation function of the vector",
        "n = ij x jk, i.e. the cross product of the two vectors.",
        "Since three atoms span a plane, the order of the three atoms",
        "does not matter. Optionally, by invoking the [TT]-d[tt] switch, you can",
        "calculate the rotational correlation function for linear molecules",
        "by specifying atom pairs (i,j) in the index file.",
        "[PAR]",
        "EXAMPLES[PAR]",
        "[TT]g_rotacf -P 1 -nparm 2 -fft -n index -o rotacf-x-P1",
        "-fa expfit-x-P1 -beginfit 2.5 -endfit 20.0[tt][PAR]",
        "This will calculate the rotational correlation function using a first",
        "order Legendre polynomial of the angle of a vector defined by the index",
        "file. The correlation function will be fitted from 2.5 ps until 20.0 ps",
        "to a two-parameter exponential."
    };
    static gmx_bool bVec    = FALSE, bAver = TRUE;

    t_pargs         pa[] = {
        { "-d",   FALSE, etBOOL, {&bVec},
          "Use index doublets (vectors) for correlation function instead of triplets (planes)" },
        { "-aver", FALSE, etBOOL, {&bAver},
          "Average over molecules" }
    };

    t_trxstatus    *status;
    int             isize;
    atom_id        *index;
    char           *grpname;
    rvec           *x, *x_s;
    matrix          box;
    real          **c1;
    rvec            xij, xjk, n;
    int             i, m, teller, n_alloc, natoms, nvec, ai, aj, ak;
    unsigned long   mode;
    real            t, t0, t1, dt;
    gmx_rmpbc_t     gpbc = NULL;
    t_topology     *top;
    int             ePBC;
    t_filenm        fnm[] = {
        { efTRX, "-f", NULL,  ffREAD  },
        { efTPX, NULL, NULL,  ffREAD },
        { efNDX, NULL, NULL,  ffREAD  },
        { efXVG, "-o", "rotacf",  ffWRITE }
    };
#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, 0, NULL, &oenv);

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);

    if (bVec)
    {
        nvec = isize/2;
    }
    else
    {
        nvec = isize/3;
    }

    if (((isize % 3) != 0) && !bVec)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of 3, "
                  "these can not be atom triplets\n");
    }
    if (((isize % 2) != 0) && bVec)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of 2, "
                  "these can not be atom doublets\n");
    }

    top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC);

    snew(c1, nvec);
    for (i = 0; (i < nvec); i++)
    {
        c1[i] = NULL;
    }
    n_alloc = 0;

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

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

    /* Start the loop over frames */
    t1      = t0 = t;
    teller  = 0;
    do
    {
        if (teller >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; (i < nvec); i++)
            {
                srenew(c1[i], DIM*n_alloc);
            }
        }
        t1 = t;

        /* Remove periodicity */
        gmx_rmpbc_copy(gpbc, natoms, box, x, x_s);

        /* Compute crossproducts for all vectors, if triplets.
         * else, just get the vectors in case of doublets.
         */
        if (bVec == FALSE)
        {
            for (i = 0; (i < nvec); i++)
            {
                ai = index[3*i];
                aj = index[3*i+1];
                ak = index[3*i+2];
                rvec_sub(x_s[ai], x_s[aj], xij);
                rvec_sub(x_s[aj], x_s[ak], xjk);
                cprod(xij, xjk, n);
                for (m = 0; (m < DIM); m++)
                {
                    c1[i][DIM*teller+m] = n[m];
                }
            }
        }
        else
        {
            for (i = 0; (i < nvec); i++)
            {
                ai = index[2*i];
                aj = index[2*i+1];
                rvec_sub(x_s[ai], x_s[aj], n);
                for (m = 0; (m < DIM); m++)
                {
                    c1[i][DIM*teller+m] = n[m];
                }
            }
        }
        /* Increment loop counter */
        teller++;
    }
    while (read_next_x(oenv, status, &t, natoms, x, box));
    close_trj(status);
    fprintf(stderr, "\nDone with trajectory\n");

    gmx_rmpbc_done(gpbc);


    /* Autocorrelation function */
    if (teller < 2)
    {
        fprintf(stderr, "Not enough frames for correlation function\n");
    }
    else
    {
        dt = (t1 - t0)/(teller-1);

        mode = eacVector;

        do_autocorr(ftp2fn(efXVG, NFILE, fnm), oenv, "Rotational Correlation Function",
                    teller, nvec, c1, dt, mode, bAver);
    }

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

    thanx(stderr);

    return 0;
}
Ejemplo n.º 6
0
extern int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
                                    const char* fnXVG, const char *fnTRX,
                                    const char* fnDAT,
                                    real start_q, real end_q,
                                    real energy, int ng, const output_env_t oenv)
{
    int                     i, *isize, flags = TRX_READ_X, **index_atp;
    t_trxstatus            *status;
    char                  **grpname, title[STRLEN];
    atom_id               **index;
    t_topology              top;
    int                     ePBC;
    t_trxframe              fr;
    reduced_atom_t        **red;
    structure_factor       *sf;
    rvec                   *xtop;
    real                  **sf_table;
    matrix                  box;
    real                    r_tmp;

    gmx_structurefactors_t *gmx_sf;
    real                   *a, *b, c;

    snew(a, 4);
    snew(b, 4);


    gmx_sf = gmx_structurefactors_init(fnDAT);

    gmx_structurefactors_get_sf(gmx_sf, 0, a, b, &c);

    snew (sf, 1);
    sf->energy = energy;

    /* Read the topology informations */
    read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
    sfree (xtop);

    /* groups stuff... */
    snew (isize, ng);
    snew (index, ng);
    snew (grpname, ng);

    fprintf (stderr, "\nSelect %d group%s\n", ng,
             ng == 1 ? "" : "s");
    if (fnTPS)
    {
        get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
    }
    else
    {
        rd_index (fnNDX, ng, isize, index, grpname);
    }

    /* The first time we read data is a little special */
    read_first_frame (oenv, &status, fnTRX, &fr, flags);

    sf->total_n_atoms = fr.natoms;

    snew (red, ng);
    snew (index_atp, ng);

    r_tmp = std::max(box[XX][XX], box[YY][YY]);
    r_tmp = std::max(box[ZZ][ZZ], r_tmp);

    sf->ref_k = (2.0 * M_PI) / (r_tmp);
    /* ref_k will be the reference momentum unit */
    sf->n_angles = static_cast<int>(end_q / sf->ref_k + 0.5);

    snew (sf->F, ng);
    for (i = 0; i < ng; i++)
    {
        snew (sf->F[i], sf->n_angles);
    }
    for (i = 0; i < ng; i++)
    {
        snew (red[i], isize[i]);
        rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE, gmx_sf);
        index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
    }

    sf_table = compute_scattering_factor_table (gmx_sf, (structure_factor_t *)sf);


    /* This is the main loop over frames */

    do
    {
        sf->nSteps++;
        for (i = 0; i < ng; i++)
        {
            rearrange_atoms (red[i], &fr, index[i], isize[i], &top, FALSE, gmx_sf);

            compute_structure_factor ((structure_factor_t *)sf, box, red[i], isize[i],
                                      start_q, end_q, i, sf_table);
        }
    }

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

    save_data ((structure_factor_t *)sf, fnXVG, ng, start_q, end_q, oenv);


    sfree(a);
    sfree(b);

    gmx_structurefactors_done(gmx_sf);

    return 0;
}
Ejemplo n.º 7
0
int gmx_velacc(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_velacc[tt] computes the velocity autocorrelation function.",
        "When the [TT]-m[tt] option is used, the momentum autocorrelation",
        "function is calculated.[PAR]",
        "With option [TT]-mol[tt] the velocity autocorrelation function of",
        "molecules is calculated. In this case the index group should consist",
        "of molecule numbers instead of atom numbers.[PAR]",
        "Be sure that your trajectory contains frames with velocity information",
        "(i.e. [TT]nstvout[tt] was set in your original [TT].mdp[tt] file),",
        "and that the time interval between data collection points is",
        "much shorter than the time scale of the autocorrelation."
    };

    static gmx_bool bMass = FALSE, bMol = FALSE, bRecip = TRUE;
    t_pargs         pa[]  = {
        { "-m", FALSE, etBOOL, {&bMass},
          "Calculate the momentum autocorrelation function" },
        { "-recip", FALSE, etBOOL, {&bRecip},
          "Use cm^-1 on X-axis instead of 1/ps for spectra." },
        { "-mol", FALSE, etBOOL, {&bMol},
          "Calculate the velocity acf of molecules" }
    };

    t_topology      top;
    int             ePBC = -1;
    t_trxframe      fr;
    matrix          box;
    gmx_bool        bTPS = FALSE, bTop = FALSE;
    int             gnx;
    atom_id        *index;
    char           *grpname;
    char            title[256];
    /* t0, t1 are the beginning and end time respectively.
     * dt is the time step, mass is temp variable for atomic mass.
     */
    real              t0, t1, dt, mass;
    t_trxstatus      *status;
    int               counter, n_alloc, i, j, counter_dim, k, l;
    rvec              mv_mol;
    /* Array for the correlation function */
    real            **c1;
    real             *normm = NULL;
    output_env_t      oenv;

#define NHISTO 360

    t_filenm  fnm[] = {
        { efTRN, "-f",    NULL,   ffREAD  },
        { efTPS, NULL,    NULL,   ffOPTRD },
        { efNDX, NULL,    NULL,   ffOPTRD },
        { efXVG, "-o",    "vac",  ffWRITE },
        { efXVG, "-os",   "spectrum", ffOPTWR }
    };
#define NFILE asize(fnm)
    int       npargs;
    t_pargs  *ppa;

    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, 0, NULL, &oenv);

    if (bMol || bMass)
    {
        bTPS = ftp2bSet(efTPS, NFILE, fnm) || !ftp2bSet(efNDX, NFILE, fnm);
    }

    if (bTPS)
    {
        bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, NULL, NULL, box,
                             TRUE);
        get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
    }
    else
    {
        rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
    }

    if (bMol)
    {
        if (!bTop)
        {
            gmx_fatal(FARGS, "Need a topology to determine the molecules");
        }
        snew(normm, top.atoms.nr);
        precalc(top, normm);
        index_atom2mol(&gnx, index, &top.mols);
    }

    /* Correlation stuff */
    snew(c1, gnx);
    for (i = 0; (i < gnx); i++)
    {
        c1[i] = NULL;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr, TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    counter = 0;
    do
    {
        if (counter >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < gnx; i++)
            {
                srenew(c1[i], DIM*n_alloc);
            }
        }
        counter_dim = DIM*counter;
        if (bMol)
        {
            for (i = 0; i < gnx; i++)
            {
                clear_rvec(mv_mol);
                k = top.mols.index[index[i]];
                l = top.mols.index[index[i]+1];
                for (j = k; j < l; j++)
                {
                    if (bMass)
                    {
                        mass = top.atoms.atom[j].m;
                    }
                    else
                    {
                        mass = normm[j];
                    }
                    mv_mol[XX] += mass*fr.v[j][XX];
                    mv_mol[YY] += mass*fr.v[j][YY];
                    mv_mol[ZZ] += mass*fr.v[j][ZZ];
                }
                c1[i][counter_dim+XX] = mv_mol[XX];
                c1[i][counter_dim+YY] = mv_mol[YY];
                c1[i][counter_dim+ZZ] = mv_mol[ZZ];
            }
        }
        else
        {
            for (i = 0; i < gnx; i++)
            {
                if (bMass)
                {
                    mass = top.atoms.atom[index[i]].m;
                }
                else
                {
                    mass = 1;
                }
                c1[i][counter_dim+XX] = mass*fr.v[index[i]][XX];
                c1[i][counter_dim+YY] = mass*fr.v[index[i]][YY];
                c1[i][counter_dim+ZZ] = mass*fr.v[index[i]][ZZ];
            }
        }

        t1 = fr.time;

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

    close_trj(status);

    if (counter >= 4)
    {
        /* Compute time step between frames */
        dt = (t1-t0)/(counter-1);
        do_autocorr(opt2fn("-o", NFILE, fnm), oenv,
                    bMass ?
                    "Momentum Autocorrelation Function" :
                    "Velocity Autocorrelation Function",
                    counter, gnx, c1, dt, eacVector, TRUE);

        do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");

        if (opt2bSet("-os", NFILE, fnm))
        {
            calc_spectrum(counter/2, (real *) (c1[0]), (t1-t0)/2, opt2fn("-os", NFILE, fnm),
                          oenv, bRecip);
            do_view(oenv, opt2fn("-os", NFILE, fnm), "-nxy");
        }
    }
    else
    {
        fprintf(stderr, "Not enough frames in trajectory - no output generated.\n");
    }

    thanx(stderr);

    return 0;
}
Ejemplo n.º 8
0
int gmx_h2order(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] computes the orientation of water molecules with respect to the normal",
        "of the box. The program determines the average cosine of the angle",
        "between the dipole moment of water and an axis of the box. The box is",
        "divided in slices and the average orientation per slice is printed.",
        "Each water molecule is assigned to a slice, per time frame, based on the",
        "position of the oxygen. When [TT]-nm[tt] is used, the angle between the water",
        "dipole and the axis from the center of mass to the oxygen is calculated",
        "instead of the angle between the dipole and a box axis."
    };
    static int         axis    = 2;           /* normal to memb. default z  */
    static const char *axtitle = "Z";
    static int         nslices = 0;           /* nr of slices defined       */
    t_pargs            pa[]    = {
        { "-d",   FALSE, etSTR, {&axtitle},
          "Take the normal on the membrane in direction X, Y or Z." },
        { "-sl",  FALSE, etINT, {&nslices},
          "Calculate order parameter as function of boxlength, dividing the box"
          " in this number of slices."}
    };
    const char        *bugs[] = {
        "The program assigns whole water molecules to a slice, based on the first "
        "atom of three in the index file group. It assumes an order O,H,H. "
        "Name is not important, but the order is. If this demand is not met, "
        "assigning molecules to slices is different."
    };

    output_env_t       oenv;
    real              *slOrder,             /* av. cosine, per slice      */
                       slWidth = 0.0;       /* width of a slice           */
    rvec              *slDipole;
    char              *grpname,             /* groupnames                 */
    *micname;
    int                ngx,                 /* nr. of atomsin sol group   */
                       nmic = 0;            /* nr. of atoms in micelle    */
    t_topology        *top;                 /* topology           */
    int                ePBC;
    atom_id           *index,               /* indices for solvent group  */
    *micelle                  = NULL;
    gmx_bool           bMicel =  FALSE;     /* think we're a micel        */
    t_filenm           fnm[]  = {           /* files for g_order      */
        { efTRX, "-f", NULL,  ffREAD },     /* trajectory file            */
        { efNDX, NULL, NULL,  ffREAD },     /* index file         */
        { efNDX, "-nm", NULL, ffOPTRD },    /* index with micelle atoms   */
        { efTPX, NULL, NULL,  ffREAD },     /* topology file              */
        { efXVG, "-o",  "order", ffWRITE }, /* xvgr output file       */
    };

#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv,
                           PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE,
                           fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv))
    {
        return 0;
    }
    bMicel = opt2bSet("-nm", NFILE, fnm);

    top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC); /* read topology file */

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &ngx, &index, &grpname);

    if (bMicel)
    {
        rd_index(opt2fn("-nm", NFILE, fnm), 1, &nmic, &micelle, &micname);
    }

    calc_h2order(ftp2fn(efTRX, NFILE, fnm), index, ngx, &slDipole, &slOrder,
                 &slWidth, &nslices, top, ePBC, axis, bMicel, micelle, nmic,
                 oenv);

    h2order_plot(slDipole, slOrder, opt2fn("-o", NFILE, fnm), nslices,
                 slWidth, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); /* view xvgr file */

    return 0;
}
Ejemplo n.º 9
0
int gmx_bond(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_bond[tt] makes a distribution of bond lengths. If all is well a",
        "Gaussian distribution should be made when using a harmonic potential.",
        "Bonds are read from a single group in the index file in order i1-j1",
        "i2-j2 through in-jn.[PAR]",
        "[TT]-tol[tt] gives the half-width of the distribution as a fraction",
        "of the bondlength ([TT]-blen[tt]). That means, for a bond of 0.2",
        "a tol of 0.1 gives a distribution from 0.18 to 0.22.[PAR]",
        "Option [TT]-d[tt] plots all the distances as a function of time.",
        "This requires a structure file for the atom and residue names in",
        "the output. If however the option [TT]-averdist[tt] is given (as well",
        "or separately) the average bond length is plotted instead."
    };
    const char     *bugs[] = {
        "It should be possible to get bond information from the topology."
    };
    static real     blen  = -1.0, tol = 0.1;
    static gmx_bool bAver = TRUE, bAverDist = TRUE;
    t_pargs         pa[]  = {
        { "-blen", FALSE, etREAL, {&blen},
          "Bond length. By default length of first bond" },
        { "-tol",  FALSE, etREAL, {&tol},
          "Half width of distribution as fraction of [TT]-blen[tt]" },
        { "-aver", FALSE, etBOOL, {&bAver},
          "Average bond length distributions" },
        { "-averdist", FALSE, etBOOL, {&bAverDist},
          "Average distances (turns on [TT]-d[tt])" }
    };
    FILE           *fp;
    char           *grpname;
    const char     *fdist;
    int             gnx;
    atom_id        *index;
    char            title[STRLEN];
    t_topology      top;
    int             ePBC = -1;
    rvec           *x;
    matrix          box;
    output_env_t    oenv;

    t_filenm        fnm[] = {
        { efTRX, "-f", NULL, ffREAD  },
        { efNDX, NULL, NULL, ffREAD  },
        { efTPS, NULL, NULL, ffOPTRD },
        { efXVG, "-o", "bonds", ffWRITE },
        { efLOG, NULL, "bonds", ffOPTWR },
        { efXVG, "-d", "distance", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    if (bAverDist)
    {
        fdist = opt2fn("-d", NFILE, fnm);
    }
    else
    {
        fdist = opt2fn_null("-d", NFILE, fnm);
        if (fdist)
        {
            read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x, NULL, box,
                          FALSE);
        }
    }

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
    if (!even(gnx) )
    {
        fprintf(stderr, "WARNING: odd number of atoms (%d) in group!\n", gnx);
    }
    fprintf(stderr, "Will gather information on %d bonds\n", gnx/2);

    if (!bAver)
    {
        fp = ftp2FILE(efLOG, NFILE, fnm, "w");
    }
    else
    {
        fp = NULL;
    }

    do_bonds(fp, ftp2fn(efTRX, NFILE, fnm), opt2fn("-o", NFILE, fnm), fdist, gnx, index,
             blen, tol, bAver, &top, ePBC, bAverDist, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    do_view(oenv, opt2fn_null("-d", NFILE, fnm), "-nxy");

    return 0;
}
Ejemplo n.º 10
0
int gmx_relax(int argc,char *argv[])
{
  const char *desc[] = {
    "g_noe calculates a NOE spectrum"
  };

  int        status;
  t_topology *top;
  int        i,j,k,natoms,nprot,*prot_ind;
  int        ifit;
  char       *gn_fit;
  atom_id    *ind_fit,*all_at;
  real       *w_rls;
  rvec       *xp;
  t_pair     *pair;
  matrix     box;
  int        step,nre;
  real       t,lambda;
  real       *shifts=NULL;
  t_filenm   fnm[] = {
    { efTRX, "-f", NULL,     ffREAD },
    { efTPX, "-s", NULL,     ffREAD },
    { efNDX, NULL, NULL,     ffREAD },
    { efDAT, "-d", "shifts", ffREAD },
    { efOUT, "-o","spec",    ffWRITE },
    { efXVG, "-corr", "rij-corr", ffWRITE },
    { efXVG, "-noe", "noesy", ffWRITE }
  };
#define NFILE asize(fnm)
  static real taum      = 0.0, maxdist = 0.6;
  static int  nlevels   = 15;
  static int  nrestart  = 1;
  static int  maxframes = 100;
  static bool bFFT      = TRUE,bFit = TRUE, bVerbose = TRUE;
  t_pargs pa[] = {
    { "-taum",     FALSE, etREAL, &taum, 
      "Rotational correlation time for your molecule. It is obligatory to pass this option" },
    { "-maxdist",  FALSE, etREAL, &maxdist,
      "Maximum distance to be plotted" },
    { "-nlevels",  FALSE, etINT,  &nlevels,
      "Number of levels for plotting" },
    { "-nframes", FALSE, etINT,  &maxframes,
      "Number of frames in your trajectory. Will stop analysis after this" },
    { "-fft",      FALSE, etBOOL, &bFFT,
      "Use FFT for correlation function" },
    { "-nrestart", FALSE, etINT,  &nrestart,
      "Number of frames between starting point for computation of ACF without FFT" },
    { "-fit",      FALSE, etBOOL, &bFit,
      "Do an optimal superposition on reference structure in tpx file" },
    { "-v",        FALSE, etBOOL, &bVerbose,
      "Tell you what I am about to do" }
  };

  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL);
  if (taum <= 0)
    gmx_fatal(FARGS,"Please give me a sensible taum!\n");
  if (nlevels > 50) {
    nlevels = 50;
    fprintf(stderr,"Warning: too many levels, setting to %d\n",nlevels);
  }
  		    
  top    = read_top(ftp2fn(efTPX,NFILE,fnm));
  natoms = top->atoms.nr;
  snew(xp,natoms);
  read_tpx(ftp2fn(efTPX,NFILE,fnm),&step,&t,&lambda,NULL,box,
	   &natoms,xp,NULL,NULL,NULL);

  /* Determine the number of protons, and their index numbers 
   * by checking the mass 
   */
  nprot  = 0;
  snew(prot_ind,natoms);
  for(i=0; (i<natoms); i++)
    if (top->atoms.atom[i].m  < 2) {
      prot_ind[nprot++] = i;
    }
  fprintf(stderr,"There %d protons in your topology\n",nprot);
  snew(pair,(nprot*(nprot-1)/2));
  for(i=k=0; (i<nprot); i++) {
    for(j=i+1; (j<nprot); j++,k++) {
      pair[k].ai = prot_ind[i];
      pair[k].aj = prot_ind[j];
    }
  }
  sfree(prot_ind);
  
  fprintf(stderr,"Select group for root least squares fit\n");
  rd_index(ftp2fn(efNDX,NFILE,fnm),1,&ifit,&ind_fit,&gn_fit);
  
  if (ifit < 3) 
    gmx_fatal(FARGS,"Need >= 3 points to fit!\n");

  /* Make an array with weights for fitting */
  snew(w_rls,natoms);
  for(i=0; (i<ifit); i++)
    w_rls[ind_fit[i]]=top->atoms.atom[ind_fit[i]].m;
    
  /* Prepare reference frame */
  snew(all_at,natoms);
  for(j=0; (j<natoms); j++)
    all_at[j]=j;
  rm_pbc(&(top->idef),natoms,box,xp,xp);
  reset_x(ifit,ind_fit,natoms,all_at,xp,w_rls);
  sfree(all_at);
  
  spectrum(bVerbose,
	   ftp2fn(efTRX,NFILE,fnm),ftp2fn(efDAT,NFILE,fnm),
	   ftp2bSet(efDAT,NFILE,fnm),opt2fn("-corr",NFILE,fnm),
	   opt2fn("-noe",NFILE,fnm),
	   maxframes,bFFT,bFit,nrestart,
	   k,pair,natoms,shifts,
	   taum,maxdist,w_rls,xp,&(top->idef));
  
  thanx(stderr);
  
  return 0;
}
Ejemplo n.º 11
0
static void do_sdf(char *fnNDX,char *fnTPS,char *fnTRX, char *fnSDF, 
                   char *fnREF, bool bRef, rvec cutoff, real binwidth,
                   int mode, rvec triangle, rvec dtri)
{
  FILE       *fp;
  int        status;
  int        ng,natoms,i,j,k,l,X,Y,Z,lc,dest;
  ivec       nbin;
  int        ***count;
  /* real       ***sdf; */
  real       sdf,min_sdf=1e10,max_sdf=0;
  char       **grpname;
  int        *isize;
  int        isize_cg=0;
  int        isize_ref=3;
  int        ref_resnr[3];
  int        nrefmol=0,refc=0;
  atom_id    **index;
  atom_id    *index_cg=NULL;
  atom_id    *index_ref=NULL;
  real       t,boxmin,hbox,normfac;
  real       invbinw;
  rvec       tri_upper,tri_lower;
  rvec       *x,xcog,dx,*x_i1,xi,*x_refmol;
  matrix     box;
  matrix     rot; /* rotation matrix := unit vectors for the molecule frame */
  rvec       k_mol,i1_mol,i2_mol,dx_mol;
  real       delta;
  atom_id    ix,jx;
  t_topology top;
  int        ePBC=-1;
  t_pbc      pbc;
  bool       bTop=FALSE,bRefDone=FALSE,bInGroup=FALSE;
  char       title[STRLEN];


  /* Read Topology */
  if (fnTPS) {
    bTop=read_tps_conf(fnTPS,title,&top,&ePBC,&x,NULL,box,TRUE);
  }
  


  if ( !bTop ) {
    fprintf(stderr,"\nNeed tpr-file to make a reference structure.\n");
    fprintf(stderr,"Option -r will be ignored!\n");
    bRef = FALSE;
  }


  /* Allocate memory for 4 groups, 3 dummy groups and a group for the ref 
structure if needed */
  ng = 4;
  snew(grpname,ng);
  /* the dummy groups are used to dynamically store triples of atoms */
  /* for molecular coordinate systems */
  if ( bRef )
    {
      snew(isize,ng+4);
      snew(index,ng+4);
    }
  else 
    {
      snew(isize,ng+3);
      snew(index,ng+3);
    }


  /* Read the index groups */
  fprintf(stderr,"\nSelect the 3 reference groups and the SDF group:\n");
  if (fnTPS)
    get_index(&top.atoms,fnNDX,ng,isize,index,grpname);
  else
    rd_index(fnNDX,ng,isize,index,grpname);


  isize[NDX_REF1]=isize[G_REF1];
  for (i=NDX_REF1; i<=NDX_REF3; i++)
    snew(index[i],isize[NDX_REF1]);


  /* Read first frame and check it */
  natoms=read_first_x(&status,fnTRX,&t,&x,box);
  if ( !natoms )
    gmx_fatal(FARGS,"Could not read coordinates from statusfile!\n");


  /* check with topology */
  if (fnTPS)
    if ( natoms > top.atoms.nr )
      gmx_fatal(FARGS,"Trajectory (%d atoms) does not match topology (%d atoms)!\n",
                  natoms,top.atoms.nr);


  /* check with index groups */
  for (i=0; i<ng; i++)
    for (j=0; j<isize[i]; j++)
      if ( index[i][j] >= natoms )
        gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) larger "
                    "than number of atoms in trajectory (%d atoms)!\n",
                    index[i][j],grpname[i],isize[i],natoms);


  /* check reference groups */
  if ( mode == 1 )
    {
      if ( isize[G_REF1] != isize[G_REF2] || isize[G_REF1] != isize[G_REF3] || 
           isize[G_REF2] != isize[G_REF3] )
        gmx_fatal(FARGS,"For single particle SDF, all reference groups"
                    "must have the same size.\n");


      /* for single particle SDF dynamic triples are not needed */
      /* so we build them right here */


      /* copy all triples from G_REFx to NDX_REFx */    
      for (i=0; i<isize[G_REF1]; i++)
        {
          /* check if all three atoms come from the same molecule */
          for (j=G_REF1; j<=G_REF3; j++)
            ref_resnr[j] = top.atoms.atom[index[j][i]].resnr;


          if ( ref_resnr[G_REF1] != ref_resnr[G_REF2] ||
                 ref_resnr[G_REF2] != ref_resnr[G_REF3] ||
                 ref_resnr[G_REF3] != ref_resnr[G_REF1] )
              {
                fprintf(stderr,"\nWarning: reference triple (%d) will be skipped.\n",i);
                fprintf(stderr,  "         resnr[1]: %d, resnr[2]: %d, resnr[3]: %d\n",
                        ref_resnr[G_REF1],ref_resnr[G_REF2], ref_resnr[G_REF3]);
                isize[NDX_REF1]--;
                for (j=NDX_REF1; j<=NDX_REF3; j++)
                  srenew(index[j],isize[NDX_REF1]);
                continue;
              }
          else
            /* check if all entries are unique*/
            if ( index[G_REF1][i] == index[G_REF2][i] ||
                 index[G_REF2][i] == index[G_REF3][i] ||
                 index[G_REF3][i] == index[G_REF1][i] )
              {
                fprintf(stderr,"Warning: reference triple (%d) will be skipped.\n",i);
                fprintf(stderr,  "         index[1]: %d, index[2]: %d, index[3]: %d\n",
                        index[G_REF1][i],index[G_REF2][i],index[G_REF3][i]);    
                isize[NDX_REF1]--;
                for (j=NDX_REF1; j<=NDX_REF3; j++)
                  srenew(index[j],isize[NDX_REF1]);
                continue;
              }
            else /* everythings fine, copy that one */
              for (j=G_REF1; j<=G_REF3; j++)
                index[j+4][i] = index[j][i];
        }
    }
  else if ( mode == 2 )
    {
      if ( isize[G_REF1] != isize[G_REF2] )
        gmx_fatal(FARGS,"For two particle SDF, reference groups 1 and 2"
                    "must have the same size.\n");


      for (i=0; i<isize[G_REF1]; i++)
        {
          /* check consistency for atoms 1 and 2 */
          for (j=G_REF1; j<=G_REF2; j++)
            ref_resnr[j] = top.atoms.atom[index[j][i]].resnr;


          if ( ref_resnr[G_REF1] != ref_resnr[G_REF2] ||
               index[G_REF1][i] == index[G_REF2][i] )
            {
              if ( ref_resnr[G_REF1] != ref_resnr[G_REF2] )
                {
                  fprintf(stderr,"\nWarning: bond (%d) not from one molecule."
                          "Will not be used for SDF.\n",i);
                  fprintf(stderr,  "         resnr[1]: %d, resnr[2]: %d\n",
                          ref_resnr[G_REF1],ref_resnr[G_REF2]);
                }
              else
                {
                  fprintf(stderr,"\nWarning: atom1 and atom2 are identical."
                          "Bond (%d) will not be used for SDF.\n",i);
                  fprintf(stderr,  "         index[1]: %d, index[2]: %d\n",
                          index[G_REF1][i],index[G_REF2][i]);
                }
              for (j=NDX_REF1; j<=NDX_REF2; j++)
                {
                  for (k=i; k<isize[G_REF1]-1; k++)
                    index[j][k]=index[j][k+1];
                  isize[j]--;
                  srenew(index[j],isize[j]);
                }
            }
        }
    }


  /* Read Atoms for refmol group */
  if ( bRef )
    {
      snew(index[G_REFMOL],1);


      for (i=G_REF1; i<=G_REF3; i++)
        ref_resnr[i] = top.atoms.atom[index[i][0]].resnr;


      for (i=0; i<natoms; i++)
        {
          if (  ref_resnr[G_REF1] == top.atoms.atom[i].resnr ||
                ref_resnr[G_REF2] == top.atoms.atom[i].resnr ||
                ref_resnr[G_REF3] == top.atoms.atom[i].resnr )
            nrefmol++;
        }
      srenew(index[G_REFMOL],nrefmol);
      isize[G_REFMOL] = nrefmol;
      nrefmol = 0;


      for (i=0; i<natoms; i++)
        {
          if (  ref_resnr[G_REF1] == top.atoms.atom[i].resnr ||
                ref_resnr[G_REF2] == top.atoms.atom[i].resnr ||
                ref_resnr[G_REF3] == top.atoms.atom[i].resnr )
            {
              index[G_REFMOL][nrefmol] = i;
              nrefmol++;
            }
        }
    }


  /* initialize some stuff */
  boxmin = min( norm(box[XX]), min( norm(box[YY]), norm(box[ZZ]) ) );
  hbox   = boxmin / 2.0;


  for (i=0; i<DIM; i++)
    {
      cutoff[i] = cutoff[i] / 2;
      nbin[i]   = (int)(2 * cutoff[i] / binwidth) + 1;
      invbinw = 1.0 / binwidth;
      tri_upper[i] = triangle[i] + dtri[i];
      tri_upper[i] = sqr(tri_upper[i]);
      tri_lower[i] = triangle[i] - dtri[i];
      tri_lower[i] = sqr(tri_lower[i]);
    }


  /* Allocate the array's for sdf */
  snew(count,nbin[0]+1);
  for(i=0; i<nbin[0]+1; i++) 
    {
      snew(count[i],nbin[1]+1);
      for (j=0; j<nbin[1]+1; j++) 
        snew(count[i][j],nbin[2]+1);
    }


  /* Allocate space for the coordinates */
  snew(x_i1,isize[G_SDF]);
  snew(x_refmol,isize[G_REFMOL]);
  for (i=0; i<isize[G_REFMOL]; i++)
    for (j=XX; j<=ZZ; j++)
      x_refmol[i][j] = 0;


  normfac = 0;


  do {
    /* Must init pbc every step because of pressure coupling */
    set_pbc(&pbc,ePBC,box);
    rm_pbc(&top.idef,ePBC,natoms,box,x,x);


    /* Dynamically build the ref tripels */
    if ( mode == 2 )
      {
        isize[NDX_REF1]=0;
        for (j=NDX_REF1; j<=NDX_REF3; j++)
          srenew(index[j],isize[NDX_REF1]+1);


        /* consistancy of G_REF[1,2] has already been check */
        /* hence we can look for the third atom right away */


        for (i=0; i<isize[G_REF1]; i++)
          {
            for (j=0; j<isize[G_REF3]; j++)
              {
                /* Avoid expensive stuff if possible */
                if ( top.atoms.atom[index[G_REF1][i]].resnr != 
                     top.atoms.atom[index[G_REF3][j]].resnr &&
                     index[G_REF1][i] != index[G_REF3][j] &&
                     index[G_REF2][i] != index[G_REF3][j] )
                  {
                    pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF3][j]],dx);
                    delta = norm2(dx);
                    if ( delta < tri_upper[G_REF1] &&
                         delta > tri_lower[G_REF1] )
                      {
                        pbc_dx(&pbc,x[index[G_REF2][i]],x[index[G_REF3][j]],dx);
                        delta = norm2(dx);
                        if ( delta < tri_upper[G_REF2] &&
                             delta > tri_lower[G_REF2] )
                          {
                            /* found triple */
                            index[NDX_REF1][isize[NDX_REF1]]=index[G_REF1][i];
                            index[NDX_REF2][isize[NDX_REF1]]=index[G_REF2][i];
                            index[NDX_REF3][isize[NDX_REF1]]=index[G_REF3][j];


                            /* resize groups */
                            isize[NDX_REF1]++;
                            for (k=NDX_REF1; k<=NDX_REF3; k++)
                              srenew(index[k],isize[NDX_REF1]+1);
                          }
                      }
                  }
              }
          }
      }
    else if ( mode ==3 )
      {
        isize[NDX_REF1]=0;
        for (j=NDX_REF1; j<=NDX_REF3; j++)
          srenew(index[j],isize[NDX_REF1]+1);

        /* consistancy will be checked while searching */


        for (i=0; i<isize[G_REF1]; i++)
          {
            for (j=0; j<isize[G_REF2]; j++)
              {
                /* Avoid expensive stuff if possible */
                if ( top.atoms.atom[index[G_REF1][i]].resnr != 
                     top.atoms.atom[index[G_REF2][j]].resnr &&
                     index[G_REF1][i] != index[G_REF2][j] )
                  {
                    pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF2][j]],dx);
                    delta = norm2(dx);
                    if ( delta < tri_upper[G_REF3] &&
                         delta > tri_lower[G_REF3] )
                      {
                        for (k=0; k<isize[G_REF3]; k++)
                          {
                            if ( top.atoms.atom[index[G_REF1][i]].resnr != 
                                 top.atoms.atom[index[G_REF3][k]].resnr &&
                                 top.atoms.atom[index[G_REF2][j]].resnr != 
                                 top.atoms.atom[index[G_REF3][k]].resnr &&
                                 index[G_REF1][i] != index[G_REF3][k] &&
                                 index[G_REF2][j] != index[G_REF3][k])
                              {
                                pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF3][k]],dx);
                                delta = norm2(dx);
                                if ( delta < tri_upper[G_REF1] &&
                                     delta > tri_lower[G_REF1] )
                                  {
                                    pbc_dx(&pbc,x[index[G_REF2][j]],x[index[G_REF3][k]],dx);
                                    delta = norm2(dx);
                                    if ( delta < tri_upper[G_REF2] &&
                                         delta > tri_lower[G_REF2] )
                                      {
                                        /* found triple */
                                        index[NDX_REF1][isize[NDX_REF1]]=index[G_REF1][i];
                                        index[NDX_REF2][isize[NDX_REF1]]=index[G_REF2][j];
                                        index[NDX_REF3][isize[NDX_REF1]]=index[G_REF3][k];
                                    
                                        /* resize groups */
                                        isize[NDX_REF1]++;
                                        for (l=NDX_REF1; l<=NDX_REF3; l++)
                                          srenew(index[l],isize[NDX_REF1]+1);
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }
 
    for (i=0; i<isize[NDX_REF1]; i++)
      {
        /* setup the molecular coordinate system (i',j',k') */
        /* because the coodinate system of the box forms a unit matrix */
        /* (i',j',k') is identical with the rotation matrix */
        clear_mat(rot);


        /* k' = unitv(r(atom0) - r(atom1)) */
        pbc_dx(&pbc,x[index[NDX_REF1][i]],x[index[NDX_REF2][i]],k_mol);
        unitv(k_mol,rot[2]);
        
        /* i' = unitv(k' x (r(atom2) - r(atom1))) */
        pbc_dx(&pbc,x[index[NDX_REF3][i]],x[index[NDX_REF2][i]],i1_mol);
        cprod(i1_mol,rot[2],i2_mol);
        unitv(i2_mol,rot[0]);
      
        /* j' = k' x i' */
        cprod(rot[2],rot[0],rot[1]);


        /* set the point of reference */
        if ( mode == 2 )
          copy_rvec(x[index[NDX_REF3][i]],xi);
        else
          copy_rvec(x[index[NDX_REF1][i]],xi);


        /* make the reference */
        if ( bRef )
          {
            for (j=0; j<isize[G_REFMOL]; j++)
              {
                pbc_dx(&pbc,xi,x[index[G_REFMOL][j]],dx);
                mvmul(rot,dx,dx_mol);
                rvec_inc(x_refmol[j],dx_mol);
                for(k=XX; k<=ZZ; k++)
                   x_refmol[j][k] = x_refmol[j][k] / 2;
              }
          }


        /* Copy the indexed coordinates to a continuous array */
        for(j=0; j<isize[G_SDF]; j++)
          copy_rvec(x[index[G_SDF][j]],x_i1[j]);
        
        /* count the SDF */
        for(j=0; j<isize[G_SDF]; j++) 
          {
            /* Exclude peaks from the reference set */
            bInGroup=FALSE;
            for (k=NDX_REF1; k<=NDX_REF3; k++)
              if ( index[G_SDF][j] == index[k][i] )
                bInGroup=TRUE;


            if ( !bInGroup )
              {
                pbc_dx(&pbc,xi,x_i1[j],dx);
            
                /* transfer dx to the molecular coordinate system */
                mvmul(rot,dx,dx_mol);


                /* check cutoff's and count */
                if ( dx_mol[XX] > -cutoff[XX] && dx_mol[XX] < cutoff[XX] )
                  if ( dx_mol[YY] > -cutoff[YY] && dx_mol[YY] < cutoff[YY] )
                    if ( dx_mol[ZZ] > -cutoff[ZZ] && dx_mol[ZZ] < cutoff[ZZ] )
                      {
                        X = (int)(floor(dx_mol[XX]*invbinw)) + (nbin[XX]-1)/2 
+1;
                        Y = (int)(floor(dx_mol[YY]*invbinw)) + (nbin[YY]-1)/2 
+1;
                        Z = (int)(floor(dx_mol[ZZ]*invbinw)) + (nbin[ZZ]-1)/2 
+1;
                        count[X][Y][Z]++;
                        normfac++;
                      }
              }
          }
      }
  } while (read_next_x(status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  close_trj(status);
  
  sfree(x);


  /* write the reference strcture*/
  if ( bRef )
    {
      fp=ffopen(fnREF,"w"); 
      fprintf(fp,"%s\n",title);
      fprintf(fp,"  %d\n",isize[G_REFMOL]);


      for (i=0; i<isize[G_REFMOL]; i++)
        fprintf(fp,"%5d%5s%5s%5d%8.3f%8.3f%8.3f\n",
                top.atoms.atom[index[G_REFMOL][i]].resnr+1,
                *(top.atoms.resname[top.atoms.atom[index[G_REFMOL][i]].resnr]),
                *(top.atoms.atomname[index[G_REFMOL][i]]),i+1,
                -1*x_refmol[i][XX],-1*x_refmol[i][YY],-1*x_refmol[i][ZZ]);
      /* Inserted -1* on the line above three times */
      fprintf(fp,"   10.00000   10.00000   10.00000\n");
      ffclose(fp);
      fprintf(stderr,"\nWrote reference structure. (%d Atoms)\n",isize[G_REFMOL]);
    }


  /* Calculate the mean probability density */
  fprintf(stderr,"\nNumber of configuations used for SDF: %d\n",(int)normfac);


  normfac = nbin[0]*nbin[1]*nbin[2] / normfac;


  fprintf(stderr,"\nMean probability density: %f\n",1/normfac);


  /* normalize the SDF and write output */
  /* see http://www.csc.fi/gopenmol/index.phtml for documentation */
  fp=ffopen(fnSDF,"wb"); 


  /* rank */
  i_write(fp,3);


  /* Type of surface */
  i_write(fp,42);


  /* Zdim, Ydim, Xdim */
  for (i=ZZ; i>=XX; i--)
    i_write(fp,nbin[i]);


  /* [Z,Y,X][min,max] (box corners in Angstroem)*/
  for (i=ZZ; i>=XX; i--)
    {
      f_write(fp,-cutoff[i]*10);
      f_write(fp,cutoff[i]*10);
    }


/* Original Code
  for (i=1; i<nbin[2]+1; i++)
    for (j=1; j<nbin[1]+1; j++)
      for (k=1; k<nbin[0]+1; k++) 
        {
          sdf = normfac * count[k][j][i];
          if ( sdf < min_sdf ) min_sdf = sdf;
          if ( sdf > max_sdf ) max_sdf = sdf;
          f_write(fp,sdf);
        }*/
/* Changed Code to Mirror SDF to correct coordinates */
  for (i=nbin[2]; i>0; i--)
    for (j=nbin[1]; j>0; j--)
      for (k=nbin[0]; k>0; k--)
        {
          sdf = normfac * count[k][j][i];
          if ( sdf < min_sdf ) min_sdf = sdf;
          if ( sdf > max_sdf ) max_sdf = sdf;
          f_write(fp,sdf);
        }

  fprintf(stderr,"\nMin: %f Max: %f\n",min_sdf,max_sdf);


  ffclose(fp); 


  /* Give back the mem */
  for(i=0; i<nbin[0]+1; i++)
    {
      for (j=0; j<nbin[1]+1; j++)
        {
          sfree(count[i][j]);
        }
      sfree(count[i]);
    }
  sfree(count);
}
Ejemplo n.º 12
0
int main(int argc,char *argv[])
{
  static char *desc[] = {
    "[TT]do_shift[tt] reads a trajectory file and computes the chemical",
    "shift for each time frame (or every [BB]dt[bb] ps) by",
    "calling the 'total' program. If you do not have the total program,",
    "get it. do_shift assumes that the total executable is in",
    "[TT]/home/mdgroup/total/total[tt]. If that is not the case, then you should",
    "set an environment variable [BB]TOTAL[bb] as in: [PAR]",
    "[TT]setenv TOTAL /usr/local/bin/total[tt][PAR]",
    "where the right hand side should point to the total executable.[PAR]",
    "Output is printed in files [TT]shift.out[tt] where t is the time of the frame.[PAR]",
    "The program also needs an input file called [BB]random.dat[bb] which",
    "contains the random coil chemical shifts of all protons."
  };
  static real dt=0.0;
  t_pargs pa[] = {
    { "-dt", FALSE, etREAL, { &dt }, "Time interval between frames." }
  };
  static char *bugs[] = {
    "The program is very slow"
  };
  static     char *OXYGEN="O";
  FILE       *out,*tot,*fp;
  t_topology *top;
  t_atoms    *atoms;
  int        status,nres;
  real       t,nt;
  int        i,natoms,nframe=0;
  matrix     box;
  int        gnx;
  char       *grpnm,*randf;
  atom_id    *index;
  rvec       *x,*x_s;
  char       pdbfile[32],tmpfile[32];
  char       total[256],*dptr;
  t_filenm   fnm[] = {
    { efTRX, "-f",   NULL,     ffREAD },
    { efTPX, NULL,   NULL,     ffREAD },
    { efNDX, NULL,   NULL,     ffREAD },
    { efOUT, "-o",   "shift",  ffWRITE },
    { efDAT, "-d",   "random", ffREAD }
  };
  char *leg[] = { "shift","ring","anisCO","anisCN","sigmaE","sum" };
#define NFILE asize(fnm)

  CopyRight(stdout,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE ,NFILE,fnm,
		    asize(pa),pa,asize(desc),desc,asize(bugs),bugs);
		    
  top=read_top(ftp2fn(efTPX,NFILE,fnm));
  atoms=&(top->atoms);
  nres=atoms->nres;
  for(i=0; (i<atoms->nr); i++)
    if ((strcmp(*atoms->atomname[i],"O1") == 0) ||
	(strcmp(*atoms->atomname[i],"O2") == 0) ||
	(strcmp(*atoms->atomname[i],"OXT") == 0) ||
	(strcmp(*atoms->atomname[i],"OT") == 0))
      atoms->atomname[i]=&OXYGEN;
  rd_index(ftp2fn(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm);
  
  snew(x_s,atoms->nr);

  strcpy(pdbfile,"dsXXXXXX");
  gmx_tmpnam(pdbfile);
  strcpy(tmpfile,"dsXXXXXX");
  gmx_tmpnam(tmpfile);
  fprintf(stderr,"pdbfile = %s\ntmpfile = %s\n",pdbfile,tmpfile);
  
  if ((dptr=getenv("TOTAL")) == NULL)
    dptr="/home/mdgroup/total/total";
  sprintf(total,"%s > /dev/null",dptr);
  fprintf(stderr,"total cmd='%s'\n",total);
  randf=ftp2fn(efDAT,NFILE,fnm);
  
  natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
  if (natoms != atoms->nr) 
    gmx_fatal(FARGS,"Trajectory does not match topology!");
  out=ftp2FILE(efOUT,NFILE,fnm,"w");
  xvgr_legend(out,asize(leg),leg);
  nt=t;
  do {
    if (t >= nt) {
      rm_pbc(&(top->idef),top->atoms.nr,box,x,x_s);
      fp=gmx_ffopen(pdbfile,"w");
      write_pdbfile_indexed(fp,"Generated by do_shift",
			    atoms,x_s,box,0,-1,gnx,index);
      gmx_ffclose(fp);
      
      if ((tot=popen(total,"w")) == NULL)
	perror("opening pipe to total");
      fprintf(tot,"%s\n",pdbfile);
      fprintf(tot,"%s\n",tmpfile);
      fprintf(tot,"3\n");
      fprintf(tot,"N\n");
      fprintf(tot,"%s\n",randf);
      fprintf(tot,"N\n");
      fprintf(tot,"N\n");
      if (pclose(tot) != 0)
	perror("closing pipe to total");
      cat(out,tmpfile,t);
      remove(pdbfile);
      remove(tmpfile);
      nt+=dt;
      nframe++;
    }
  } while(read_next_x(status,&t,natoms,x,box));
  close_trj(status);
  gmx_ffclose(out);
  
  gmx_thanx(stderr);
  
  return 0;
}
Ejemplo n.º 13
0
int gmx_dyndom(int argc, char *argv[])
{
    const char  *desc[] = {
        "[TT]g_dyndom[tt] reads a [TT].pdb[tt] file output from DynDom",
        "(http://www.cmp.uea.ac.uk/dyndom/).",
        "It reads the coordinates, the coordinates of the rotation axis,",
        "and an index file containing the domains.",
        "Furthermore, it takes the first and last atom of the arrow file",
        "as command line arguments (head and tail) and",
        "finally it takes the translation vector (given in DynDom info file)",
        "and the angle of rotation (also as command line arguments). If the angle",
        "determined by DynDom is given, one should be able to recover the",
        "second structure used for generating the DynDom output.",
        "Because of limited numerical accuracy this should be verified by",
        "computing an all-atom RMSD (using [TT]g_confrms[tt]) rather than by file",
        "comparison (using diff).[PAR]",
        "The purpose of this program is to interpolate and extrapolate the",
        "rotation as found by DynDom. As a result unphysical structures with",
        "long or short bonds, or overlapping atoms may be produced. Visual",
        "inspection, and energy minimization may be necessary to",
        "validate the structure."
    };
    static real  trans0 = 0;
    static rvec  head   = { 0, 0, 0 };
    static rvec  tail   = { 0, 0, 0 };
    static real  angle0 = 0, angle1 = 0, maxangle = 0;
    static int   label  = 0, nframes = 11;
    t_pargs      pa[]   = {
        { "-firstangle",    FALSE, etREAL, {&angle0},
          "Angle of rotation about rotation vector" },
        { "-lastangle",    FALSE, etREAL, {&angle1},
          "Angle of rotation about rotation vector" },
        { "-nframe",   FALSE, etINT,  {&nframes},
          "Number of steps on the pathway" },
        { "-maxangle", FALSE, etREAL, {&maxangle},
          "DymDom dtermined angle of rotation about rotation vector" },
        { "-trans",    FALSE, etREAL, {&trans0},
          "Translation (Angstrom) along rotation vector (see DynDom info file)" },
        { "-head",     FALSE, etRVEC, {head},
          "First atom of the arrow vector" },
        { "-tail",     FALSE, etRVEC, {tail},
          "Last atom of the arrow vector" }
    };
    int          i, j, natoms, isize;
    t_trxstatus *status;
    atom_id     *index = NULL, *index_all;
    char         title[256], *grpname;
    t_atoms      atoms;
    real         angle, trans;
    rvec        *x, *v, *xout, *vout;
    matrix       box;
    output_env_t oenv;

    t_filenm     fnm[] = {
        { efPDB, "-f", "dyndom",  ffREAD },
        { efTRO, "-o", "rotated", ffWRITE },
        { efNDX, "-n", "domains", ffREAD }
    };
#define NFILE asize(fnm)

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

    get_stx_coordnum (opt2fn("-f", NFILE, fnm), &natoms);
    init_t_atoms(&atoms, natoms, TRUE);
    snew(x, natoms);
    snew(v, natoms);
    read_stx_conf(opt2fn("-f", NFILE, fnm), title, &atoms, x, v, NULL, box);
    snew(xout, natoms);
    snew(vout, natoms);

    printf("Select group to rotate:\n");
    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
    printf("Going to rotate %s containg %d atoms\n", grpname, isize);

    snew(index_all, atoms.nr);
    for (i = 0; (i < atoms.nr); i++)
    {
        index_all[i] = i;
    }

    status = open_trx(opt2fn("-o", NFILE, fnm), "w");

    label = 'A';
    for (i = 0; (i < nframes); i++, label++)
    {
        angle = angle0 + (i*(angle1-angle0))/(nframes-1);
        trans = trans0*0.1*angle/maxangle;
        printf("Frame: %2d (label %c), angle: %8.3f deg., trans: %8.3f nm\n",
               i, label, angle, trans);
        rot_conf(&atoms, x, v, trans, angle, head, tail, isize, index, xout, vout);

        if (label > 'Z')
        {
            label -= 26;
        }
        for (j = 0; (j < atoms.nr); j++)
        {
            atoms.resinfo[atoms.atom[j].resind].chainid = label;
        }

        write_trx(status, atoms.nr, index_all, &atoms, i, angle, box, xout, vout, NULL);
    }
    close_trx(status);

    return 0;
}
Ejemplo n.º 14
0
t_bb *mkbbind(const char *fn, int *nres, int *nbb, int res0,
              int *nall, atom_id **index,
              char ***atomname, t_atom atom[],
              t_resinfo *resinfo)
{
    static const char * bb_nm[] = { "N", "H", "CA", "C", "O", "HN" };
#define NBB asize(bb_nm)
    t_bb               *bb;
    char               *grpname;
    int                 ai, i, i0, i1, j, k, ri, rnr, gnx, r0, r1;

    fprintf(stderr, "Please select a group containing the entire backbone\n");
    rd_index(fn, 1, &gnx, index, &grpname);
    *nall = gnx;
    fprintf(stderr, "Checking group %s\n", grpname);
    r0 = r1 = atom[(*index)[0]].resind;
    for (i = 1; (i < gnx); i++)
    {
        r0 = min(r0, atom[(*index)[i]].resind);
        r1 = max(r1, atom[(*index)[i]].resind);
    }
    rnr = r1-r0+1;
    fprintf(stderr, "There are %d residues\n", rnr);
    snew(bb, rnr);
    for (i = 0; (i < rnr); i++)
    {
        bb[i].N = bb[i].H = bb[i].CA = bb[i].C = bb[i].O = -1, bb[i].resno = res0+i;
    }

    for (i = j = 0; (i < gnx); i++)
    {
        ai = (*index)[i];
        ri = atom[ai].resind-r0;
        if (strcmp(*(resinfo[ri].name), "PRO") == 0)
        {
            if (strcmp(*(atomname[ai]), "CD") == 0)
            {
                bb[ri].H = ai;
            }
        }
        for (k = 0; (k < NBB); k++)
        {
            if (strcmp(bb_nm[k], *(atomname[ai])) == 0)
            {
                j++;
                break;
            }
        }
        switch (k)
        {
            case 0:
                bb[ri].N = ai;
                break;
            case 1:
            case 5:
                /* No attempt to address the case where some weird input has both H and HN atoms in the group */
                bb[ri].H = ai;
                break;
            case 2:
                bb[ri].CA = ai;
                break;
            case 3:
                bb[ri].C = ai;
                break;
            case 4:
                bb[ri].O = ai;
                break;
            default:
                break;
        }
    }

    for (i0 = 0; (i0 < rnr); i0++)
    {
        if ((bb[i0].N != -1) && (bb[i0].H != -1) &&
            (bb[i0].CA != -1) &&
            (bb[i0].C != -1) && (bb[i0].O != -1))
        {
            break;
        }
    }
    for (i1 = rnr-1; (i1 >= 0); i1--)
    {
        if ((bb[i1].N != -1) && (bb[i1].H != -1) &&
            (bb[i1].CA != -1) &&
            (bb[i1].C != -1) && (bb[i1].O != -1))
        {
            break;
        }
    }
    if (i0 == 0)
    {
        i0++;
    }
    if (i1 == rnr-1)
    {
        i1--;
    }

    for (i = i0; (i < i1); i++)
    {
        bb[i].Cprev = bb[i-1].C;
        bb[i].Nnext = bb[i+1].N;
    }
    rnr = max(0, i1-i0+1);
    fprintf(stderr, "There are %d complete backbone residues (from %d to %d)\n",
            rnr, bb[i0].resno, bb[i1].resno);
    if (rnr == 0)
    {
        gmx_fatal(FARGS, "Zero complete backbone residues were found, cannot proceed");
    }
    for (i = 0; (i < rnr); i++, i0++)
    {
        bb[i] = bb[i0];
    }

    /* Set the labels */
    for (i = 0; (i < rnr); i++)
    {
        ri = atom[bb[i].CA].resind;
        sprintf(bb[i].label, "%s%d", *(resinfo[ri].name), ri+res0);
    }

    *nres = rnr;
    *nbb  = rnr*asize(bb_nm);

    return bb;
}
Ejemplo n.º 15
0
int
do_scattering_intensity (char* fnTPS, char* fnNDX, char* fnXVG, char *fnTRX,
		         real start_q,real end_q, real energy,int ng)
{
    int i,*isize,status,flags = TRX_READ_X,**index_atp;
    char **grpname,title[STRLEN];
    atom_id **index;
    t_topology top;
    int ePBC;
    t_trxframe fr;
    reduced_atom **red;
    structure_factor *sf;
    rvec *xtop;
    real **sf_table;
    int nsftable;
    matrix box;
    double r_tmp;

    snew (sf, 1);
    sf->energy = energy;

    /* Read the topology informations */
    read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
    sfree (xtop);
    
    /* groups stuff... */
    snew (isize, ng);
    snew (index, ng);
    snew (grpname, ng);

    fprintf (stderr, "\nSelect %d group%s\n", ng,
	     ng == 1 ? "" : "s");
    if (fnTPS)
	get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
    else
	rd_index (fnNDX, ng, isize, index, grpname);

    /* The first time we read data is a little special */
    read_first_frame (&status, fnTRX, &fr, flags);

    sf->total_n_atoms = fr.natoms;
    
    snew (red, ng);
    snew (index_atp, ng);

    r_tmp = max (box[XX][XX], box[YY][YY]);
    r_tmp = (double) max (box[ZZ][ZZ], r_tmp);

    sf->ref_k = (2.0 * M_PI) / (r_tmp);
    /* ref_k will be the reference momentum unit */
    sf->n_angles = (int) rint (end_q / sf->ref_k);

    snew (sf->F, ng);
    for (i = 0; i < ng; i++)
	snew (sf->F[i], sf->n_angles);
    for (i = 0; i < ng; i++) {
	snew (red[i], isize[i]);
	rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE);
	index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
    }
    sf_table = compute_scattering_factor_table (sf,&nsftable);
    /* This is the main loop over frames */

    do {
	sf->nSteps++;
	for (i = 0; i < ng; i++) {
	    rearrange_atoms (red[i], &fr, index[i], isize[i], &top,FALSE);

	    compute_structure_factor (sf, box, red[i], isize[i],
				      start_q, end_q, i, sf_table);
	}
    }
    while (read_next_frame (status, &fr));

    save_data (sf, fnXVG, ng, start_q, end_q);

    return 0;
}
Ejemplo n.º 16
0
int gmx_disre(int argc,char *argv[])
{
    const char *desc[] = {
        "[TT]g_disre[tt] computes violations of distance restraints.",
        "If necessary, all protons can be added to a protein molecule ",
        "using the [TT]g_protonate[tt] program.[PAR]",
        "The program always",
        "computes the instantaneous violations rather than time-averaged,",
        "because this analysis is done from a trajectory file afterwards",
        "it does not make sense to use time averaging. However,",
        "the time averaged values per restraint are given in the log file.[PAR]",
        "An index file may be used to select specific restraints for",
        "printing.[PAR]",
        "When the optional [TT]-q[tt] flag is given a [TT].pdb[tt] file coloured by the",
        "amount of average violations.[PAR]",
        "When the [TT]-c[tt] option is given, an index file will be read",
        "containing the frames in your trajectory corresponding to the clusters",
        "(defined in another manner) that you want to analyze. For these clusters",
        "the program will compute average violations using the third power",
        "averaging algorithm and print them in the log file."
    };
    static int  ntop      = 0;
    static int  nlevels   = 20;
    static real max_dr    = 0;
    static gmx_bool bThird    = TRUE;
    t_pargs pa[] = {
        {   "-ntop", FALSE, etINT,  {&ntop},
            "Number of large violations that are stored in the log file every step"
        },
        {   "-maxdr", FALSE, etREAL, {&max_dr},
            "Maximum distance violation in matrix output. If less than or equal to 0 the maximum will be determined by the data."
        },
        {   "-nlevels", FALSE, etINT, {&nlevels},
            "Number of levels in the matrix output"
        },
        {   "-third", FALSE, etBOOL, {&bThird},
            "Use inverse third power averaging or linear for matrix output"
        }
    };

    FILE        *out=NULL,*aver=NULL,*numv=NULL,*maxxv=NULL,*xvg=NULL;
    t_tpxheader header;
    t_inputrec  ir;
    gmx_mtop_t  mtop;
    rvec        *xtop;
    gmx_localtop_t *top;
    t_atoms     *atoms=NULL;
    t_forcerec  *fr;
    t_fcdata    fcd;
    t_nrnb      nrnb;
    t_commrec   *cr;
    t_graph     *g;
    int         ntopatoms,natoms,i,j,kkk;
    t_trxstatus *status;
    real        t;
    rvec        *x,*f,*xav=NULL;
    matrix      box;
    gmx_bool        bPDB;
    int         isize;
    atom_id     *index=NULL,*ind_fit=NULL;
    char        *grpname;
    t_cluster_ndx *clust=NULL;
    t_dr_result dr,*dr_clust=NULL;
    char        **leg;
    real        *vvindex=NULL,*w_rls=NULL;
    t_mdatoms   *mdatoms;
    t_pbc       pbc,*pbc_null;
    int         my_clust;
    FILE        *fplog;
    output_env_t oenv;
    gmx_rmpbc_t  gpbc=NULL;

    t_filenm fnm[] = {
        { efTPX, NULL, NULL, ffREAD },
        { efTRX, "-f", NULL, ffREAD },
        { efXVG, "-ds", "drsum",  ffWRITE },
        { efXVG, "-da", "draver", ffWRITE },
        { efXVG, "-dn", "drnum",  ffWRITE },
        { efXVG, "-dm", "drmax",  ffWRITE },
        { efXVG, "-dr", "restr",  ffWRITE },
        { efLOG, "-l",  "disres", ffWRITE },
        { efNDX, NULL,  "viol",   ffOPTRD },
        { efPDB, "-q",  "viol",   ffOPTWR },
        { efNDX, "-c",  "clust",  ffOPTRD },
        { efXPM, "-x",  "matrix", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,FALSE,0,&fplog);

    if (ntop)
        init5(ntop);

    read_tpxheader(ftp2fn(efTPX,NFILE,fnm),&header,FALSE,NULL,NULL);
    snew(xtop,header.natoms);
    read_tpx(ftp2fn(efTPX,NFILE,fnm),&ir,box,&ntopatoms,xtop,NULL,NULL,&mtop);
    bPDB = opt2bSet("-q",NFILE,fnm);
    if (bPDB) {
        snew(xav,ntopatoms);
        snew(ind_fit,ntopatoms);
        snew(w_rls,ntopatoms);
        for(kkk=0; (kkk<ntopatoms); kkk++) {
            w_rls[kkk] = 1;
            ind_fit[kkk] = kkk;
        }

        snew(atoms,1);
        *atoms = gmx_mtop_global_atoms(&mtop);

        if (atoms->pdbinfo == NULL) {
            snew(atoms->pdbinfo,atoms->nr);
        }
    }

    top = gmx_mtop_generate_local_top(&mtop,&ir);

    g = NULL;
    pbc_null = NULL;
    if (ir.ePBC != epbcNONE) {
        if (ir.bPeriodicMols)
            pbc_null = &pbc;
        else
            g = mk_graph(fplog,&top->idef,0,mtop.natoms,FALSE,FALSE);
    }

    if (ftp2bSet(efNDX,NFILE,fnm)) {
        rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
        xvg=xvgropen(opt2fn("-dr",NFILE,fnm),"Individual Restraints","Time (ps)",
                     "nm",oenv);
        snew(vvindex,isize);
        snew(leg,isize);
        for(i=0; (i<isize); i++) {
            index[i]++;
            snew(leg[i],12);
            sprintf(leg[i],"index %d",index[i]);
        }
        xvgr_legend(xvg,isize,(const char**)leg,oenv);
    }
    else
        isize=0;

    ir.dr_tau=0.0;
    init_disres(fplog,&mtop,&ir,NULL,FALSE,&fcd,NULL);

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

    init_dr_res(&dr,fcd.disres.nres);
    if (opt2bSet("-c",NFILE,fnm)) {
        clust = cluster_index(fplog,opt2fn("-c",NFILE,fnm));
        snew(dr_clust,clust->clust->nr+1);
        for(i=0; (i<=clust->clust->nr); i++)
            init_dr_res(&dr_clust[i],fcd.disres.nres);
    }
    else {
        out =xvgropen(opt2fn("-ds",NFILE,fnm),
                      "Sum of Violations","Time (ps)","nm",oenv);
        aver=xvgropen(opt2fn("-da",NFILE,fnm),
                      "Average Violation","Time (ps)","nm",oenv);
        numv=xvgropen(opt2fn("-dn",NFILE,fnm),
                      "# Violations","Time (ps)","#",oenv);
        maxxv=xvgropen(opt2fn("-dm",NFILE,fnm),
                       "Largest Violation","Time (ps)","nm",oenv);
    }

    mdatoms = init_mdatoms(fplog,&mtop,ir.efep!=efepNO);
    atoms2md(&mtop,&ir,0,NULL,0,mtop.natoms,mdatoms);
    update_mdatoms(mdatoms,ir.init_lambda);
    fr      = mk_forcerec();
    fprintf(fplog,"Made forcerec\n");
    init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL,
                  FALSE,-1);
    init_nrnb(&nrnb);
    if (ir.ePBC != epbcNONE)
        gpbc = gmx_rmpbc_init(&top->idef,ir.ePBC,natoms,box);

    j=0;
    do {
        if (ir.ePBC != epbcNONE) {
            if (ir.bPeriodicMols)
                set_pbc(&pbc,ir.ePBC,box);
            else
                gmx_rmpbc(gpbc,natoms,box,x);
        }

        if (clust) {
            if (j > clust->maxframe)
                gmx_fatal(FARGS,"There are more frames in the trajectory than in the cluster index file. t = %8f\n",t);
            my_clust = clust->inv_clust[j];
            range_check(my_clust,0,clust->clust->nr);
            check_viol(fplog,cr,&(top->idef.il[F_DISRES]),
                       top->idef.iparams,top->idef.functype,
                       x,f,fr,pbc_null,g,dr_clust,my_clust,isize,index,vvindex,&fcd);
        }
        else
            check_viol(fplog,cr,&(top->idef.il[F_DISRES]),
                       top->idef.iparams,top->idef.functype,
                       x,f,fr,pbc_null,g,&dr,0,isize,index,vvindex,&fcd);
        if (bPDB) {
            reset_x(atoms->nr,ind_fit,atoms->nr,NULL,x,w_rls);
            do_fit(atoms->nr,w_rls,x,x);
            if (j == 0) {
                /* Store the first frame of the trajectory as 'characteristic'
                 * for colouring with violations.
                 */
                for(kkk=0; (kkk<atoms->nr); kkk++)
                    copy_rvec(x[kkk],xav[kkk]);
            }
        }
        if (!clust) {
            if (isize > 0) {
                fprintf(xvg,"%10g",t);
                for(i=0; (i<isize); i++)
                    fprintf(xvg,"  %10g",vvindex[i]);
                fprintf(xvg,"\n");
            }
            fprintf(out,  "%10g  %10g\n",t,dr.sumv);
            fprintf(aver, "%10g  %10g\n",t,dr.averv);
            fprintf(maxxv,"%10g  %10g\n",t,dr.maxv);
            fprintf(numv, "%10g  %10d\n",t,dr.nv);
        }
        j++;
    } while (read_next_x(oenv,status,&t,natoms,x,box));
    close_trj(status);
    if (ir.ePBC != epbcNONE)
        gmx_rmpbc_done(gpbc);

    if (clust) {
        dump_clust_stats(fplog,fcd.disres.nres,&(top->idef.il[F_DISRES]),
                         top->idef.iparams,clust->clust,dr_clust,
                         clust->grpname,isize,index);
    }
    else {
        dump_stats(fplog,j,fcd.disres.nres,&(top->idef.il[F_DISRES]),
                   top->idef.iparams,&dr,isize,index,
                   bPDB ? atoms : NULL);
        if (bPDB) {
            write_sto_conf(opt2fn("-q",NFILE,fnm),
                           "Coloured by average violation in Angstrom",
                           atoms,xav,NULL,ir.ePBC,box);
        }
        dump_disre_matrix(opt2fn_null("-x",NFILE,fnm),&dr,fcd.disres.nres,
                          j,&top->idef,&mtop,max_dr,nlevels,bThird);
        ffclose(out);
        ffclose(aver);
        ffclose(numv);
        ffclose(maxxv);
        if (isize > 0) {
            ffclose(xvg);
            do_view(oenv,opt2fn("-dr",NFILE,fnm),"-nxy");
        }
        do_view(oenv,opt2fn("-dn",NFILE,fnm),"-nxy");
        do_view(oenv,opt2fn("-da",NFILE,fnm),"-nxy");
        do_view(oenv,opt2fn("-ds",NFILE,fnm),"-nxy");
        do_view(oenv,opt2fn("-dm",NFILE,fnm),"-nxy");
    }
    thanx(stderr);

    if (gmx_parallel_env_initialized())
        gmx_finalize();

    gmx_log_close(fplog);

    return 0;
}
Ejemplo n.º 17
0
int gmx_trjcat(int argc, char *argv[])
{
    const char     *desc[] =
    {
        "[THISMODULE] concatenates several input trajectory files in sorted order. ",
        "In case of double time frames the one in the later file is used. ",
        "By specifying [TT]-settime[tt] you will be asked for the start time ",
        "of each file. The input files are taken from the command line, ",
        "such that a command like [TT]gmx trjcat -f *.trr -o fixed.trr[tt] should do ",
        "the trick. Using [TT]-cat[tt], you can simply paste several files ",
        "together without removal of frames with identical time stamps.[PAR]",
        "One important option is inferred when the output file is amongst the",
        "input files. In that case that particular file will be appended to",
        "which implies you do not need to store double the amount of data.",
        "Obviously the file to append to has to be the one with lowest starting",
        "time since one can only append at the end of a file.[PAR]",
        "If the [TT]-demux[tt] option is given, the N trajectories that are",
        "read, are written in another order as specified in the [REF].xvg[ref] file.",
        "The [REF].xvg[ref] file should contain something like::",
        "",
        "    0  0  1  2  3  4  5",
        "    2  1  0  2  3  5  4",
        "",
        "The first number is the time, and subsequent numbers point to",
        "trajectory indices.",
        "The frames corresponding to the numbers present at the first line",
        "are collected into the output trajectory. If the number of frames in",
        "the trajectory does not match that in the [REF].xvg[ref] file then the program",
        "tries to be smart. Beware."
    };
    static gmx_bool bCat            = FALSE;
    static gmx_bool bSort           = TRUE;
    static gmx_bool bKeepLast       = FALSE;
    static gmx_bool bKeepLastAppend = FALSE;
    static gmx_bool bOverwrite      = FALSE;
    static gmx_bool bSetTime        = FALSE;
    static gmx_bool bDeMux;
    static real     begin = -1;
    static real     end   = -1;
    static real     dt    = 0;

    t_pargs
        pa[] =
    {
        { "-b", FALSE, etTIME,
          { &begin }, "First time to use (%t)" },
        { "-e", FALSE, etTIME,
          { &end }, "Last time to use (%t)" },
        { "-dt", FALSE, etTIME,
          { &dt }, "Only write frame when t MOD dt = first time (%t)" },
        { "-settime", FALSE, etBOOL,
          { &bSetTime }, "Change starting time interactively" },
        { "-sort", FALSE, etBOOL,
          { &bSort }, "Sort trajectory files (not frames)" },
        { "-keeplast", FALSE, etBOOL,
          { &bKeepLast }, "Keep overlapping frames at end of trajectory" },
        { "-overwrite", FALSE, etBOOL,
          { &bOverwrite }, "Overwrite overlapping frames during appending" },
        { "-cat", FALSE, etBOOL,
          { &bCat }, "Do not discard double time frames" }
    };
#define npargs asize(pa)
    int               ftpin, i, frame, frame_out;
    t_trxstatus      *status, *trxout = nullptr;
    real              t_corr;
    t_trxframe        fr, frout;
    int               n_append;
    gmx_bool          bNewFile, bIndex, bWrite;
    int              *cont_type;
    real             *readtime, *timest, *settime;
    real              first_time  = 0, lasttime = 0, last_ok_t = -1, timestep;
    gmx_bool          lastTimeSet = FALSE;
    real              last_frame_time, searchtime;
    int               isize = 0, j;
    int              *index = nullptr, imax;
    char             *grpname;
    real            **val = nullptr, *t = nullptr, dt_remd;
    int               n, nset, ftpout = -1, prevEndStep = 0, filetype;
    gmx_off_t         fpos;
    gmx_output_env_t *oenv;
    t_filenm          fnm[] =
    {
        { efTRX, "-f", nullptr, ffRDMULT },
        { efTRO, "-o", nullptr, ffWRMULT },
        { efNDX, "-n", "index", ffOPTRD },
        { efXVG, "-demux", "remd", ffOPTRD }
    };

#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_TIME_UNIT, NFILE, fnm,
                           asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
    {
        return 0;
    }
    fprintf(stdout, "Note that major changes are planned in future for "
            "trjcat, to improve usability and utility.");

    auto timeUnit = output_env_get_time_unit(oenv);

    bIndex = ftp2bSet(efNDX, NFILE, fnm);
    bDeMux = ftp2bSet(efXVG, NFILE, fnm);
    bSort  = bSort && !bDeMux;

    imax = -1;
    if (bIndex)
    {
        printf("Select group for output\n");
        rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
        /* scan index */
        imax = index[0];
        for (i = 1; i < isize; i++)
        {
            imax = std::max(imax, index[i]);
        }
    }
    if (bDeMux)
    {
        nset    = 0;
        dt_remd = 0;
        val     = read_xvg_time(opt2fn("-demux", NFILE, fnm), TRUE,
                                opt2parg_bSet("-b", npargs, pa), begin,
                                opt2parg_bSet("-e", npargs, pa), end, 1, &nset, &n,
                                &dt_remd, &t);
        printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt_remd);
        if (debug)
        {
            fprintf(debug, "Dump of replica_index.xvg\n");
            for (i = 0; (i < n); i++)
            {
                fprintf(debug, "%10g", t[i]);
                for (j = 0; (j < nset); j++)
                {
                    fprintf(debug, "  %3d", static_cast<int>(std::round(val[j][i])));
                }
                fprintf(debug, "\n");
            }
        }
    }

    gmx::ArrayRef<const std::string> inFiles = opt2fns("-f", NFILE, fnm);
    if (inFiles.empty())
    {
        gmx_fatal(FARGS, "No input files!" );
    }

    if (bDeMux && ssize(inFiles) != nset)
    {
        gmx_fatal(FARGS, "You have specified %td files and %d entries in the demux table", inFiles.ssize(), nset);
    }

    ftpin = fn2ftp(inFiles[0].c_str());

    if (ftpin != efTRR && ftpin != efXTC && ftpin != efTNG)
    {
        gmx_fatal(FARGS, "gmx trjcat can only handle binary trajectory formats (trr, xtc, tng)");
    }

    for (const std::string &inFile : inFiles)
    {
        if (ftpin != fn2ftp(inFile.c_str()))
        {
            gmx_fatal(FARGS, "All input files must be of the same (trr, xtc or tng) format");
        }
    }

    gmx::ArrayRef<const std::string> outFiles = opt2fns("-o", NFILE, fnm);
    if (outFiles.empty())
    {
        gmx_fatal(FARGS, "No output files!");
    }
    if ((outFiles.size() > 1) && !bDeMux)
    {
        gmx_fatal(FARGS, "Don't know what to do with more than 1 output file if  not demultiplexing");
    }
    else if (bDeMux && ssize(outFiles) != nset && outFiles.size() != 1)
    {
        gmx_fatal(FARGS, "Number of output files should be 1 or %d (#input files), not %td", nset, outFiles.ssize());
    }
    if (bDeMux)
    {
        auto outFilesDemux = gmx::copyOf(outFiles);
        if (gmx::ssize(outFilesDemux) != nset)
        {
            std::string name = outFilesDemux[0];
            outFilesDemux.resize(nset);
            for (i = 0; (i < nset); i++)
            {
                outFilesDemux[0] = gmx::formatString("%d_%s", i, name.c_str());
            }
        }
        do_demux(inFiles, outFilesDemux, n, val, t, dt_remd, isize, index, dt, oenv);
    }
    else
    {
        snew(readtime, inFiles.size() + 1);
        snew(timest, inFiles.size() + 1);
        scan_trj_files(inFiles, readtime, timest, imax, oenv);

        snew(settime, inFiles.size() + 1);
        snew(cont_type, inFiles.size() + 1);
        auto inFilesEdited = gmx::copyOf(inFiles);
        edit_files(inFilesEdited, readtime, timest, settime, cont_type, bSetTime, bSort,
                   oenv);

        /* Check whether the output file is amongst the input files
         * This has to be done after sorting etc.
         */
        const char *out_file = outFiles[0].c_str();
        ftpout   = fn2ftp(out_file);
        n_append = -1;
        for (size_t i = 0; i < inFilesEdited.size() && n_append == -1; i++)
        {
            if (std::strcmp(inFilesEdited[i].c_str(), out_file) == 0)
            {
                n_append = i;
            }
        }
        if (n_append == 0)
        {
            fprintf(stderr, "Will append to %s rather than creating a new file\n",
                    out_file);
        }
        else if (n_append != -1)
        {
            gmx_fatal(FARGS, "Can only append to the first file which is %s (not %s)",
                      inFilesEdited[0].c_str(), out_file);
        }

        /* Not checking input format, could be dangerous :-) */
        /* Not checking output format, equally dangerous :-) */

        frame     = -1;
        frame_out = -1;
        /* the default is not to change the time at all,
         * but this is overridden by the edit_files routine
         */
        t_corr = 0;

        if (n_append == -1)
        {
            if (ftpout == efTNG)
            {
                if (ftpout != ftpin)
                {
                    gmx_fatal(FARGS, "When writing TNG the input file format must also be TNG");
                }
                if (bIndex)
                {
                    trxout = trjtools_gmx_prepare_tng_writing(out_file, 'w', nullptr,
                                                              inFilesEdited[0].c_str(), isize, nullptr, gmx::arrayRefFromArray(index, isize), grpname);
                }
                else
                {
                    trxout = trjtools_gmx_prepare_tng_writing(out_file, 'w', nullptr,
                                                              inFilesEdited[0].c_str(), -1, nullptr, {}, nullptr);
                }
            }
            else
            {
                trxout = open_trx(out_file, "w");
            }
            std::memset(&frout, 0, sizeof(frout));
        }
        else
        {
            t_fileio *stfio;

            if (!read_first_frame(oenv, &status, out_file, &fr, FLAGS))
            {
                gmx_fatal(FARGS, "Reading first frame from %s", out_file);
            }

            stfio = trx_get_fileio(status);
            if (!bKeepLast && !bOverwrite)
            {
                fprintf(stderr, "\n\nWARNING: Appending without -overwrite implies -keeplast "
                        "between the first two files. \n"
                        "If the trajectories have an overlap and have not been written binary \n"
                        "reproducible this will produce an incorrect trajectory!\n\n");

                filetype = gmx_fio_getftp(stfio);
                /* Fails if last frame is incomplete
                 * We can't do anything about it without overwriting
                 * */
                if (filetype == efXTC || filetype == efTNG)
                {
                    lasttime = trx_get_time_of_final_frame(status);
                    fr.time  = lasttime;
                }
                else
                {
                    while (read_next_frame(oenv, status, &fr))
                    {
                        ;
                    }
                    lasttime = fr.time;
                }
                lastTimeSet     = TRUE;
                bKeepLastAppend = TRUE;
                close_trx(status);
                trxout = open_trx(out_file, "a");
            }
            else if (bOverwrite)
            {
                if (gmx_fio_getftp(stfio) != efXTC)
                {
                    gmx_fatal(FARGS, "Overwrite only supported for XTC." );
                }
                last_frame_time = trx_get_time_of_final_frame(status);

                /* xtc_seek_time broken for trajectories containing only 1 or 2 frames
                 *     or when seek time = 0 */
                if (inFilesEdited.size() > 1 && settime[1] < last_frame_time+timest[0]*0.5)
                {
                    /* Jump to one time-frame before the start of next
                     *  trajectory file */
                    searchtime = settime[1]-timest[0]*1.25;
                }
                else
                {
                    searchtime = last_frame_time;
                }
                if (xtc_seek_time(stfio, searchtime, fr.natoms, TRUE))
                {
                    gmx_fatal(FARGS, "Error seeking to append position.");
                }
                read_next_frame(oenv, status, &fr);
                if (std::abs(searchtime - fr.time) > timest[0]*0.5)
                {
                    gmx_fatal(FARGS, "Error seeking: attempted to seek to %f but got %f.",
                              searchtime, fr.time);
                }
                lasttime    = fr.time;
                lastTimeSet = TRUE;
                fpos        = gmx_fio_ftell(stfio);
                close_trx(status);
                trxout = open_trx(out_file, "r+");
                if (gmx_fio_seek(trx_get_fileio(trxout), fpos))
                {
                    gmx_fatal(FARGS, "Error seeking to append position.");
                }
            }
            if (lastTimeSet)
            {
                printf("\n Will append after %f \n", lasttime);
            }
            frout = fr;
        }
        /* Lets stitch up some files */
        timestep = timest[0];
        for (size_t i = n_append + 1; i < inFilesEdited.size(); i++)
        {
            /* Open next file */

            /* set the next time from the last frame in previous file */
            if (i > 0)
            {
                /* When writing TNG the step determine which frame to write. Use an
                 * offset to be able to increase steps properly when changing files. */
                if (ftpout == efTNG)
                {
                    prevEndStep = frout.step;
                }

                if (frame_out >= 0)
                {
                    if (cont_type[i] == TIME_CONTINUE)
                    {
                        begin        = frout.time;
                        begin       += 0.5*timestep;
                        settime[i]   = frout.time;
                        cont_type[i] = TIME_EXPLICIT;
                    }
                    else if (cont_type[i] == TIME_LAST)
                    {
                        begin  = frout.time;
                        begin += 0.5*timestep;
                    }
                    /* Or, if the time in the next part should be changed by the
                     * same amount, start at half a timestep from the last time
                     * so we dont repeat frames.
                     */
                    /* I don't understand the comment above, but for all the cases
                     * I tried the code seems to work properly. B. Hess 2008-4-2.
                     */
                }
                /* Or, if time is set explicitly, we check for overlap/gap */
                if (cont_type[i] == TIME_EXPLICIT)
                {
                    if (i < inFilesEdited.size() &&
                        frout.time < settime[i] - 1.5*timestep)
                    {
                        fprintf(stderr, "WARNING: Frames around t=%f %s have a different "
                                "spacing than the rest,\n"
                                "might be a gap or overlap that couldn't be corrected "
                                "automatically.\n", output_env_conv_time(oenv, frout.time),
                                timeUnit.c_str());
                    }
                }
            }

            /* if we don't have a timestep in the current file, use the old one */
            if (timest[i] != 0)
            {
                timestep = timest[i];
            }
            read_first_frame(oenv, &status, inFilesEdited[i].c_str(), &fr, FLAGS);
            if (!fr.bTime)
            {
                fr.time = 0;
                fprintf(stderr, "\nWARNING: Couldn't find a time in the frame.\n");
            }

            if (cont_type[i] == TIME_EXPLICIT)
            {
                t_corr = settime[i]-fr.time;
            }
            /* t_corr is the amount we want to change the time.
             * If the user has chosen not to change the time for
             * this part of the trajectory t_corr remains at
             * the value it had in the last part, changing this
             * by the same amount.
             * If no value was given for the first trajectory part
             * we let the time start at zero, see the edit_files routine.
             */

            bNewFile = TRUE;

            if (!lastTimeSet)
            {
                lasttime    = 0;
                lastTimeSet = true;
            }
            printf("\n");
            printf("lasttime %g\n", lasttime);

            do
            {
                /* copy the input frame to the output frame */
                frout = fr;
                /* set the new time by adding the correct calculated above */
                frout.time += t_corr;
                if (ftpout == efTNG)
                {
                    frout.step += prevEndStep;
                }
                /* quit if we have reached the end of what should be written */
                if ((end > 0) && (frout.time > end+GMX_REAL_EPS))
                {
                    i = inFilesEdited.size();
                    break;
                }

                /* determine if we should write this frame (dt is handled elsewhere) */
                if (bCat) /* write all frames of all files */
                {
                    bWrite = TRUE;
                }
                else if (bKeepLast || (bKeepLastAppend && i == 1))
                /* write till last frame of this traj
                   and skip first frame(s) of next traj */
                {
                    bWrite = ( frout.time > lasttime+0.5*timestep );
                }
                else /* write till first frame of next traj */
                {
                    bWrite = ( frout.time < settime[i+1]-0.5*timestep );
                }

                if (bWrite && (frout.time >= begin) )
                {
                    frame++;
                    if (frame_out == -1)
                    {
                        first_time = frout.time;
                    }
                    lasttime    = frout.time;
                    lastTimeSet = TRUE;
                    if (dt == 0 || bRmod(frout.time, first_time, dt))
                    {
                        frame_out++;
                        last_ok_t = frout.time;
                        if (bNewFile)
                        {
                            fprintf(stderr, "\nContinue writing frames from %s t=%g %s, "
                                    "frame=%d      \n",
                                    inFilesEdited[i].c_str(),
                                    output_env_conv_time(oenv, frout.time), timeUnit.c_str(),
                                    frame);
                            bNewFile = FALSE;
                        }

                        if (bIndex)
                        {
                            write_trxframe_indexed(trxout, &frout, isize, index,
                                                   nullptr);
                        }
                        else
                        {
                            write_trxframe(trxout, &frout, nullptr);
                        }
                        if ( ((frame % 10) == 0) || (frame < 10) )
                        {
                            fprintf(stderr, " ->  frame %6d time %8.3f %s     \r",
                                    frame_out, output_env_conv_time(oenv, frout.time), timeUnit.c_str());
                            fflush(stderr);
                        }
                    }
                }
            }
            while (read_next_frame(oenv, status, &fr));

            close_trx(status);
        }
        if (trxout)
        {
            close_trx(trxout);
        }
        fprintf(stderr, "\nLast frame written was %d, time %f %s\n",
                frame, output_env_conv_time(oenv, last_ok_t), timeUnit.c_str());
    }

    return 0;
}
Ejemplo n.º 18
0
int gmx_trjcat(int argc,char *argv[])
{
  const char *desc[] = {
      "trjcat concatenates several input trajectory files in sorted order. ",
      "In case of double time frames the one in the later file is used. ",
      "By specifying [TT]-settime[tt] you will be asked for the start time ",
      "of each file. The input files are taken from the command line, ",
      "such that a command like [TT]trjcat -o fixed.trr *.trr[tt] should do ",
      "the trick. Using [TT]-cat[tt] you can simply paste several files ",
      "together without removal of frames with identical time stamps.[PAR]",
      "One important option is inferred when the output file is amongst the",
      "input files. In that case that particular file will be appended to",
      "which implies you do not need to store double the amount of data.",
      "Obviously the file to append to has to be the one with lowest starting",
      "time since one can only append at the end of a file.[PAR]",
      "If the [TT]-demux[tt] option is given, the N trajectories that are",
      "read, are written in another order as specified in the xvg file."
      "The xvg file should contain something like:[PAR]",
      "0  0  1  2  3  4  5[BR]",
      "2  1  0  2  3  5  4[BR]",
      "Where the first number is the time, and subsequent numbers point to",
      "trajectory indices.",
      "The frames corresponding to the numbers present at the first line",
      "are collected into the output trajectory. If the number of frames in",
      "the trajectory does not match that in the xvg file then the program",
      "tries to be smart. Beware."
  };
  static bool  bVels=TRUE;
  static int   prec=3;
  static bool  bCat=FALSE;
  static bool  bSort=TRUE;
  static bool  bKeepLast=FALSE;
  static bool  bSetTime=FALSE;
  static bool  bDeMux;
  static real  begin=-1;
  static real  end=-1;
  static real  dt=0;

  t_pargs pa[] = {
    { "-b",       FALSE, etTIME, {&begin},
      "First time to use (%t)"},
    { "-e",       FALSE, etTIME, {&end},
      "Last time to use (%t)"},
    { "-dt",      FALSE, etTIME, {&dt},
      "Only write frame when t MOD dt = first time (%t)" },
    { "-prec",    FALSE, etINT,  {&prec},
      "Precision for .xtc and .gro writing in number of decimal places" },
    { "-vel",     FALSE, etBOOL, {&bVels},
      "Read and write velocities if possible" },
    { "-settime", FALSE, etBOOL, {&bSetTime}, 
      "Change starting time interactively" },
    { "-sort",    FALSE, etBOOL, {&bSort},
      "Sort trajectory files (not frames)" },
    { "-keeplast",FALSE, etBOOL, {&bKeepLast},
      "keep overlapping frames at end of trajectory" },
    { "-cat",     FALSE, etBOOL, {&bCat},
      "do not discard double time frames" }
  };
#define npargs asize(pa)
  int         status,ftpin,i,frame,frame_out,step=0,trjout=0;
  rvec        *x,*v;
  real        xtcpr,t_corr;
  t_trxframe  fr,frout;
  char        **fnms,**fnms_out,*in_file,*out_file;
  int         n_append;
  int         trxout=-1;
  bool        bNewFile,bIndex,bWrite;
  int         earliersteps,nfile_in,nfile_out,*cont_type,last_ok_step;
  real        *readtime,*timest,*settime;
  real        first_time=0,lasttime=NOTSET,last_ok_t=-1,timestep;
  int         isize,j;
  atom_id     *index=NULL,imax;
  char        *grpname;
  real        **val=NULL,*t=NULL,dt_remd;
  int         n,nset;
  t_filenm fnm[] = {
      { efTRX, "-f",     NULL,      ffRDMULT },
      { efTRO, "-o",     NULL,      ffWRMULT },
      { efNDX, "-n",     "index",   ffOPTRD  },
      { efXVG, "-demux", "remd",    ffOPTRD  }
  };
  
#define NFILE asize(fnm)
  
  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_BE_NICE|PCA_TIME_UNIT,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,
		    0,NULL);

  bIndex = ftp2bSet(efNDX,NFILE,fnm);
  bDeMux = ftp2bSet(efXVG,NFILE,fnm);
  bSort  = bSort && !bDeMux;
  
  imax=NO_ATID;
  if (bIndex) {
    printf("Select group for output\n");
    rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
    /* scan index */
    imax=index[0];
    for(i=1; i<isize; i++)
      imax = max(imax, index[i]);
  }
  if (bDeMux) {
    nset    = 0;
    dt_remd = 0;
    val=read_xvg_time(opt2fn("-demux",NFILE,fnm),TRUE,
		      opt2parg_bSet("-b",npargs,pa),begin,
		      opt2parg_bSet("-e",npargs,pa),end,
		      1,&nset,&n,&dt_remd,&t);
    printf("Read %d sets of %d points, dt = %g\n\n",nset,n,dt_remd);
    if (debug) {
      fprintf(debug,"Dump of replica_index.xvg\n");
      for(i=0; (i<n); i++) {
	fprintf(debug,"%10g",t[i]);
	for(j=0; (j<nset); j++) {
	  fprintf(debug,"  %3d",gmx_nint(val[j][i]));
	}
	fprintf(debug,"\n");
      }
    }
  }
  /* prec is in nr of decimal places, xtcprec is a multiplication factor: */
  xtcpr=1;
  for (i=0; i<prec; i++)
    xtcpr*=10;
  
  nfile_in = opt2fns(&fnms,"-f",NFILE,fnm);
  if (!nfile_in)
    gmx_fatal(FARGS,"No input files!");
    
  if (bDeMux && (nfile_in != nset)) 
    gmx_fatal(FARGS,"You have specified %d files and %d entries in the demux table",nfile_in,nset);
    
  nfile_out = opt2fns(&fnms_out,"-o",NFILE,fnm);
  if (!nfile_out)
    gmx_fatal(FARGS,"No output files!");
  if ((nfile_out > 1) && !bDeMux) 
    gmx_fatal(FARGS,"Don't know what to do with more than 1 output file if  not demultiplexing");
  else if (bDeMux && (nfile_out != nset) && (nfile_out != 1))
    gmx_fatal(FARGS,"Number of output files should be 1 or %d (#input files), not %d",nset,nfile_out);

  if (bDeMux) {
    if (nfile_out != nset) {
      char *buf = strdup(fnms_out[0]);
      snew(fnms_out,nset);
      for(i=0; (i<nset); i++) {
	snew(fnms_out[i],strlen(buf)+32);
	sprintf(fnms_out[i],"%d_%s",i,buf);
      }
    }
    do_demux(nfile_in,fnms,fnms_out,n,val,t,dt_remd,isize,index,dt);
  }
  else {
    snew(readtime,nfile_in+1);
    snew(timest,nfile_in+1);
    scan_trj_files(fnms,nfile_in,readtime,timest,imax);
    
    snew(settime,nfile_in+1);
    snew(cont_type,nfile_in+1);
    edit_files(fnms,nfile_in,readtime,timest,settime,cont_type,bSetTime,bSort);
  
    /* Check whether the output file is amongst the input files 
     * This has to be done after sorting etc.
     */
    out_file = fnms_out[0];
    n_append = -1;
    for(i=0; ((i<nfile_in) && (n_append==-1)); i++) {
      if (strcmp(fnms[i],out_file) == 0) {
	n_append = i;
      }
    }
    if (n_append == 0)
      fprintf(stderr,"Will append to %s rather than creating a new file\n",
	      out_file);
    else if (n_append != -1)
      gmx_fatal(FARGS,"Can only append to the first file which is %s (not %s)",
		fnms[0],out_file);
    
    earliersteps=0;    
    
    /* Not checking input format, could be dangerous :-) */
    /* Not checking output format, equally dangerous :-) */
    
    frame=-1;
    frame_out=-1;
    /* the default is not to change the time at all,
     * but this is overridden by the edit_files routine
     */
    t_corr=0;
    
    if (n_append == -1) {
      trxout = open_trx(out_file,"w");
      memset(&frout,0,sizeof(frout));
    }
    else {
      /* Read file to find what is the last frame in it */
      if (!read_first_frame(&status,out_file,&fr,FLAGS))
	gmx_fatal(FARGS,"Reading first frame from %s",out_file);
      while (read_next_frame(status,&fr))
	;
      close_trj(status);
      lasttime = fr.time;
      bKeepLast = TRUE;
      trxout = open_trx(out_file,"a");
      frout = fr;
    }
    /* Lets stitch up some files */
    timestep = timest[0];
    for(i=n_append+1; (i<nfile_in); i++) {
      /* Open next file */
      
      /* set the next time from the last frame in previous file */
      if (i > 0) {
	if (frame_out >= 0) {
	  if(cont_type[i]==TIME_CONTINUE) {
	    begin =frout.time;
	    begin += 0.5*timestep;
	    settime[i]=frout.time;
	    cont_type[i]=TIME_EXPLICIT;	  
	  }
	  else if(cont_type[i]==TIME_LAST) {
	    begin=frout.time;
	    begin += 0.5*timestep;
	  }
	  /* Or, if the time in the next part should be changed by the
	   * same amount, start at half a timestep from the last time
	   * so we dont repeat frames.
	   */
	  /* I don't understand the comment above, but for all the cases
	   * I tried the code seems to work properly. B. Hess 2008-4-2.
	   */
	}
	/* Or, if time is set explicitly, we check for overlap/gap */
	if(cont_type[i]==TIME_EXPLICIT) 
	  if( ( i < nfile_in ) &&
	      ( frout.time < settime[i]-1.5*timestep ) ) 
	    fprintf(stderr, "WARNING: Frames around t=%f %s have a different "
		    "spacing than the rest,\n"
		    "might be a gap or overlap that couldn't be corrected "
		    "automatically.\n",convert_time(frout.time),time_unit());
      }
      
      /* if we don't have a timestep in the current file, use the old one */
      if ( timest[i] != 0 )
	timestep = timest[i];
      
      read_first_frame(&status,fnms[i],&fr,FLAGS);
      if(!fr.bTime) {
	fr.time=0;
	fprintf(stderr,"\nWARNING: Couldn't find a time in the frame.\n");
      }
      
      if(cont_type[i]==TIME_EXPLICIT)
	t_corr=settime[i]-fr.time;
      /* t_corr is the amount we want to change the time.
       * If the user has chosen not to change the time for
       * this part of the trajectory t_corr remains at 
       * the value it had in the last part, changing this
       * by the same amount.
       * If no value was given for the first trajectory part
       * we let the time start at zero, see the edit_files routine.
       */
	
      bNewFile=TRUE;
      
      printf("\n");
      if (lasttime != NOTSET)
	printf("lasttime %g\n", lasttime);
      
      do {
	/* copy the input frame to the output frame */
	frout=fr;
	/* set the new time by adding the correct calculated above */
	frout.time += t_corr; 
	/* quit if we have reached the end of what should be written */
	if((end > 0) && (frout.time > end+GMX_REAL_EPS)) {
	  i=nfile_in;
	  break;
	}
	
	/* determine if we should write this frame (dt is handled elsewhere) */
	if (bCat) /* write all frames of all files */ 
	  bWrite = TRUE;
	else if ( bKeepLast ) /* write till last frame of this traj
				 and skip first frame(s) of next traj */
	  bWrite = ( frout.time > lasttime+0.5*timestep );
	else /* write till first frame of next traj */
	  bWrite = ( frout.time < settime[i+1]-0.5*timestep );
	
	if( bWrite && (frout.time >= begin) ) {
	  frame++;
	  if (frame_out == -1)
	    first_time = frout.time;
	  lasttime = frout.time;
	  if (dt==0 || bRmod(frout.time,first_time,dt)) {
	    frame_out++;
	    last_ok_t=frout.time;
	    if(bNewFile) {
	      fprintf(stderr,"\nContinue writing frames from %s t=%g %s, "
		      "frame=%d      \n",
		      fnms[i],convert_time(frout.time),time_unit(),frame);
	      bNewFile=FALSE;
	    }
	    
	    if (bIndex)
	      write_trxframe_indexed(trxout,&frout,isize,index,NULL);
	    else
	      write_trxframe(trxout,&frout,NULL);
	    if ( ((frame % 10) == 0) || (frame < 10) )
	      fprintf(stderr," ->  frame %6d time %8.3f %s     \r",
		      frame_out,convert_time(frout.time),time_unit());
	  }
	}
      } while( read_next_frame(status,&fr));
      
      close_trj(status);
      
      earliersteps+=step;	  
    }  
    if (trxout >= 0)
      close_trx(trxout);
     
    fprintf(stderr,"\nLast frame written was %d, time %f %s\n",
	    frame,convert_time(last_ok_t),time_unit()); 
  }
  thanx(stderr);
  
  return 0;
}