3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
69 static void rotate_ends(t_bundle *bun,rvec axis,int c0,int c1)
75 for(end=0; end<bun->nend; end++)
76 for(i=0; i<bun->n; i++) {
77 copy_rvec(bun->end[end][i],tmp);
78 bun->end[end][i][c0] = ax[c1]*tmp[c0] - ax[c0]*tmp[c1];
79 bun->end[end][i][c1] = ax[c0]*tmp[c0] + ax[c1]*tmp[c1];
82 axis[c0] = ax[c1]*tmp[c0] - ax[c0]*tmp[c1];
83 axis[c1] = ax[c0]*tmp[c0] + ax[c1]*tmp[c1];
86 static void calc_axes(rvec x[],t_atom atom[],int gnx[],atom_id *index[],
87 gmx_bool bRot,t_bundle *bun)
91 rvec axis[MAX_ENDS],cent;
95 for(end=0; end<bun->nend; end++) {
96 for(i=0; i<bun->n; i++) {
97 clear_rvec(bun->end[end][i]);
100 div = gnx[end]/bun->n;
101 for(i=0; i<gnx[end]; i++) {
102 m = atom[index[end][i]].m;
104 bun->end[end][i/div][d] += m*x[index[end][i]][d];
107 clear_rvec(axis[end]);
108 for(i=0; i<bun->n; i++) {
109 svmul(1.0/mtot[i],bun->end[end][i],bun->end[end][i]);
110 rvec_inc(axis[end],bun->end[end][i]);
112 svmul(1.0/bun->n,axis[end],axis[end]);
116 rvec_add(axis[0],axis[1],cent);
117 svmul(0.5,cent,cent);
118 /* center the bundle on the origin */
119 for(end=0; end<bun->nend; end++) {
120 rvec_dec(axis[end],cent);
121 for(i=0; i<bun->n; i++)
122 rvec_dec(bun->end[end][i],cent);
125 /* rotate the axis parallel to the z-axis */
126 rotate_ends(bun,axis[0],YY,ZZ);
127 rotate_ends(bun,axis[0],XX,ZZ);
129 for(i=0; i<bun->n; i++) {
130 rvec_add(bun->end[0][i],bun->end[1][i],bun->mid[i]);
131 svmul(0.5,bun->mid[i],bun->mid[i]);
132 rvec_sub(bun->end[0][i],bun->end[1][i],bun->dir[i]);
133 bun->len[i] = norm(bun->dir[i]);
134 unitv(bun->dir[i],bun->dir[i]);
138 static void dump_axes(t_trxstatus *status,t_trxframe *fr,t_atoms *outat,
142 static rvec *xout=NULL;
146 snew(xout,outat->nr);
148 for(i=0; i<bun->n; i++) {
149 copy_rvec(bun->end[0][i],xout[3*i]);
151 copy_rvec(bun->end[2][i],xout[3*i+1]);
153 copy_rvec(bun->mid[i],xout[3*i+1]);
154 copy_rvec(bun->end[1][i],xout[3*i+2]);
161 frout.natoms = outat->nr;
164 write_trxframe(status,&frout,NULL);
167 int gmx_bundle(int argc,char *argv[])
169 const char *desc[] = {
170 "g_bundle analyzes bundles of axes. The axes can be for instance",
171 "helix axes. The program reads two index groups and divides both",
172 "of them in [TT]-na[tt] parts. The centers of mass of these parts",
173 "define the tops and bottoms of the axes.",
174 "Several quantities are written to file:",
175 "the axis length, the distance and the z-shift of the axis mid-points",
176 "with respect to the average center of all axes, the total tilt,",
177 "the radial tilt and the lateral tilt with respect to the average axis.",
179 "With options [TT]-ok[tt], [TT]-okr[tt] and [TT]-okl[tt] the total,",
180 "radial and lateral kinks of the axes are plotted. An extra index",
181 "group of kink atoms is required, which is also divided into [TT]-na[tt]",
182 "parts. The kink angle is defined as the angle between the kink-top and",
183 "the bottom-kink vectors.",
185 "With option [TT]-oa[tt] the top, mid (or kink when [TT]-ok[tt] is set)",
186 "and bottom points of each axis",
187 "are written to a pdb file each frame. The residue numbers correspond",
188 "to the axis numbers. When viewing this file with [TT]rasmol[tt], use the",
189 "command line option [TT]-nmrpdb[tt], and type [TT]set axis true[tt] to",
190 "display the reference axis."
193 static gmx_bool bZ=FALSE;
195 { "-na", FALSE, etINT, {&n},
197 { "-z", FALSE, etBOOL, {&bZ},
198 "Use the Z-axis as reference iso the average axis" }
200 FILE *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl;
201 FILE *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL;
212 char *grpname[MAX_ENDS],title[256];
213 /* FIXME: The constness should not be cast away */
214 char *anm=(char *)"CA",*rnm=(char *)"GLY";
215 int i,j,gnx[MAX_ENDS];
216 atom_id *index[MAX_ENDS];
221 gmx_rmpbc_t gpbc=NULL;
223 #define NLEG asize(leg)
225 { efTRX, "-f", NULL, ffREAD },
226 { efTPS, NULL, NULL, ffREAD },
227 { efNDX, NULL, NULL, ffOPTRD },
228 { efXVG, "-ol", "bun_len", ffWRITE },
229 { efXVG, "-od", "bun_dist", ffWRITE },
230 { efXVG, "-oz", "bun_z", ffWRITE },
231 { efXVG, "-ot", "bun_tilt", ffWRITE },
232 { efXVG, "-otr", "bun_tiltr", ffWRITE },
233 { efXVG, "-otl", "bun_tiltl", ffWRITE },
234 { efXVG, "-ok", "bun_kink", ffOPTWR },
235 { efXVG, "-okr", "bun_kinkr", ffOPTWR },
236 { efXVG, "-okl", "bun_kinkl", ffOPTWR },
237 { efPDB, "-oa", "axes", ffOPTWR }
239 #define NFILE asize(fnm)
241 CopyRight(stderr,argv[0]);
242 parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE,
243 NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
245 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,TRUE);
247 bKink = opt2bSet("-ok",NFILE,fnm) || opt2bSet("-okr",NFILE,fnm)
248 || opt2bSet("-okl",NFILE,fnm);
254 fprintf(stderr,"Select a group of top and a group of bottom ");
256 fprintf(stderr,"and a group of kink ");
257 fprintf(stderr,"atoms\n");
258 get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),bun.nend,
261 if (n<=0 || gnx[0] % n || gnx[1] % n || (bKink && gnx[2] % n))
263 "The size of one of your index groups is not a multiple of n");
273 flen = xvgropen(opt2fn("-ol",NFILE,fnm),"Axis lengths",
274 output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
275 fdist = xvgropen(opt2fn("-od",NFILE,fnm),"Distance of axis centers",
276 output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
277 fz = xvgropen(opt2fn("-oz",NFILE,fnm),"Z-shift of axis centers",
278 output_env_get_xvgr_tlabel(oenv),"(nm)",oenv);
279 ftilt = xvgropen(opt2fn("-ot",NFILE,fnm),"Axis tilts",
280 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
281 ftiltr = xvgropen(opt2fn("-otr",NFILE,fnm),"Radial axis tilts",
282 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
283 ftiltl = xvgropen(opt2fn("-otl",NFILE,fnm),"Lateral axis tilts",
284 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
287 fkink = xvgropen(opt2fn("-ok",NFILE,fnm),"Kink angles",
288 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
289 fkinkr = xvgropen(opt2fn("-okr",NFILE,fnm),"Radial kink angles",
290 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
291 if (output_env_get_print_xvgr_codes(oenv))
292 fprintf(fkinkr,"@ subtitle \"+ = ) ( - = ( )\"\n");
293 fkinkl = xvgropen(opt2fn("-okl",NFILE,fnm),"Lateral kink angles",
294 output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv);
297 if (opt2bSet("-oa",NFILE,fnm)) {
298 init_t_atoms(&outatoms,3*n,FALSE);
300 for(i=0; i<3*n; i++) {
301 outatoms.atomname[i] = &anm;
302 outatoms.atom[i].resind = i/3;
303 outatoms.resinfo[i/3].name = &rnm;
304 outatoms.resinfo[i/3].nr = i/3 + 1;
305 outatoms.resinfo[i/3].ic = ' ';
307 fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
311 read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X);
312 gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
315 gmx_rmpbc_trxfr(gpbc,&fr);
316 calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
317 t = output_env_conv_time(oenv,fr.time);
318 fprintf(flen," %10g",t);
319 fprintf(fdist," %10g",t);
320 fprintf(fz," %10g",t);
321 fprintf(ftilt," %10g",t);
322 fprintf(ftiltr," %10g",t);
323 fprintf(ftiltl," %10g",t);
325 fprintf(fkink," %10g",t);
326 fprintf(fkinkr," %10g",t);
327 fprintf(fkinkl," %10g",t);
330 for(i=0; i<bun.n; i++) {
331 fprintf(flen," %6g",bun.len[i]);
332 fprintf(fdist," %6g",norm(bun.mid[i]));
333 fprintf(fz," %6g",bun.mid[i][ZZ]);
334 fprintf(ftilt," %6g",RAD2DEG*acos(bun.dir[i][ZZ]));
335 comp = bun.mid[i][XX]*bun.dir[i][XX]+bun.mid[i][YY]*bun.dir[i][YY];
336 fprintf(ftiltr," %6g",RAD2DEG*
337 asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
338 comp = bun.mid[i][YY]*bun.dir[i][XX]-bun.mid[i][XX]*bun.dir[i][YY];
339 fprintf(ftiltl," %6g",RAD2DEG*
340 asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
342 rvec_sub(bun.end[0][i],bun.end[2][i],va);
343 rvec_sub(bun.end[2][i],bun.end[1][i],vb);
344 unitv_no_table(va,va);
345 unitv_no_table(vb,vb);
346 fprintf(fkink," %6g",RAD2DEG*acos(iprod(va,vb)));
348 copy_rvec(bun.mid[i],vr);
350 unitv_no_table(vr,vr);
351 fprintf(fkinkr," %6g",RAD2DEG*asin(iprod(vc,vr)));
355 fprintf(fkinkl," %6g",RAD2DEG*asin(iprod(vc,vl)));
362 fprintf(ftiltr,"\n");
363 fprintf(ftiltl,"\n");
366 fprintf(fkinkr,"\n");
367 fprintf(fkinkl,"\n");
370 dump_axes(fpdb,&fr,&outatoms,&bun);
371 } while(read_next_frame(oenv,status,&fr));
372 gmx_rmpbc_done(gpbc);