/*! * \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); } }
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); } }
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); }
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); }
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"); } }
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]); } } }
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; }
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); }
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; }
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; }
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); }
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; }
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); }
void xvgr_subtitle(FILE *out,char *subtitle) { if (bPrintXvgrCodes()) fprintf(out,"@ subtitle \"%s\"\n",subtitle); }
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; }
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; }