Пример #1
0
/*!
 * \param[in] out  Output file.
 * \param[in] sc   Selection collection which should be written.
 */
void
xvgr_selcollection(FILE *out, gmx_ana_selcollection_t *sc)
{
    char  *buf;
    char  *p, *nl;

    if (bPrintXvgrCodes() && sc && sc->selstr)
    {
        fprintf(out, "# Selections:\n");
        buf = strdup(sc->selstr);
        p = buf;
        while (p && p[0] != 0)
        {
            nl = strchr(p, '\n');
            if (nl)
            {
                *nl = 0;
            }
            fprintf(out, "#   %s\n", p);
            p  = nl;
            if (nl)
            {
                ++p;
            }
        }
        fprintf(out, "#\n");
        sfree(buf);
    }
}
Пример #2
0
void xvgr_line_props(FILE *out, int NrSet, int LineStyle, int LineColor)
{
  if (bPrintXvgrCodes()) {
    fprintf(out, "@    with g0\n");
    fprintf(out, "@    s%d linestyle %d\n", NrSet, LineStyle);
    fprintf(out, "@    s%d color %d\n", NrSet, LineColor);
  }
}
Пример #3
0
void xvgr_world(FILE *out,real xmin,real ymin,real xmax,real ymax)
{
  if (bPrintXvgrCodes()) 
    fprintf(out,"@ world xmin %g\n"
	    "@ world ymin %g\n"
	    "@ world xmax %g\n"
	    "@ world ymax %g\n",xmin,ymin,xmax,ymax);
}
Пример #4
0
void analyse_ss(char *outfile, t_matrix *mat, char *ss_string)
{
  FILE *fp;
  t_mapping *map;
  int s,f,r,*count,ss_count;
  char **leg;
  
  map=mat->map;
  snew(count,mat->nmap);
  snew(leg,mat->nmap+1);
  leg[0]="Structure";
  for(s=0; s<mat->nmap; s++)
    leg[s+1]=map[s].desc;
  
  fp=xvgropen(outfile,"Secondary Structure",
	      xvgr_tlabel(),"Number of Residues");
  if (bPrintXvgrCodes())
    fprintf(fp,"@ subtitle \"Structure = ");
  for(s=0; s<strlen(ss_string); s++) {
    if (s>0)
      fprintf(fp," + ");
    for(f=0; f<mat->nmap; f++)
      if (ss_string[s]==map[f].code.c1)
	fprintf(fp,"%s",map[f].desc);
  }
  fprintf(fp,"\"\n");
  xvgr_legend(fp,mat->nmap+1,leg);
  
  for(f=0; f<mat->nx; f++) {
    ss_count=0;
    for(s=0; s<mat->nmap; s++)
      count[s]=0;
    for(r=0; r<mat->ny; r++)
      count[mat->matrix[f][r]]++;
    for(s=0; s<mat->nmap; s++) {
      if (strchr(ss_string,map[s].code.c1))
	ss_count+=count[s];
    }
    fprintf(fp,"%8g %5d",mat->axis_x[f],ss_count);
    for(s=0; s<mat->nmap; s++)
      fprintf(fp," %5d",count[s]);
    fprintf(fp,"\n");
  }
  
  fclose(fp);
  sfree(leg);
  sfree(count);
}
Пример #5
0
void xvgr_box(FILE *out,
	      int LocType,
	      real xmin,real ymin,real xmax,real ymax,
	      int LineStyle,int LineWidth,int LineColor,
	      int BoxFill,int BoxColor,int BoxPattern)
{
  if (bPrintXvgrCodes()) {
    fprintf(out,"@with box\n");
    fprintf(out,"@    box on\n");
    fprintf(out,"@    box loctype %s\n",LocTypeStr[LocType]);
    fprintf(out,"@    box %g, %g, %g, %g\n",xmin,ymin,xmax,ymax);
    fprintf(out,"@    box linestyle %d\n",LineStyle);
    fprintf(out,"@    box linewidth %d\n",LineWidth);
    fprintf(out,"@    box color %d\n",LineColor);
    fprintf(out,"@    box fill %s\n",BoxFillStr[BoxFill]);
    fprintf(out,"@    box fill color %d\n",BoxColor);
    fprintf(out,"@    box fill pattern %d\n",BoxPattern);
    fprintf(out,"@box def\n");
  }
}
Пример #6
0
void xvgr_legend(FILE *out,int nsets,char *setname[])
{
  int i;
  
  if (bPrintXvgrCodes()) {
    xvgr_view(out,0.15,0.15,0.75,0.85);
    fprintf(out,"@ legend on\n");
    fprintf(out,"@ legend box on\n");
    fprintf(out,"@ legend loctype view\n");
    fprintf(out,"@ legend %g, %g\n",0.78,0.8);
    fprintf(out,"@ legend length %d\n",2);
    for(i=0; (i<nsets); i++)
      if (setname[i]) {
	if (use_xmgr())
	  fprintf(out,"@ legend string %d \"%s\"\n",i,setname[i]);
	else
	  fprintf(out,"@ s%d legend \"%s\"\n",i,setname[i]);
      }
  }
}
Пример #7
0
FILE *xvgropen(const char *fn,const char *title,const char *xaxis,const char *yaxis)
{
  FILE *xvgr;
  char pukestr[100];
  time_t t;
  
  xvgr=gmx_fio_fopen(fn,"w");
  if (bPrintXvgrCodes()) {
    time(&t);
    fprintf(xvgr,"# This file was created %s",ctime(&t));
    fprintf(xvgr,"# by the following command:\n# %s\n#\n",command_line());
    fprintf(xvgr,"# %s is part of G R O M A C S:\n#\n",Program());
    bromacs(pukestr,99);
    fprintf(xvgr,"# %s\n#\n",pukestr);
    fprintf(xvgr,"@    title \"%s\"\n",title);
    fprintf(xvgr,"@    xaxis  label \"%s\"\n",xaxis);
    fprintf(xvgr,"@    yaxis  label \"%s\"\n",yaxis);
    if (use_xmgr())
      fprintf(xvgr,"@TYPE nxy\n");
    else
      fprintf(xvgr,"@TYPE xy\n");
  }
  return xvgr;
}
Пример #8
0
static void estimate_error(char *eefile,int nb_min,int resol,int n,int nset,
                           double *av,double *sig,real **val,real dt,
                           bool bFitAc,bool bSingleExpFit,bool bAllowNegLTCorr)
{
    FILE   *fp;
    int    bs,prev_bs,nbs,nb;
    real   spacing,nbr;
    int    s,i,j;
    double blav,var;
    char   **leg;
    real   *tbs,*ybs,rtmp,dens,*fitsig,twooe,tau1_est,tau_sig;
    real   fitparm[4];
    real   ee,a,tau1,tau2;
    
    if (n < 4)
    {
      fprintf(stdout,"The number of points is smaller than 4, can not make an error estimate\n");
      
      return;
    }
    
    fp = xvgropen(eefile,"Error estimates",
                  "Block size (time)","Error estimate");
    if (bPrintXvgrCodes())
    {
        fprintf(fp,
                "@ subtitle \"using block averaging, total time %g (%d points)\"\n",
                (n-1)*dt,n);
    }
    snew(leg,2*nset);
    xvgr_legend(fp,2*nset,leg);
    sfree(leg);

    spacing = pow(2,1.0/resol);
    snew(tbs,n);
    snew(ybs,n);
    snew(fitsig,n);
    for(s=0; s<nset; s++)
    {
        nbs = 0;
        prev_bs = 0;
        nbr = nb_min;
        while (nbr <= n)
        {
            bs = n/(int)nbr;
            if (bs != prev_bs)
            {
                nb = n/bs;
                var = 0;
                for(i=0; i<nb; i++)
                {
                    blav=0;
                    for (j=0; j<bs; j++)
                    {
                        blav += val[s][bs*i+j];
                    }
                    var += sqr(av[s] - blav/bs);
                }
                tbs[nbs] = bs*dt;
                if (sig[s] == 0)
                {
                    ybs[nbs] = 0;
                }
                else
                {
                    ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]);
                }
                nbs++;
            }
            nbr *= spacing;
            nb = (int)(nbr+0.5);
            prev_bs = bs;
        }

        if (sig[s] == 0)
        {
            ee   = 0;
            a    = 1;
            tau1 = 0;
            tau2 = 0;
        }
        else
        {
            for(i=0; i<nbs/2; i++)
            {
                rtmp         = tbs[i];
                tbs[i]       = tbs[nbs-1-i];
                tbs[nbs-1-i] = rtmp;
                rtmp         = ybs[i];
                ybs[i]       = ybs[nbs-1-i];
                ybs[nbs-1-i] = rtmp;
            }
            /* The initial slope of the normalized ybs^2 is 1.
             * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1
             * From this we take our initial guess for tau1.
             */
            twooe = 2/exp(1);
            i = -1;
            do
            {
                i++;
                tau1_est = tbs[i];
            } while (i < nbs - 1 &&
                     (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est));
            
            if (ybs[0] > ybs[1])
            {
                fprintf(stdout,"Data set %d has strange time correlations:\n"
                        "the std. error using single points is larger than that of blocks of 2 points\n"
                        "The error estimate might be inaccurate, check the fit\n",
                        s+1);
                /* Use the total time as tau for the fitting weights */
                tau_sig = (n - 1)*dt;
            }
            else
            {
                tau_sig = tau1_est;
            }
            
            if (debug)
            {
                fprintf(debug,"set %d tau1 estimate %f\n",s+1,tau1_est);
            }
            
            /* Generate more or less appropriate sigma's,
             * also taking the density of points into account.
             */
            for(i=0; i<nbs; i++)
            {
                if (i == 0)
                {
                    dens = tbs[1]/tbs[0] - 1;
                }
                else if (i == nbs-1)
                {
                    dens = tbs[nbs-1]/tbs[nbs-2] - 1;
                }
                else
                {
                    dens = 0.5*(tbs[i+1]/tbs[i-1] - 1);
                }
                fitsig[i] = sqrt((tau_sig + tbs[i])/dens);
            }
            
            if (!bSingleExpFit)
            {
                fitparm[0] = tau1_est;
                fitparm[1] = 0.95;
                /* We set the initial guess for tau2
                 * to halfway between tau1_est and the total time (on log scale).
                 */
                fitparm[2] = sqrt(tau1_est*(n-1)*dt);
                do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,0);
                fitparm[3] = 1-fitparm[1];
            }
            if (bSingleExpFit || fitparm[0]<0 || fitparm[2]<0 || fitparm[1]<0
                || (fitparm[1]>1 && !bAllowNegLTCorr) || fitparm[2]>(n-1)*dt)
            {
                if (!bSingleExpFit)
                {
                    if (fitparm[2] > (n-1)*dt)
                    {
                        fprintf(stdout,
                                "Warning: tau2 is longer than the length of the data (%g)\n"
                                "         the statistics might be bad\n",
                                (n-1)*dt);
                    }
                    else
                    {
                        fprintf(stdout,"a fitted parameter is negative\n");
                    }
                    fprintf(stdout,"invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                            sig[s]*anal_ee_inf(fitparm,n*dt),
                            fitparm[1],fitparm[0],fitparm[2]);
                    /* Do a fit with tau2 fixed at the total time.
                     * One could also choose any other large value for tau2.
                     */
                    fitparm[0] = tau1_est;
                    fitparm[1] = 0.95;
                    fitparm[2] = (n-1)*dt;
                    fprintf(stderr,"Will fix tau2 at the total time: %g\n",fitparm[2]);
                    do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,4);
                    fitparm[3] = 1-fitparm[1];
                }
                if (bSingleExpFit || fitparm[0]<0 || fitparm[1]<0
                    || (fitparm[1]>1 && !bAllowNegLTCorr))
                {
                    if (!bSingleExpFit) {
                        fprintf(stdout,"a fitted parameter is negative\n");
                        fprintf(stdout,"invalid fit:  e.e. %g  a %g  tau1 %g  tau2 %g\n",
                                sig[s]*anal_ee_inf(fitparm,n*dt),
                                fitparm[1],fitparm[0],fitparm[2]);
                    }
                    /* Do a single exponential fit */
                    fprintf(stderr,"Will use a single exponential fit for set %d\n",s+1);
                    fitparm[0] = tau1_est;
                    fitparm[1] = 1.0;
                    fitparm[2] = 0.0;
                    do_lmfit(nbs,ybs,fitsig,0,tbs,0,dt*n,bDebugMode(),effnERREST,fitparm,6);
                    fitparm[3] = 1-fitparm[1];
                }
            }
            ee   = sig[s]*anal_ee_inf(fitparm,n*dt);
            a    = fitparm[1];
            tau1 = fitparm[0];
            tau2 = fitparm[2];
        }
        fprintf(stdout,"Set %3d:  err.est. %g  a %g  tau1 %g  tau2 %g\n",
                s+1,ee,a,tau1,tau2);
        fprintf(fp,"@ legend string %d \"av %f\"\n",2*s,av[s]);
        fprintf(fp,"@ legend string %d \"ee %6g\"\n",
                2*s+1,sig[s]*anal_ee_inf(fitparm,n*dt));
        for(i=0; i<nbs; i++)
        {
            fprintf(fp,"%g %g %g\n",tbs[i],sig[s]*sqrt(ybs[i]/(n*dt)),
                    sig[s]*sqrt(fit_function(effnERREST,fitparm,tbs[i])/(n*dt)));
        }
        
        if (bFitAc)
        {
            int fitlen;
            real *ac,acint,ac_fit[4];
            
            snew(ac,n);
            for(i=0; i<n; i++) {
                ac[i] = val[s][i] - av[s];
                if (i > 0)
                    fitsig[i] = sqrt(i);
                else
                    fitsig[i] = 1;
            }
            low_do_autocorr(NULL,NULL,n,1,-1,&ac,
                            dt,eacNormal,1,FALSE,TRUE,
                            FALSE,0,0,effnNONE,0);
            
            fitlen = n/nb_min;
            
            /* Integrate ACF only up to fitlen/2 to avoid integrating noise */ 
            acint = 0.5*ac[0];
            for(i=1; i<=fitlen/2; i++)
            {
                acint += ac[i];
            }
            acint *= dt;
            
            /* Generate more or less appropriate sigma's */
            for(i=0; i<=fitlen; i++)
            {
                fitsig[i] = sqrt(acint + dt*i);
            }
            
            ac_fit[0] = 0.5*acint;
            ac_fit[1] = 0.95;
            ac_fit[2] = 10*acint;
            do_lmfit(n/nb_min,ac,fitsig,dt,0,0,fitlen*dt,
                     bDebugMode(),effnEXP3,ac_fit,0);
            ac_fit[3] = 1 - ac_fit[1];
            
            fprintf(stdout,"Set %3d:  ac erest %g  a %g  tau1 %g  tau2 %g\n",
                    s+1,sig[s]*anal_ee_inf(ac_fit,n*dt),
                    ac_fit[1],ac_fit[0],ac_fit[2]);
            
            fprintf(fp,"&\n");
            for(i=0; i<nbs; i++)
            {
                fprintf(fp,"%g %g\n",tbs[i],
                        sig[s]*sqrt(fit_function(effnERREST,ac_fit,tbs[i]))/(n*dt));
            }
            
            sfree(ac);
        }
        if (s < nset-1)
        {
            fprintf(fp,"&\n");
        }
    }
    sfree(fitsig);
    sfree(ybs);
    sfree(tbs);
    fclose(fp);
}
Пример #9
0
int gmx_angle(int argc,char *argv[])
{
    static char *desc[] = {
        "g_angle computes the angle distribution for a number of angles",
        "or dihedrals. This way you can check whether your simulation",
        "is correct. With option -ov you can plot the average angle of",
        "a group of angles as a function of time. With the -all option",
        "the first graph is the average, the rest are the individual angles.[PAR]",
        "With the -of option g_angle also calculates the fraction of trans",
        "dihedrals (only for dihedrals) as function of time, but this is",
        "probably only fun for a selected few.[PAR]",
        "With option -oc a dihedral correlation function is calculated.[PAR]",
        "It should be noted that the indexfile should contain",
        "atom-triples 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 PCA analysis using [TT]g_covar[tt]."
    };
    static char *opt[] = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
    static 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 || phi > 60."
        },
        {   "-avercorr", FALSE,  etBOOL, {&bAverCorr},
            "Average the correlation functions for the individual angles/dihedrals"
        }
    };
    static char *bugs[] = {
        "Counting transitions only works for dihedrals with multiplicity 3"
    };

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

    CopyRight(stderr,argv[0]);
    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs,pa);
    parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE,fnm,npargs,ppa,asize(desc),desc,asize(bugs),bugs);

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

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

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

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


    /* Check whether specific analysis has to be performed */
    bCorr=opt2bSet("-oc",NFILE,fnm);
    bAver=opt2bSet("-ov",NFILE,fnm);
    bTrans=opt2bSet("-ot",NFILE,fnm);
    bFrac=opt2bSet("-of",NFILE,fnm);

    if (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);

    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)");
        for(i=0; (i<nframes); i++) {
            fprintf(out,"%10.5f  %8.3f",time[i],aver_angle[i]*RAD2DEG);
            if (bALL) {
                for(j=0; (j<nangles); j++)
                    if (bPBC) {
                        real dd = dih[j][i];
                        fprintf(out,"  %8.3f",atan2(sin(dd),cos(dd))*RAD2DEG);
                    }
                    else
                        fprintf(out,"  %8.3f",dih[j][i]*RAD2DEG);
            }
            fprintf(out,"\n");
        }
        fclose(out);
    }
    if (opt2bSet("-or",NFILE,fnm))
        dump_dih_trn(nframes,nangles,dih,opt2fn("-or",NFILE,fnm),dt);

    if (bFrac) {
        sprintf(title,"Trans fraction: %s",grpname);
        out=xvgropen(opt2fn("-of",NFILE,fnm),
                     title,"Time (ps)","Fraction");
        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];
        }
        fclose(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[0],dt,bRb);

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

            if (bChandler) {
                real dval,sixty=DEG2RAD*60;
                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),"Dihedral Autocorrelation Function",
                        nframes,nangles,dih,dt,mode,bAverCorr);
        }
    }


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

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

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

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

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

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

    fclose(out);

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

    thanx(stderr);

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

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

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

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

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

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

  if (opt2bSet("-oa",NFILE,fnm)) {
    init_t_atoms(&outatoms,3*n,FALSE);
    outatoms.nr = 3*n;
    for(i=0; i<3*n; i++) {
      outatoms.atomname[i] = &anm;
      outatoms.atom[i].resnr = i/3;
      outatoms.resname[i/3] = &rnm;
    }
    fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
  } else
    fpdb = -1;
  
  read_first_frame(&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X); 
  
  do {
    rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
    calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
    t = convert_time(fr.time);
    fprintf(flen," %10g",t);
    fprintf(fdist," %10g",t);
    fprintf(fz," %10g",t);
    fprintf(ftilt," %10g",t);
    fprintf(ftiltr," %10g",t);
    fprintf(ftiltl," %10g",t);
    if (bKink) {
      fprintf(fkink," %10g",t);
      fprintf(fkinkr," %10g",t);
      fprintf(fkinkl," %10g",t);
    }

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

  close_trx(status);
  
  if (fpdb >= 0)
    close_trx(fpdb);
  fclose(flen);
  fclose(fdist);
  fclose(fz);
  fclose(ftilt);
  fclose(ftiltr);
  fclose(ftiltl);
  if (bKink) {
    fclose(fkink);
    fclose(fkinkr);
    fclose(fkinkl);
  }
  
  thanx(stderr);
  
  return 0;
}
Пример #11
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);
}
Пример #12
0
int gmx_gyrate(int argc,char *argv[])
{
  const char *desc[] = {
    "g_gyrate computes the radius of gyration of a group of atoms",
    "and the radii of gyration about the x, y and z axes,",
    "as a function of time. The atoms are explicitly mass weighted.[PAR]",
    "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
    "for multiple molecules by splitting the analysis group in equally",
    "sized parts.[PAR]",
    "With the option [TT]-nz[tt] 2D radii of gyration in the x-y plane",
    "of slices along the z-axis are calculated."
  };
  static int  nmol=1,nz=0;
  static bool bQ=FALSE,bRot=FALSE,bMOI=FALSE;
  t_pargs pa[] = {
    { "-nmol", FALSE, etINT, {&nmol},
      "The number of molecules to analyze" },
    { "-q", FALSE, etBOOL, {&bQ},
      "Use absolute value of the charge of an atom as weighting factor instead of mass" },
    { "-p", FALSE, etBOOL, {&bRot},
      "Calculate the radii of gyration about the principal axes." },
    { "-moi", FALSE, etBOOL, {&bMOI},
      "Calculate the moments of inertia (defined by the principal axes)." },
    { "-nz", FALSE, etINT, {&nz},
      "Calculate the 2D radii of gyration of # slices along the z-axis" },
  };
  FILE       *out;
  int        status;
  t_topology top;
  int        ePBC;
  rvec       *x,*x_s;
  rvec       xcm,gvec,gvec1;
  matrix     box,trans;
  bool       bACF;
  real       **moi_trans=NULL;
  int        max_moi=0,delta_moi=100;
  rvec       d,d1;         /* eigenvalues of inertia tensor */
  real       t,t0,tm,gyro;
  int        natoms;
  char       *grpname,title[256];
  int        i,j,m,gnx,nam,mol;
  atom_id    *index;
  char *leg[]  = { "Rg", "RgX", "RgY", "RgZ" }; 
  char *legI[] = { "Itot", "I1", "I2", "I3" }; 
#define NLEG asize(leg) 
  t_filenm fnm[] = {
    { efTRX, "-f",   NULL,       ffREAD }, 
    { efTPS, NULL,   NULL,       ffREAD },
    { efNDX, NULL,   NULL,       ffOPTRD },
    { efXVG, NULL,   "gyrate",   ffWRITE }, 
    { efXVG, "-acf", "moi-acf",  ffOPTWR },
  }; 
#define NFILE asize(fnm) 
  int     npargs;
  t_pargs *ppa;
  
  CopyRight(stderr,argv[0]);
  npargs = asize(pa);
  ppa    = add_acf_pargs(&npargs,pa);

  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
		    NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL); 
  bACF = opt2bSet("-acf",NFILE,fnm);
  if (bACF && nmol!=1)
    gmx_fatal(FARGS,"Can only do acf with nmol=1");
  bRot = bRot || bMOI || bACF;
  /*
    if (nz > 0)
    bMOI = TRUE;
  */
  if (bRot) {
    printf("Will rotate system along principal axes\n"); 
    snew(moi_trans,DIM);
  }
  if (bMOI) {
    printf("Will print moments of inertia\n");
    bQ = FALSE;
  }
  if (bQ) 
    printf("Will print radius normalised by charge\n"); 
    
  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,TRUE);
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);

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

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

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

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

  if (bACF) {
    int mode = eacVector;
  
    do_autocorr(opt2fn("-acf",NFILE,fnm),
		"Moment of inertia vector ACF",
		j,3,moi_trans,(t-t0)/j,mode,FALSE);
    do_view(opt2fn("-acf",NFILE,fnm),"-nxy");
  }
  
  do_view(ftp2fn(efXVG,NFILE,fnm),"-nxy");
  
  thanx(stderr);
  
  return 0;
}
Пример #13
0
void xvgr_view(FILE *out,real xmin,real ymin,real xmax,real ymax)
{
  if (bPrintXvgrCodes()) 
    fprintf(out,"@ view %g, %g, %g, %g\n",xmin,ymin,xmax,ymax);
}
Пример #14
0
void xvgr_subtitle(FILE *out,char *subtitle)
{
  if (bPrintXvgrCodes()) 
    fprintf(out,"@ subtitle \"%s\"\n",subtitle);
}
Пример #15
0
int gmx_sorient(int argc,char *argv[])
{
  t_topology top;
  int      ePBC;
  char     title[STRLEN];
  int      status;
  int      natoms;
  real     t;
  rvec     *xtop,*x;
  matrix   box;
  
  FILE    *fp;
  int     i,j,p,sa0,sa1,sa2,n,ntot,nf,m,*hist1,*hist2,*histn,nbin1,nbin2,nrbin;
  real    *histi1,*histi2,invbw,invrbw;
  double  sum1,sum2;
  int     *isize,nrefgrp,nrefat;
  atom_id **index;
  char    **grpname;
  real    inp,outp,two_pi,nav,normfac,rmin2,rmax2,rcut,rcut2,r2,r,mass,mtot;
  real    c1,c2;
  char    str[STRLEN];
  bool    bTPS;
  rvec    xref,dx,dxh1,dxh2,outer;
  t_pbc   pbc;
  char    *legr[] = { "<cos(\\8q\\4\\s1\\N)>", 
		      "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" };
  char    *legc[] = { "cos(\\8q\\4\\s1\\N)", 
		      "3cos\\S2\\N(\\8q\\4\\s2\\N)-1" };
  
  static char *desc[] = {
    "g_sorient analyzes solvent orientation around solutes.", 
    "It calculates two angles between the vector from one or more",
    "reference positions to the first atom of each solvent molecule:[BR]"
    "theta1: the angle with the vector from the first atom of the solvent",
    "molecule to the midpoint between atoms 2 and 3.[BR]",
    "theta2: the angle with the normal of the solvent plane, defined by the",
    "same three atoms, or when the option [TT]-v23[tt] is set",
    "the angle with the vector between atoms 2 and 3.[BR]",
    "The reference can be a set of atoms or",
    "the center of mass of a set of atoms. The group of solvent atoms should",
    "consist of 3 atoms per solvent molecule.",
    "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are",
    "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]",
    "[TT]-o[tt]: distribtion of cos(theta1) for rmin<=r<=rmax.[PAR]",
    "[TT]-no[tt]: distribution of cos(theta2) for rmin<=r<=rmax.[PAR]",
    "[TT]-ro[tt]: <cos(theta1)> and <3cos^2(theta2)-1> as a function of the",
    "distance.[PAR]",
    "[TT]-co[tt]: the sum over all solvent molecules within distance r",
    "of cos(theta1) and 3cos^2(theta2)-1 as a function of r.[PAR]",
    "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r"
  };
  
  static bool bCom = FALSE,bVec23=FALSE,bPBC = FALSE;
  static real rmin=0.0,rmax=0.5,binwidth=0.02,rbinw=0.02;
  t_pargs pa[] = {
    { "-com",  FALSE, etBOOL,  {&bCom},
      "Use the center of mass as the reference postion" },
    { "-v23",  FALSE, etBOOL,  {&bVec23},
      "Use the vector between atoms 2 and 3" },
    { "-rmin",  FALSE, etREAL, {&rmin}, "Minimum distance (nm)" },
    { "-rmax",  FALSE, etREAL, {&rmax}, "Maximum distance (nm)" },
    { "-cbin",  FALSE, etREAL, {&binwidth}, "Binwidth for the cosine" },
    { "-rbin",  FALSE, etREAL, {&rbinw}, "Binwidth for r (nm)" },
    { "-pbc",   FALSE, etBOOL, {&bPBC}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." }
  };
  
  t_filenm fnm[] = {
    { efTRX, NULL,  NULL,  ffREAD },
    { efTPS, NULL,  NULL,  ffREAD },
    { efNDX, NULL,  NULL,  ffOPTRD },
    { efXVG, NULL,  "sori.xvg",  ffWRITE },
    { efXVG, "-no", "snor.xvg",  ffWRITE },
    { efXVG, "-ro", "sord.xvg",  ffWRITE },
    { efXVG, "-co", "scum.xvg",  ffWRITE },
    { efXVG, "-rc", "scount.xvg",  ffWRITE }
  };
#define NFILE asize(fnm)

  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL);
  
  two_pi = 2/M_PI;

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

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

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

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

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

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

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

  invrbw = 1/rbinw;
  
  snew(hist1,nbin1+1);
  snew(hist2,nbin2+1);
  nrbin = rcut/rbinw;
  if (nrbin == 0)
    nrbin = 1;
  snew(histi1,nrbin);
  snew(histi2,nrbin);
  snew(histn,nrbin);

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

  /* start analysis of trajectory */
  do {
    if (bTPS) {
      /* make molecules whole again */
      rm_pbc(&top.idef,ePBC,natoms,box,x,x);
    }
    
    set_pbc(&pbc,ePBC,box);
    n    = 0;
    inp  = 0;
    outp = 0;
    for(p=0; (p<nrefgrp); p++) {
      if (bCom)
	calc_com_pbc(nrefat,&top,x,&pbc,index[0],xref,bPBC,box);
      else
	copy_rvec(x[index[0][p]],xref);

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

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

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

  /* Add the bin for the exact maximum to the previous bin */
  hist1[nbin1-1] += hist1[nbin1];
  hist2[nbin2-1] += hist2[nbin2];
  
  nav     = (real)ntot/(nrefgrp*nf);
  normfac = invbw/ntot;
  
  fprintf(stderr,  "Average nr of molecules between %g and %g nm: %.1f\n",
	  rmin,rmax,nav);
  if (ntot > 0) {
    sum1 /= ntot;
    sum2 /= ntot;
    fprintf(stderr,"Average cos(theta1)     between %g and %g nm: %6.3f\n",
	    rmin,rmax,sum1);
    fprintf(stderr,"Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n",
	    rmin,rmax,sum2);
  }
  
  sprintf(str,"Solvent orientation between %g and %g nm",rmin,rmax);
  fp=xvgropen(opt2fn("-o",NFILE,fnm), 
	      str,"cos(\\8q\\4\\s1\\N)",""); 
  if (bPrintXvgrCodes())
    fprintf(fp,"@ subtitle \"average shell size %.1f molecules\"\n",nav);
  for(i=0; i<nbin1; i++) {
    fprintf(fp,"%g %g\n",(i+0.5)*binwidth-1,2*normfac*hist1[i]);
  }
  fclose(fp);
  
  sprintf(str,"Solvent normal orientation between %g and %g nm",rmin,rmax);
  fp=xvgropen(opt2fn("-no",NFILE,fnm), 
	      str,"cos(\\8q\\4\\s2\\N)","");
  if (bPrintXvgrCodes())
    fprintf(fp,"@ subtitle \"average shell size %.1f molecules\"\n",nav);
  for(i=0; i<nbin2; i++) {
    fprintf(fp,"%g %g\n",(i+0.5)*binwidth,normfac*hist2[i]);
  }
  fclose(fp);

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

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

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

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

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

	cr = init_par(&argc,&argv);

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

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

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

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

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

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

  out=xvgropen(opt2fn("-of",NFILE,fnm), 
               "Eigenfrequencies","Eigenvector index","Wavenumber [cm\\S-1\\N]");
  if (bPrintXvgrCodes()) { 
    if (bM)
      fprintf(out,"@ subtitle \"mass weighted\"\n");
    else 
      fprintf(out,"@ subtitle \"not mass weighted\"\n");
  }
  
  /* Gromacs units are kJ/(mol*nm*nm*amu),
   * where amu is the atomic mass unit.
   *
   * For the eigenfrequencies we want to convert this to spectroscopic absorption
   * wavenumbers given in cm^(-1), which is the frequency divided by the speed of
   * light. Do this by first converting to omega^2 (units 1/s), take the square 
   * root, and finally divide by the speed of light (nm/ps in gromacs).   
   */
  factor_gmx_to_omega2       = 1.0E21/(AVOGADRO*AMU);
  factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT);  
    
  for (i=0; i<=(end-begin); i++)
  {
      value = eigenvalues[i];
      if(value < 0)
          value = 0;
      value=sqrt(value*factor_gmx_to_omega2)*factor_omega_to_wavenumber;
      fprintf (out,"%6d %15g\n",begin+i,value);
  }
  fclose(out);
  
  /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors 
   * were scaled back from mass weighted cartesian to plain cartesian in the
   * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors
   * will not be strictly orthogonal in plain cartesian scalar products.
   */   
  write_eigenvectors(opt2fn("-v",NFILE,fnm),natoms,eigenvectors,FALSE,begin,end,
                     eWXR_NO,NULL,FALSE,top_x,bM,eigenvalues);
  
  thanx(stderr);
  
  return 0;
}