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