Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxana / gmx_helix.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include <math.h>
42
43 #include "gromacs/fileio/confio.h"
44 #include "gmx_fatal.h"
45 #include "fitahx.h"
46 #include "gromacs/fileio/futil.h"
47 #include "gstat.h"
48 #include "hxprops.h"
49 #include "macros.h"
50 #include "gromacs/math/utilities.h"
51 #include "pbc.h"
52 #include "gromacs/fileio/tpxio.h"
53 #include "gromacs/fileio/trxio.h"
54 #include "physics.h"
55 #include "index.h"
56 #include "smalloc.h"
57 #include "gromacs/commandline/pargs.h"
58 #include <string.h>
59 #include "sysstuff.h"
60 #include "txtdump.h"
61 #include "typedefs.h"
62 #include "vec.h"
63 #include "xvgr.h"
64 #include "gmx_ana.h"
65
66 int gmx_helix(int argc, char *argv[])
67 {
68     const char        *desc[] = {
69         "[THISMODULE] computes all kinds of helix properties. First, the peptide",
70         "is checked to find the longest helical part, as determined by",
71         "hydrogen bonds and [GRK]phi[grk]/[GRK]psi[grk] angles.",
72         "That bit is fitted",
73         "to an ideal helix around the [IT]z[it]-axis and centered around the origin.",
74         "Then the following properties are computed:[PAR]",
75         "[BB]1.[bb] Helix radius (file [TT]radius.xvg[tt]). This is merely the",
76         "RMS deviation in two dimensions for all C[GRK]alpha[grk] atoms.",
77         "it is calculated as [SQRT]([SUM][sum][SUB]i[sub] (x^2(i)+y^2(i)))/N[sqrt] where N is the number",
78         "of backbone atoms. For an ideal helix the radius is 0.23 nm[BR]",
79         "[BB]2.[bb] Twist (file [TT]twist.xvg[tt]). The average helical angle per",
80         "residue is calculated. For an [GRK]alpha[grk]-helix it is 100 degrees,",
81         "for 3-10 helices it will be smaller, and ",
82         "for 5-helices it will be larger.[BR]",
83         "[BB]3.[bb] Rise per residue (file [TT]rise.xvg[tt]). The helical rise per",
84         "residue is plotted as the difference in [IT]z[it]-coordinate between C[GRK]alpha[grk]",
85         "atoms. For an ideal helix, this is 0.15 nm[BR]",
86         "[BB]4.[bb] Total helix length (file [TT]len-ahx.xvg[tt]). The total length",
87         "of the",
88         "helix in nm. This is simply the average rise (see above) times the",
89         "number of helical residues (see below).[BR]",
90         "[BB]5.[bb] Helix dipole, backbone only (file [TT]dip-ahx.xvg[tt]).[BR]",
91         "[BB]6.[bb] RMS deviation from ideal helix, calculated for the C[GRK]alpha[grk]",
92         "atoms only (file [TT]rms-ahx.xvg[tt]).[BR]",
93         "[BB]7.[bb] Average C[GRK]alpha[grk] - C[GRK]alpha[grk] dihedral angle (file [TT]phi-ahx.xvg[tt]).[BR]",
94         "[BB]8.[bb] Average [GRK]phi[grk] and [GRK]psi[grk] angles (file [TT]phipsi.xvg[tt]).[BR]",
95         "[BB]9.[bb] Ellipticity at 222 nm according to Hirst and Brooks.",
96         "[PAR]"
97     };
98     static gmx_bool    bCheck = FALSE, bFit = TRUE, bDBG = FALSE, bEV = FALSE;
99     static int         rStart = 0, rEnd = 0, r0 = 1;
100     t_pargs            pa []  = {
101         { "-r0", FALSE, etINT, {&r0},
102           "The first residue number in the sequence" },
103         { "-q",  FALSE, etBOOL, {&bCheck},
104           "Check at every step which part of the sequence is helical" },
105         { "-F",  FALSE, etBOOL, {&bFit},
106           "Toggle fit to a perfect helix" },
107         { "-db", FALSE, etBOOL, {&bDBG},
108           "Print debug info" },
109         { "-ev", FALSE, etBOOL, {&bEV},
110           "Write a new 'trajectory' file for ED" },
111         { "-ahxstart", FALSE, etINT, {&rStart},
112           "First residue in helix" },
113         { "-ahxend", FALSE, etINT, {&rEnd},
114           "Last residue in helix" }
115     };
116
117     typedef struct {
118         FILE       *fp, *fp2;
119         gmx_bool    bfp2;
120         const char *filenm;
121         const char *title;
122         const char *xaxis;
123         const char *yaxis;
124         real        val;
125     } t_xvgrfile;
126
127     t_xvgrfile     xf[efhNR] = {
128         { NULL, NULL, TRUE,  "radius",  "Helix radius",               NULL, "r (nm)", 0.0 },
129         { NULL, NULL, TRUE,  "twist",   "Twist per residue",          NULL, "Angle (deg)", 0.0 },
130         { NULL, NULL, TRUE,  "rise",    "Rise per residue",           NULL, "Rise (nm)", 0.0 },
131         { NULL, NULL, FALSE, "len-ahx", "Length of the Helix",        NULL, "Length (nm)", 0.0 },
132         { NULL, NULL, FALSE, "dip-ahx", "Helix Backbone Dipole",      NULL, "rq (nm e)", 0.0 },
133         { NULL, NULL, TRUE,  "rms-ahx", "RMS Deviation from Ideal Helix", NULL, "RMS (nm)", 0.0 },
134         { NULL, NULL, FALSE, "rmsa-ahx", "Average RMSD per Residue",   "Residue", "RMS (nm)", 0.0 },
135         { NULL, NULL, FALSE,  "cd222",   "Ellipticity at 222 nm", NULL, "nm", 0.0 },
136         { NULL, NULL, TRUE,  "pprms",   "RMS Distance from \\8a\\4-helix", NULL, "deg", 0.0 },
137         { NULL, NULL, TRUE,  "caphi",   "Average Ca-Ca Dihedral",     NULL, "\\8F\\4(deg)", 0.0 },
138         { NULL, NULL, TRUE,  "phi",     "Average \\8F\\4 angles", NULL, "deg", 0.0 },
139         { NULL, NULL, TRUE,  "psi",     "Average \\8Y\\4 angles", NULL, "deg", 0.0 },
140         { NULL, NULL, TRUE,  "hb3",     "Average n-n+3 hbond length", NULL, "nm", 0.0 },
141         { NULL, NULL, TRUE,  "hb4",     "Average n-n+4 hbond length", NULL, "nm", 0.0 },
142         { NULL, NULL, TRUE,  "hb5",     "Average n-n+5 hbond length", NULL, "nm", 0.0 },
143         { NULL, NULL, FALSE,  "JCaHa",   "J-Coupling Values",        "Residue", "Hz", 0.0 },
144         { NULL, NULL, FALSE,  "helicity", "Helicity per Residue",     "Residue", "% of time", 0.0 }
145     };
146
147     output_env_t   oenv;
148     char           buf[54];
149     t_trxstatus   *status;
150     int            natoms, nre, nres;
151     t_bb          *bb;
152     int            i, j, m, nall, nbb, nca, teller, nSel = 0;
153     atom_id       *bbindex, *caindex, *allindex;
154     t_topology    *top;
155     int            ePBC;
156     rvec          *x, *xref;
157     real           t;
158     real           rms;
159     matrix         box;
160     gmx_rmpbc_t    gpbc = NULL;
161     gmx_bool       bRange;
162     t_filenm       fnm[] = {
163         { efTPX, NULL,  NULL,   ffREAD  },
164         { efNDX, NULL,  NULL,   ffREAD  },
165         { efTRX, "-f",  NULL,   ffREAD  },
166         { efSTO, "-cz", "zconf", ffWRITE },
167     };
168 #define NFILE asize(fnm)
169
170     if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
171                            NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
172     {
173         return 0;
174     }
175
176     bRange = (opt2parg_bSet("-ahxstart", asize(pa), pa) &&
177               opt2parg_bSet("-ahxend", asize(pa), pa));
178
179     top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC);
180
181     natoms = read_first_x(oenv, &status, opt2fn("-f", NFILE, fnm), &t, &x, box);
182
183     if (natoms != top->atoms.nr)
184     {
185         gmx_fatal(FARGS, "Sorry can only run when the number of atoms in the run input file (%d) is equal to the number in the trajectory (%d)",
186                   top->atoms.nr, natoms);
187     }
188
189     bb = mkbbind(ftp2fn(efNDX, NFILE, fnm), &nres, &nbb, r0, &nall, &allindex,
190                  top->atoms.atomname, top->atoms.atom, top->atoms.resinfo);
191     snew(bbindex, natoms);
192     snew(caindex, nres);
193
194     fprintf(stderr, "nall=%d\n", nall);
195
196     /* Open output files, default x-axis is time */
197     for (i = 0; (i < efhNR); i++)
198     {
199         sprintf(buf, "%s.xvg", xf[i].filenm);
200         remove(buf);
201         xf[i].fp = xvgropen(buf, xf[i].title,
202                             xf[i].xaxis ? xf[i].xaxis : "Time (ps)",
203                             xf[i].yaxis, oenv);
204         if (xf[i].bfp2)
205         {
206             sprintf(buf, "%s.out", xf[i].filenm);
207             remove(buf);
208             xf[i].fp2 = gmx_ffopen(buf, "w");
209         }
210     }
211
212     /* Read reference frame from tpx file to compute helix length */
213     snew(xref, top->atoms.nr);
214     read_tpx(ftp2fn(efTPX, NFILE, fnm),
215              NULL, NULL, &natoms, xref, NULL, NULL, NULL);
216     calc_hxprops(nres, bb, xref);
217     do_start_end(nres, bb, &nbb, bbindex, &nca, caindex, bRange, rStart, rEnd);
218     sfree(xref);
219     if (bDBG)
220     {
221         fprintf(stderr, "nca=%d, nbb=%d\n", nca, nbb);
222         pr_bb(stdout, nres, bb);
223     }
224
225     gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
226
227     teller = 0;
228     do
229     {
230         if ((teller++ % 10) == 0)
231         {
232             fprintf(stderr, "\rt=%.2f", t);
233         }
234         gmx_rmpbc(gpbc, natoms, box, x);
235
236
237         calc_hxprops(nres, bb, x);
238         if (bCheck)
239         {
240             do_start_end(nres, bb, &nbb, bbindex, &nca, caindex, FALSE, 0, 0);
241         }
242
243         if (nca >= 5)
244         {
245             rms = fit_ahx(nres, bb, natoms, nall, allindex, x, nca, caindex, bFit);
246
247             if (teller == 1)
248             {
249                 write_sto_conf(opt2fn("-cz", NFILE, fnm), "Helix fitted to Z-Axis",
250                                &(top->atoms), x, NULL, ePBC, box);
251             }
252
253             xf[efhRAD].val   = radius(xf[efhRAD].fp2, nca, caindex, x);
254             xf[efhTWIST].val = twist(nca, caindex, x);
255             xf[efhRISE].val  = rise(nca, caindex, x);
256             xf[efhLEN].val   = ahx_len(nca, caindex, x);
257             xf[efhCD222].val = ellipticity(nres, bb);
258             xf[efhDIP].val   = dip(nbb, bbindex, x, top->atoms.atom);
259             xf[efhRMS].val   = rms;
260             xf[efhCPHI].val  = ca_phi(nca, caindex, x);
261             xf[efhPPRMS].val = pprms(xf[efhPPRMS].fp2, nres, bb);
262
263             for (j = 0; (j <= efhCPHI); j++)
264             {
265                 fprintf(xf[j].fp,   "%10g  %10g\n", t, xf[j].val);
266             }
267
268             av_phipsi(xf[efhPHI].fp, xf[efhPSI].fp, xf[efhPHI].fp2, xf[efhPSI].fp2,
269                       t, nres, bb);
270             av_hblen(xf[efhHB3].fp, xf[efhHB3].fp2,
271                      xf[efhHB4].fp, xf[efhHB4].fp2,
272                      xf[efhHB5].fp, xf[efhHB5].fp2,
273                      t, nres, bb);
274         }
275     }
276     while (read_next_x(oenv, status, &t, x, box));
277     fprintf(stderr, "\n");
278
279     gmx_rmpbc_done(gpbc);
280
281     close_trj(status);
282
283     for (i = 0; (i < nres); i++)
284     {
285         if (bb[i].nrms > 0)
286         {
287             fprintf(xf[efhRMSA].fp, "%10d  %10g\n", r0+i, bb[i].rmsa/bb[i].nrms);
288         }
289         fprintf(xf[efhAHX].fp, "%10d  %10g\n", r0+i, (bb[i].nhx*100.0)/(real )teller);
290         fprintf(xf[efhJCA].fp, "%10d  %10g\n",
291                 r0+i, 140.3+(bb[i].jcaha/(double)teller));
292     }
293
294     for (i = 0; (i < efhNR); i++)
295     {
296         gmx_ffclose(xf[i].fp);
297         if (xf[i].bfp2)
298         {
299             gmx_ffclose(xf[i].fp2);
300         }
301         do_view(oenv, xf[i].filenm, "-nxy");
302     }
303
304     return 0;
305 }