2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017, 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.
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.
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.
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.
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.
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.
45 #include "gromacs/commandline/pargs.h"
46 #include "gromacs/commandline/viewit.h"
47 #include "gromacs/correlationfunctions/autocorr.h"
48 #include "gromacs/fileio/confio.h"
49 #include "gromacs/fileio/matio.h"
50 #include "gromacs/fileio/pdbio.h"
51 #include "gromacs/fileio/xvgr.h"
52 #include "gromacs/gmxana/gmx_ana.h"
53 #include "gromacs/gmxana/gstat.h"
54 #include "gromacs/math/units.h"
55 #include "gromacs/math/utilities.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/topology/residuetypes.h"
58 #include "gromacs/topology/topology.h"
59 #include "gromacs/utility/arraysize.h"
60 #include "gromacs/utility/cstringutil.h"
61 #include "gromacs/utility/fatalerror.h"
62 #include "gromacs/utility/futil.h"
63 #include "gromacs/utility/smalloc.h"
65 static gmx_bool bAllowed(real phi, real psi)
67 static const char *map[] = {
68 "1100000000000000001111111000000000001111111111111111111111111",
69 "1100000000000000001111110000000000011111111111111111111111111",
70 "1100000000000000001111110000000000011111111111111111111111111",
71 "1100000000000000001111100000000000111111111111111111111111111",
72 "1100000000000000001111100000000000111111111111111111111111111",
73 "1100000000000000001111100000000001111111111111111111111111111",
74 "1100000000000000001111100000000001111111111111111111111111111",
75 "1100000000000000001111100000000011111111111111111111111111111",
76 "1110000000000000001111110000000111111111111111111111111111111",
77 "1110000000000000001111110000001111111111111111111111111111111",
78 "1110000000000000001111111000011111111111111111111111111111111",
79 "1110000000000000001111111100111111111111111111111111111111111",
80 "1110000000000000001111111111111111111111111111111111111111111",
81 "1110000000000000001111111111111111111111111111111111111111111",
82 "1110000000000000001111111111111111111111111111111111111111111",
83 "1110000000000000001111111111111111111111111111111111111111111",
84 "1110000000000000001111111111111110011111111111111111111111111",
85 "1110000000000000001111111111111100000111111111111111111111111",
86 "1110000000000000001111111111111000000000001111111111111111111",
87 "1100000000000000001111111111110000000000000011111111111111111",
88 "1100000000000000001111111111100000000000000011111111111111111",
89 "1000000000000000001111111111000000000000000001111111111111110",
90 "0000000000000000001111111110000000000000000000111111111111100",
91 "0000000000000000000000000000000000000000000000000000000000000",
92 "0000000000000000000000000000000000000000000000000000000000000",
93 "0000000000000000000000000000000000000000000000000000000000000",
94 "0000000000000000000000000000000000000000000000000000000000000",
95 "0000000000000000000000000000000000000000000000000000000000000",
96 "0000000000000000000000000000000000000000000000000000000000000",
97 "0000000000000000000000000000000000000000000000000000000000000",
98 "0000000000000000000000000000000000000000000000000000000000000",
99 "0000000000000000000000000000000000000000000000000000000000000",
100 "0000000000000000000000000000000000000000000000000000000000000",
101 "0000000000000000000000000000000000000000000000000000000000000",
102 "0000000000000000000000000000000000000000000000000000000000000",
103 "0000000000000000000000000000000000000000000000000000000000000",
104 "0000000000000000000000000000000000000000000000000000000000000",
105 "0000000000000000000000000000000000000000000000000000000000000",
106 "0000000000000000000000000000000000111111111111000000000000000",
107 "1100000000000000000000000000000001111111111111100000000000111",
108 "1100000000000000000000000000000001111111111111110000000000111",
109 "0000000000000000000000000000000000000000000000000000000000000",
110 "0000000000000000000000000000000000000000000000000000000000000",
111 "0000000000000000000000000000000000000000000000000000000000000",
112 "0000000000000000000000000000000000000000000000000000000000000",
113 "0000000000000000000000000000000000000000000000000000000000000",
114 "0000000000000000000000000000000000000000000000000000000000000",
115 "0000000000000000000000000000000000000000000000000000000000000",
116 "0000000000000000000000000000000000000000000000000000000000000",
117 "0000000000000000000000000000000000000000000000000000000000000",
118 "0000000000000000000000000000000000000000000000000000000000000",
119 "0000000000000000000000000000000000000000000000000000000000000",
120 "0000000000000000000000000000000000000000000000000000000000000",
121 "0000000000000000000000000000000000000000000000000000000000000",
122 "0000000000000000000000000000000000000000000000000000000000000",
123 "0000000000000000000000000000000000000000000000000000000000000",
124 "0000000000000000000000000000000000000000000000000000000000000",
125 "0000000000000000000000000000000000000000000000000000000000000",
126 "0000000000000000000000000000000000000000000000000000000000000",
127 "0000000000000000000000000000000000000000000000000000000000000",
128 "0000000000000000000000000000000000000000000000000000000000000"
130 #define NPP asize(map)
133 #define INDEX(ppp) (((static_cast<int> (360+ppp*RAD2DEG)) % 360)/6)
138 return (map[x][y] == '1') ? TRUE : FALSE;
141 int *make_chi_ind(int nl, t_dlist dl[], int *ndih)
146 /* There are nl residues with max edMax dihedrals with 4 atoms each */
147 snew(id, nl*edMax*4);
150 for (i = 0; (i < nl); i++)
152 /* Phi, fake the first one */
153 dl[i].j0[edPhi] = n/4;
154 if (dl[i].atm.minC >= 0)
156 id[n++] = dl[i].atm.minC;
160 id[n++] = dl[i].atm.H;
162 id[n++] = dl[i].atm.N;
163 id[n++] = dl[i].atm.Cn[1];
164 id[n++] = dl[i].atm.C;
166 for (i = 0; (i < nl); i++)
168 /* Psi, fake the last one */
169 dl[i].j0[edPsi] = n/4;
170 id[n++] = dl[i].atm.N;
171 id[n++] = dl[i].atm.Cn[1];
172 id[n++] = dl[i].atm.C;
175 id[n++] = dl[i+1].atm.N;
179 id[n++] = dl[i].atm.O;
182 for (i = 1; (i < nl); i++)
185 if (has_dihedral(edOmega, &(dl[i])))
187 dl[i].j0[edOmega] = n/4;
188 id[n++] = dl[i].atm.minCalpha;
189 id[n++] = dl[i].atm.minC;
190 id[n++] = dl[i].atm.N;
191 id[n++] = dl[i].atm.Cn[1];
194 for (Xi = 0; (Xi < MAXCHI); Xi++)
197 for (i = 0; (i < nl); i++)
199 if (dl[i].atm.Cn[Xi+3] != -1)
201 dl[i].j0[edChi1+Xi] = n/4;
202 id[n++] = dl[i].atm.Cn[Xi];
203 id[n++] = dl[i].atm.Cn[Xi+1];
204 id[n++] = dl[i].atm.Cn[Xi+2];
205 id[n++] = dl[i].atm.Cn[Xi+3];
214 int bin(real chi, int mult)
218 return static_cast<int>(chi*mult/360.0);
222 static void do_dihcorr(const char *fn, int nf, int ndih, real **dih, real dt,
223 int nlist, t_dlist dlist[], real time[], int maxchi,
224 gmx_bool bPhi, gmx_bool bPsi, gmx_bool bChi, gmx_bool bOmega,
225 const gmx_output_env_t *oenv)
227 char name1[256], name2[256];
230 do_autocorr(fn, oenv, "Dihedral Autocorrelation Function",
231 nf, ndih, dih, dt, eacCos, FALSE);
234 for (i = 0; (i < nlist); i++)
238 print_one(oenv, "corrphi", dlist[i].name, "Phi ACF for", "C(t)", nf/2, time,
243 for (i = 0; (i < nlist); i++)
247 print_one(oenv, "corrpsi", dlist[i].name, "Psi ACF for", "C(t)", nf/2, time,
252 for (i = 0; (i < nlist); i++)
254 if (has_dihedral(edOmega, &dlist[i]))
258 print_one(oenv, "corromega", dlist[i].name, "Omega ACF for", "C(t)",
264 for (Xi = 0; (Xi < maxchi); Xi++)
266 sprintf(name1, "corrchi%d", Xi+1);
267 sprintf(name2, "Chi%d ACF for", Xi+1);
268 for (i = 0; (i < nlist); i++)
270 if (dlist[i].atm.Cn[Xi+3] != -1)
274 print_one(oenv, name1, dlist[i].name, name2, "C(t)", nf/2, time, dih[j]);
280 fprintf(stderr, "\n");
283 static void copy_dih_data(real in[], real out[], int nf, gmx_bool bLEAVE)
285 /* if bLEAVE, do nothing to data in copying to out
286 * otherwise multiply by 180/pi to convert rad to deg */
297 for (i = 0; (i < nf); i++)
303 static void dump_em_all(int nlist, t_dlist dlist[], int nf, real time[],
304 real **dih, int maxchi,
305 gmx_bool bPhi, gmx_bool bPsi, gmx_bool bChi, gmx_bool bOmega, gmx_bool bRAD,
306 const gmx_output_env_t *oenv)
308 char name[256], titlestr[256], ystr[256];
315 std::strcpy(ystr, "Angle (rad)");
319 std::strcpy(ystr, "Angle (degrees)");
324 for (i = 0; (i < nlist); i++)
326 /* grs debug printf("OK i %d j %d\n", i, j) ; */
329 copy_dih_data(dih[j], data, nf, bRAD);
330 print_one(oenv, "phi", dlist[i].name, "\\xf\\f{}", ystr, nf, time, data);
334 for (i = 0; (i < nlist); i++)
338 copy_dih_data(dih[j], data, nf, bRAD);
339 print_one(oenv, "psi", dlist[i].name, "\\xy\\f{}", ystr, nf, time, data);
343 for (i = 0; (i < nlist); i++)
345 if (has_dihedral(edOmega, &(dlist[i])))
349 copy_dih_data(dih[j], data, nf, bRAD);
350 print_one(oenv, "omega", dlist[i].name, "\\xw\\f{}", ystr, nf, time, data);
356 for (Xi = 0; (Xi < maxchi); Xi++)
358 for (i = 0; (i < nlist); i++)
360 if (dlist[i].atm.Cn[Xi+3] != -1)
364 sprintf(name, "chi%d", Xi+1);
365 sprintf(titlestr, "\\xc\\f{}\\s%d\\N", Xi+1);
366 copy_dih_data(dih[j], data, nf, bRAD);
367 print_one(oenv, name, dlist[i].name, titlestr, ystr, nf, time, data);
373 fprintf(stderr, "\n");
376 static void reset_one(real dih[], int nf, real phase)
380 for (j = 0; (j < nf); j++)
383 while (dih[j] < -M_PI)
387 while (dih[j] >= M_PI)
394 static int reset_em_all(int nlist, t_dlist dlist[], int nf,
395 real **dih, int maxchi)
402 for (i = 0; (i < nlist); i++)
404 if (dlist[i].atm.minC == -1)
406 reset_one(dih[j++], nf, M_PI);
410 reset_one(dih[j++], nf, 0);
414 for (i = 0; (i < nlist-1); i++)
416 reset_one(dih[j++], nf, 0);
418 /* last Psi is faked from O */
419 reset_one(dih[j++], nf, M_PI);
422 for (i = 0; (i < nlist); i++)
424 if (has_dihedral(edOmega, &dlist[i]))
426 reset_one(dih[j++], nf, 0);
429 /* Chi 1 thru maxchi */
430 for (Xi = 0; (Xi < maxchi); Xi++)
432 for (i = 0; (i < nlist); i++)
434 if (dlist[i].atm.Cn[Xi+3] != -1)
436 reset_one(dih[j], nf, 0);
441 fprintf(stderr, "j after resetting (nr. active dihedrals) = %d\n", j);
445 static void histogramming(FILE *log, int nbin, gmx_residuetype_t *rt,
446 int nf, int maxchi, real **dih,
447 int nlist, t_dlist dlist[],
449 gmx_bool bPhi, gmx_bool bPsi, gmx_bool bOmega, gmx_bool bChi,
450 gmx_bool bNormalize, gmx_bool bSSHisto, const char *ssdump,
451 real bfac_max, const t_atoms *atoms,
452 gmx_bool bDo_jc, const char *fn,
453 const gmx_output_env_t *oenv)
455 /* also gets 3J couplings and order parameters S2 */
456 // Avoid warnings about narrowing conversions from double to real
458 #pragma warning(disable: 4838)
460 t_karplus kkkphi[] = {
461 { "J_NHa1", 6.51, -1.76, 1.6, -M_PI/3, 0.0, 0.0 },
462 { "J_NHa2", 6.51, -1.76, 1.6, M_PI/3, 0.0, 0.0 },
463 { "J_HaC'", 4.0, 1.1, 0.1, 0.0, 0.0, 0.0 },
464 { "J_NHCb", 4.7, -1.5, -0.2, M_PI/3, 0.0, 0.0 },
465 { "J_Ci-1Hai", 4.5, -1.3, -1.2, 2*M_PI/3, 0.0, 0.0 }
467 t_karplus kkkpsi[] = {
468 { "J_HaN", -0.88, -0.61, -0.27, M_PI/3, 0.0, 0.0 }
470 t_karplus kkkchi1[] = {
471 { "JHaHb2", 9.5, -1.6, 1.8, -M_PI/3, 0, 0.0 },
472 { "JHaHb3", 9.5, -1.6, 1.8, 0, 0, 0.0 }
475 #pragma warning(default: 4838)
477 #define NKKKPHI asize(kkkphi)
478 #define NKKKPSI asize(kkkpsi)
479 #define NKKKCHI asize(kkkchi1)
480 #define NJC (NKKKPHI+NKKKPSI+NKKKCHI)
482 FILE *fp, *ssfp[3] = {nullptr, nullptr, nullptr};
483 const char *sss[3] = { "sheet", "helix", "coil" };
487 int ****his_aa_ss = nullptr;
488 int ***his_aa, *histmp;
489 int i, j, k, m, n, nn, Dih, nres, hindex, angle;
490 gmx_bool bBfac, bOccup;
491 char hisfile[256], hhisfile[256], sshisfile[256], title[256], *ss_str = nullptr;
493 const char *residue_name;
496 rt_size = gmx_residuetype_get_size(rt);
499 fp = gmx_ffopen(ssdump, "r");
500 if (1 != fscanf(fp, "%d", &nres))
502 gmx_fatal(FARGS, "Error reading from file %s", ssdump);
505 snew(ss_str, nres+1);
506 if (1 != fscanf(fp, "%s", ss_str))
508 gmx_fatal(FARGS, "Error reading from file %s", ssdump);
512 /* Four dimensional array... Very cool */
514 for (i = 0; (i < 3); i++)
516 snew(his_aa_ss[i], rt_size+1);
517 for (j = 0; (j <= rt_size); j++)
519 snew(his_aa_ss[i][j], edMax);
520 for (Dih = 0; (Dih < edMax); Dih++)
522 snew(his_aa_ss[i][j][Dih], nbin+1);
528 for (Dih = 0; (Dih < edMax); Dih++)
530 snew(his_aa[Dih], rt_size+1);
531 for (i = 0; (i <= rt_size); i++)
533 snew(his_aa[Dih][i], nbin+1);
540 for (i = 0; (i < nlist); i++)
548 for (Dih = 0; (Dih < NONCHI+maxchi); Dih++)
550 for (i = 0; (i < nlist); i++)
552 if (((Dih < edOmega) ) ||
553 ((Dih == edOmega) && (has_dihedral(edOmega, &(dlist[i])))) ||
554 ((Dih > edOmega) && (dlist[i].atm.Cn[Dih-NONCHI+3] != -1)))
556 make_histo(log, nf, dih[j], nbin, histmp, -M_PI, M_PI);
560 /* Assume there is only one structure, the first.
561 * Compute index in histogram.
563 /* Check the atoms to see whether their B-factors are low enough
564 * Check atoms to see their occupancy is 1.
566 bBfac = bOccup = TRUE;
567 for (nn = 0; (nn < 4); nn++, n++)
569 bBfac = bBfac && (atoms->pdbinfo[index[n]].bfac <= bfac_max);
570 bOccup = bOccup && (atoms->pdbinfo[index[n]].occup == 1);
572 if (bOccup && ((bfac_max <= 0) || bBfac))
574 hindex = static_cast<int>(((dih[j][0]+M_PI)*nbin)/(2*M_PI));
575 range_check(hindex, 0, nbin);
577 /* Assign dihedral to either of the structure determined
580 switch (ss_str[dlist[i].resnr])
583 his_aa_ss[0][dlist[i].index][Dih][hindex]++;
586 his_aa_ss[1][dlist[i].index][Dih][hindex]++;
589 his_aa_ss[2][dlist[i].index][Dih][hindex]++;
595 fprintf(debug, "Res. %d has imcomplete occupancy or bfacs > %g\n",
596 dlist[i].resnr, bfac_max);
607 calc_distribution_props(nbin, histmp, -M_PI, NKKKPHI, kkkphi, &S2);
609 for (m = 0; (m < NKKKPHI); m++)
611 Jc[i][m] = kkkphi[m].Jc;
612 Jcsig[i][m] = kkkphi[m].Jcsig;
616 calc_distribution_props(nbin, histmp, -M_PI, NKKKPSI, kkkpsi, &S2);
618 for (m = 0; (m < NKKKPSI); m++)
620 Jc[i][NKKKPHI+m] = kkkpsi[m].Jc;
621 Jcsig[i][NKKKPHI+m] = kkkpsi[m].Jcsig;
625 calc_distribution_props(nbin, histmp, -M_PI, NKKKCHI, kkkchi1, &S2);
626 for (m = 0; (m < NKKKCHI); m++)
628 Jc[i][NKKKPHI+NKKKPSI+m] = kkkchi1[m].Jc;
629 Jcsig[i][NKKKPHI+NKKKPSI+m] = kkkchi1[m].Jcsig;
632 default: /* covers edOmega and higher Chis than Chi1 */
633 calc_distribution_props(nbin, histmp, -M_PI, 0, nullptr, &S2);
636 dlist[i].S2[Dih] = S2;
638 /* Sum distribution per amino acid type as well */
639 for (k = 0; (k < nbin); k++)
641 his_aa[Dih][dlist[i].index][k] += histmp[k];
646 else /* dihed not defined */
648 dlist[i].S2[Dih] = 0.0;
654 /* Print out Jcouplings */
655 fprintf(log, "\n *** J-Couplings from simulation (plus std. dev.) ***\n\n");
656 fprintf(log, "Residue ");
657 for (i = 0; (i < NKKKPHI); i++)
659 fprintf(log, "%7s SD", kkkphi[i].name);
661 for (i = 0; (i < NKKKPSI); i++)
663 fprintf(log, "%7s SD", kkkpsi[i].name);
665 for (i = 0; (i < NKKKCHI); i++)
667 fprintf(log, "%7s SD", kkkchi1[i].name);
670 for (i = 0; (i < NJC+1); i++)
672 fprintf(log, "------------");
675 for (i = 0; (i < nlist); i++)
677 fprintf(log, "%-10s", dlist[i].name);
678 for (j = 0; (j < NJC); j++)
680 fprintf(log, " %5.2f %4.2f", Jc[i][j], Jcsig[i][j]);
686 /* and to -jc file... */
689 fp = xvgropen(fn, "\\S3\\NJ-Couplings from Karplus Equation", "Residue",
692 for (i = 0; (i < NKKKPHI); i++)
694 leg[i] = gmx_strdup(kkkphi[i].name);
696 for (i = 0; (i < NKKKPSI); i++)
698 leg[i+NKKKPHI] = gmx_strdup(kkkpsi[i].name);
700 for (i = 0; (i < NKKKCHI); i++)
702 leg[i+NKKKPHI+NKKKPSI] = gmx_strdup(kkkchi1[i].name);
704 xvgr_legend(fp, NJC, (const char**)leg, oenv);
705 fprintf(fp, "%5s ", "#Res.");
706 for (i = 0; (i < NJC); i++)
708 fprintf(fp, "%10s ", leg[i]);
711 for (i = 0; (i < nlist); i++)
713 fprintf(fp, "%5d ", dlist[i].resnr);
714 for (j = 0; (j < NJC); j++)
716 fprintf(fp, " %8.3f", Jc[i][j]);
721 for (i = 0; (i < NJC); i++)
726 /* finished -jc stuff */
728 snew(normhisto, nbin);
729 for (i = 0; (i < rt_size); i++)
731 for (Dih = 0; (Dih < edMax); Dih++)
733 /* First check whether something is in there */
734 for (j = 0; (j < nbin); j++)
736 if (his_aa[Dih][i][j] != 0)
742 ((bPhi && (Dih == edPhi)) ||
743 (bPsi && (Dih == edPsi)) ||
744 (bOmega && (Dih == edOmega)) ||
745 (bChi && (Dih >= edChi1))))
749 normalize_histo(nbin, his_aa[Dih][i], (360.0/nbin), normhisto);
752 residue_name = gmx_residuetype_get_name(rt, i);
756 sprintf(hisfile, "histo-phi%s", residue_name);
757 sprintf(title, "\\xf\\f{} Distribution for %s", residue_name);
760 sprintf(hisfile, "histo-psi%s", residue_name);
761 sprintf(title, "\\xy\\f{} Distribution for %s", residue_name);
764 sprintf(hisfile, "histo-omega%s", residue_name);
765 sprintf(title, "\\xw\\f{} Distribution for %s", residue_name);
768 sprintf(hisfile, "histo-chi%d%s", Dih-NONCHI+1, residue_name);
769 sprintf(title, "\\xc\\f{}\\s%d\\N Distribution for %s",
770 Dih-NONCHI+1, residue_name);
772 std::strcpy(hhisfile, hisfile);
773 std::strcat(hhisfile, ".xvg");
774 fp = xvgropen(hhisfile, title, "Degrees", "", oenv);
775 if (output_env_get_print_xvgr_codes(oenv))
777 fprintf(fp, "@ with g0\n");
779 xvgr_world(fp, -180, 0, 180, 0.1, oenv);
780 if (output_env_get_print_xvgr_codes(oenv))
782 fprintf(fp, "# this effort to set graph size fails unless you run with -autoscale none or -autoscale y flags\n");
783 fprintf(fp, "@ xaxis tick on\n");
784 fprintf(fp, "@ xaxis tick major 90\n");
785 fprintf(fp, "@ xaxis tick minor 30\n");
786 fprintf(fp, "@ xaxis ticklabel prec 0\n");
787 fprintf(fp, "@ yaxis tick off\n");
788 fprintf(fp, "@ yaxis ticklabel off\n");
789 fprintf(fp, "@ type xy\n");
793 for (k = 0; (k < 3); k++)
795 sprintf(sshisfile, "%s-%s.xvg", hisfile, sss[k]);
796 ssfp[k] = gmx_ffopen(sshisfile, "w");
799 for (j = 0; (j < nbin); j++)
801 angle = -180 + (360/nbin)*j;
804 fprintf(fp, "%5d %10g\n", angle, normhisto[j]);
808 fprintf(fp, "%5d %10d\n", angle, his_aa[Dih][i][j]);
812 for (k = 0; (k < 3); k++)
814 fprintf(ssfp[k], "%5d %10d\n", angle,
815 his_aa_ss[k][i][Dih][j]);
819 fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
823 for (k = 0; (k < 3); k++)
825 fprintf(ssfp[k], "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : "");
826 gmx_ffclose(ssfp[k]);
836 /* Four dimensional array... Very cool */
837 for (i = 0; (i < 3); i++)
839 for (j = 0; (j <= rt_size); j++)
841 for (Dih = 0; (Dih < edMax); Dih++)
843 sfree(his_aa_ss[i][j][Dih]);
845 sfree(his_aa_ss[i][j]);
854 static FILE *rama_file(const char *fn, const char *title, const char *xaxis,
855 const char *yaxis, const gmx_output_env_t *oenv)
859 fp = xvgropen(fn, title, xaxis, yaxis, oenv);
860 if (output_env_get_print_xvgr_codes(oenv))
862 fprintf(fp, "@ with g0\n");
864 xvgr_world(fp, -180, -180, 180, 180, oenv);
865 if (output_env_get_print_xvgr_codes(oenv))
867 fprintf(fp, "@ xaxis tick on\n");
868 fprintf(fp, "@ xaxis tick major 90\n");
869 fprintf(fp, "@ xaxis tick minor 30\n");
870 fprintf(fp, "@ xaxis ticklabel prec 0\n");
871 fprintf(fp, "@ yaxis tick on\n");
872 fprintf(fp, "@ yaxis tick major 90\n");
873 fprintf(fp, "@ yaxis tick minor 30\n");
874 fprintf(fp, "@ yaxis ticklabel prec 0\n");
875 fprintf(fp, "@ s0 type xy\n");
876 fprintf(fp, "@ s0 symbol 2\n");
877 fprintf(fp, "@ s0 symbol size 0.410000\n");
878 fprintf(fp, "@ s0 symbol fill 1\n");
879 fprintf(fp, "@ s0 symbol color 1\n");
880 fprintf(fp, "@ s0 symbol linewidth 1\n");
881 fprintf(fp, "@ s0 symbol linestyle 1\n");
882 fprintf(fp, "@ s0 symbol center false\n");
883 fprintf(fp, "@ s0 symbol char 0\n");
884 fprintf(fp, "@ s0 skip 0\n");
885 fprintf(fp, "@ s0 linestyle 0\n");
886 fprintf(fp, "@ s0 linewidth 1\n");
887 fprintf(fp, "@ type xy\n");
892 static void do_rama(int nf, int nlist, t_dlist dlist[], real **dih,
893 gmx_bool bViol, gmx_bool bRamOmega, const gmx_output_env_t *oenv)
895 FILE *fp, *gp = nullptr;
898 int i, j, k, Xi1, Xi2, Phi, Psi, Om = 0, nlevels;
900 real **mat = nullptr, phi, psi, omega, axis[NMAT], lo, hi;
901 t_rgb rlo = { 1.0, 0.0, 0.0 };
902 t_rgb rmid = { 1.0, 1.0, 1.0 };
903 t_rgb rhi = { 0.0, 0.0, 1.0 };
905 for (i = 0; (i < nlist); i++)
907 if ((has_dihedral(edPhi, &(dlist[i]))) &&
908 (has_dihedral(edPsi, &(dlist[i]))))
910 sprintf(fn, "ramaPhiPsi%s.xvg", dlist[i].name);
911 fp = rama_file(fn, "Ramachandran Plot",
912 "\\8f\\4 (deg)", "\\8y\\4 (deg)", oenv);
913 bOm = bRamOmega && has_dihedral(edOmega, &(dlist[i]));
916 Om = dlist[i].j0[edOmega];
918 for (j = 0; (j < NMAT); j++)
921 axis[j] = -180+(360*j)/NMAT;
926 sprintf(fn, "violPhiPsi%s.xvg", dlist[i].name);
927 gp = gmx_ffopen(fn, "w");
929 Phi = dlist[i].j0[edPhi];
930 Psi = dlist[i].j0[edPsi];
931 for (j = 0; (j < nf); j++)
933 phi = RAD2DEG*dih[Phi][j];
934 psi = RAD2DEG*dih[Psi][j];
935 fprintf(fp, "%10g %10g\n", phi, psi);
938 fprintf(gp, "%d\n", (bAllowed(dih[Phi][j], RAD2DEG*dih[Psi][j]) == FALSE) );
942 omega = RAD2DEG*dih[Om][j];
943 mat[static_cast<int>(((phi*NMAT)/360)+NMAT/2)][static_cast<int>(((psi*NMAT)/360)+NMAT/2)]
954 sprintf(fn, "ramomega%s.xpm", dlist[i].name);
955 fp = gmx_ffopen(fn, "w");
957 for (j = 0; (j < NMAT); j++)
959 for (k = 0; (k < NMAT); k++)
962 lo = std::min(mat[j][k], lo);
963 hi = std::max(mat[j][k], hi);
967 if (std::abs(lo) > std::abs(hi))
976 for (j = 0; (j < NMAT); j++)
978 for (k = 0; (k < NMAT); k++)
986 write_xpm3(fp, 0, "Omega/Ramachandran Plot", "Deg", "Phi", "Psi",
987 NMAT, NMAT, axis, axis, mat, lo, 180.0, hi, rlo, rmid, rhi, &nlevels);
989 for (j = 0; (j < NMAT); j++)
996 if ((has_dihedral(edChi1, &(dlist[i]))) &&
997 (has_dihedral(edChi2, &(dlist[i]))))
999 sprintf(fn, "ramaX1X2%s.xvg", dlist[i].name);
1000 fp = rama_file(fn, "\\8c\\4\\s1\\N-\\8c\\4\\s2\\N Ramachandran Plot",
1001 "\\8c\\4\\s1\\N (deg)", "\\8c\\4\\s2\\N (deg)", oenv);
1002 Xi1 = dlist[i].j0[edChi1];
1003 Xi2 = dlist[i].j0[edChi2];
1004 for (j = 0; (j < nf); j++)
1006 fprintf(fp, "%10g %10g\n", RAD2DEG*dih[Xi1][j], RAD2DEG*dih[Xi2][j]);
1012 fprintf(stderr, "No chi1 & chi2 angle for %s\n", dlist[i].name);
1018 static void print_transitions(const char *fn, int maxchi, int nlist,
1019 t_dlist dlist[], real dt,
1020 const gmx_output_env_t *oenv)
1022 /* based on order_params below */
1026 /* must correspond with enum in pp2shift.h:38 */
1028 #define NLEG asize(leg)
1030 leg[0] = gmx_strdup("Phi");
1031 leg[1] = gmx_strdup("Psi");
1032 leg[2] = gmx_strdup("Omega");
1033 leg[3] = gmx_strdup("Chi1");
1034 leg[4] = gmx_strdup("Chi2");
1035 leg[5] = gmx_strdup("Chi3");
1036 leg[6] = gmx_strdup("Chi4");
1037 leg[7] = gmx_strdup("Chi5");
1038 leg[8] = gmx_strdup("Chi6");
1040 /* Print order parameters */
1041 fp = xvgropen(fn, "Dihedral Rotamer Transitions", "Residue", "Transitions/ns",
1043 xvgr_legend(fp, NONCHI+maxchi, (const char**)leg, oenv);
1045 fprintf(fp, "%5s ", "#Res.");
1046 fprintf(fp, "%10s %10s %10s ", leg[edPhi], leg[edPsi], leg[edOmega]);
1047 for (Xi = 0; Xi < maxchi; Xi++)
1049 fprintf(fp, "%10s ", leg[NONCHI+Xi]);
1053 for (i = 0; (i < nlist); i++)
1055 fprintf(fp, "%5d ", dlist[i].resnr);
1056 for (Dih = 0; (Dih < NONCHI+maxchi); Dih++)
1058 fprintf(fp, "%10.3f ", dlist[i].ntr[Dih]/dt);
1060 /* fprintf(fp,"%12s\n",dlist[i].name); this confuses xmgrace */
1066 static void order_params(FILE *log,
1067 const char *fn, int maxchi, int nlist, t_dlist dlist[],
1068 const char *pdbfn, real bfac_init,
1069 t_atoms *atoms, const rvec x[], int ePBC, matrix box,
1070 gmx_bool bPhi, gmx_bool bPsi, gmx_bool bChi, const gmx_output_env_t *oenv)
1077 /* except for S2Min/Max, must correspond with enum in pp2shift.h:38 */
1078 const char *const_leg[2+edMax] = {
1079 "S2Min", "S2Max", "Phi", "Psi", "Omega",
1080 "Chi1", "Chi2", "Chi3", "Chi4", "Chi5",
1083 #define NLEG asize(leg)
1087 for (i = 0; i < NLEG; i++)
1089 leg[i] = gmx_strdup(const_leg[i]);
1092 /* Print order parameters */
1093 fp = xvgropen(fn, "Dihedral Order Parameters", "Residue", "S2", oenv);
1094 xvgr_legend(fp, 2+NONCHI+maxchi, const_leg, oenv);
1096 for (Dih = 0; (Dih < edMax); Dih++)
1101 fprintf(fp, "%5s ", "#Res.");
1102 fprintf(fp, "%10s %10s ", leg[0], leg[1]);
1103 fprintf(fp, "%10s %10s %10s ", leg[2+edPhi], leg[2+edPsi], leg[2+edOmega]);
1104 for (Xi = 0; Xi < maxchi; Xi++)
1106 fprintf(fp, "%10s ", leg[2+NONCHI+Xi]);
1110 for (i = 0; (i < nlist); i++)
1114 for (Dih = 0; (Dih < NONCHI+maxchi); Dih++)
1116 if (dlist[i].S2[Dih] != 0)
1118 if (dlist[i].S2[Dih] > S2Max)
1120 S2Max = dlist[i].S2[Dih];
1122 if (dlist[i].S2[Dih] < S2Min)
1124 S2Min = dlist[i].S2[Dih];
1127 if (dlist[i].S2[Dih] > 0.8)
1132 fprintf(fp, "%5d ", dlist[i].resnr);
1133 fprintf(fp, "%10.3f %10.3f ", S2Min, S2Max);
1134 for (Dih = 0; (Dih < NONCHI+maxchi); Dih++)
1136 fprintf(fp, "%10.3f ", dlist[i].S2[Dih]);
1139 /* fprintf(fp,"%12s\n",dlist[i].name); this confuses xmgrace */
1143 if (nullptr != pdbfn)
1147 atoms->havePdbInfo = TRUE;
1149 if (nullptr == atoms->pdbinfo)
1151 snew(atoms->pdbinfo, atoms->nr);
1153 for (i = 0; (i < atoms->nr); i++)
1155 atoms->pdbinfo[i].bfac = bfac_init;
1158 for (i = 0; (i < nlist); i++)
1160 atoms->pdbinfo[dlist[i].atm.N].bfac = -dlist[i].S2[0]; /* Phi */
1161 atoms->pdbinfo[dlist[i].atm.H].bfac = -dlist[i].S2[0]; /* Phi */
1162 atoms->pdbinfo[dlist[i].atm.C].bfac = -dlist[i].S2[1]; /* Psi */
1163 atoms->pdbinfo[dlist[i].atm.O].bfac = -dlist[i].S2[1]; /* Psi */
1164 for (Xi = 0; (Xi < maxchi); Xi++) /* Chi's */
1166 if (dlist[i].atm.Cn[Xi+3] != -1)
1168 atoms->pdbinfo[dlist[i].atm.Cn[Xi+1]].bfac = -dlist[i].S2[NONCHI+Xi];
1173 fp = gmx_ffopen(pdbfn, "w");
1174 fprintf(fp, "REMARK generated by g_chi\n");
1175 fprintf(fp, "REMARK "
1176 "B-factor field contains negative of dihedral order parameters\n");
1177 write_pdbfile(fp, nullptr, atoms, x, ePBC, box, ' ', 0, nullptr, TRUE);
1178 x0 = y0 = z0 = 1000.0;
1179 for (i = 0; (i < atoms->nr); i++)
1181 x0 = std::min(x0, x[i][XX]);
1182 y0 = std::min(y0, x[i][YY]);
1183 z0 = std::min(z0, x[i][ZZ]);
1185 x0 *= 10.0; /* nm -> angstrom */
1186 y0 *= 10.0; /* nm -> angstrom */
1187 z0 *= 10.0; /* nm -> angstrom */
1188 for (i = 0; (i < 10); i++)
1190 gmx_fprintf_pdb_atomline(fp, epdbATOM, atoms->nr+1+i, "CA", ' ', "LEG", ' ', atoms->nres+1, ' ',
1191 x0, y0, z0+(1.2*i), 0.0, -0.1*i, "");
1196 fprintf(log, "Dihedrals with S2 > 0.8\n");
1197 fprintf(log, "Dihedral: ");
1200 fprintf(log, " Phi ");
1204 fprintf(log, " Psi ");
1208 for (Xi = 0; (Xi < maxchi); Xi++)
1210 fprintf(log, " %s ", leg[2+NONCHI+Xi]);
1213 fprintf(log, "\nNumber: ");
1216 fprintf(log, "%4d ", nh[0]);
1220 fprintf(log, "%4d ", nh[1]);
1224 for (Xi = 0; (Xi < maxchi); Xi++)
1226 fprintf(log, "%4d ", nh[NONCHI+Xi]);
1231 for (i = 0; i < NLEG; i++)
1238 int gmx_chi(int argc, char *argv[])
1240 const char *desc[] = {
1241 "[THISMODULE] computes [GRK]phi[grk], [GRK]psi[grk], [GRK]omega[grk],",
1242 "and [GRK]chi[grk] dihedrals for all your",
1243 "amino acid backbone and sidechains.",
1244 "It can compute dihedral angle as a function of time, and as",
1245 "histogram distributions.",
1246 "The distributions [TT](histo-(dihedral)(RESIDUE).xvg[tt]) are cumulative over all residues of each type.[PAR]",
1247 "If option [TT]-corr[tt] is given, the program will",
1248 "calculate dihedral autocorrelation functions. The function used",
1249 "is C(t) = [CHEVRON][COS][GRK]chi[grk]([GRK]tau[grk])[cos] [COS][GRK]chi[grk]([GRK]tau[grk]+t)[cos][chevron]. The use of cosines",
1250 "rather than angles themselves, resolves the problem of periodicity.",
1251 "(Van der Spoel & Berendsen (1997), Biophys. J. 72, 2032-2041).",
1252 "Separate files for each dihedral of each residue",
1253 "[TT](corr(dihedral)(RESIDUE)(nresnr).xvg[tt]) are output, as well as a",
1254 "file containing the information for all residues (argument of [TT]-corr[tt]).[PAR]",
1255 "With option [TT]-all[tt], the angles themselves as a function of time for",
1256 "each residue are printed to separate files [TT](dihedral)(RESIDUE)(nresnr).xvg[tt].",
1257 "These can be in radians or degrees.[PAR]",
1258 "A log file (argument [TT]-g[tt]) is also written. This contains",
1260 " * information about the number of residues of each type.",
1261 " * The NMR ^3J coupling constants from the Karplus equation.",
1262 " * a table for each residue of the number of transitions between ",
1263 " rotamers per nanosecond, and the order parameter S^2 of each dihedral.",
1264 " * a table for each residue of the rotamer occupancy.",
1266 "All rotamers are taken as 3-fold, except for [GRK]omega[grk] and [GRK]chi[grk] dihedrals",
1267 "to planar groups (i.e. [GRK]chi[grk][SUB]2[sub] of aromatics, Asp and Asn; [GRK]chi[grk][SUB]3[sub] of Glu",
1268 "and Gln; and [GRK]chi[grk][SUB]4[sub] of Arg), which are 2-fold. \"rotamer 0\" means ",
1269 "that the dihedral was not in the core region of each rotamer. ",
1270 "The width of the core region can be set with [TT]-core_rotamer[tt][PAR]",
1272 "The S^2 order parameters are also output to an [REF].xvg[ref] file",
1273 "(argument [TT]-o[tt] ) and optionally as a [REF].pdb[ref] file with",
1274 "the S^2 values as B-factor (argument [TT]-p[tt]). ",
1275 "The total number of rotamer transitions per timestep",
1276 "(argument [TT]-ot[tt]), the number of transitions per rotamer",
1277 "(argument [TT]-rt[tt]), and the ^3J couplings (argument [TT]-jc[tt]), ",
1278 "can also be written to [REF].xvg[ref] files. Note that the analysis",
1279 "of rotamer transitions assumes that the supplied trajectory frames",
1280 "are equally spaced in time.[PAR]",
1282 "If [TT]-chi_prod[tt] is set (and [TT]-maxchi[tt] > 0), cumulative rotamers, e.g.",
1283 "1+9([GRK]chi[grk][SUB]1[sub]-1)+3([GRK]chi[grk][SUB]2[sub]-1)+([GRK]chi[grk][SUB]3[sub]-1) (if the residue has three 3-fold ",
1284 "dihedrals and [TT]-maxchi[tt] >= 3)",
1285 "are calculated. As before, if any dihedral is not in the core region,",
1286 "the rotamer is taken to be 0. The occupancies of these cumulative ",
1287 "rotamers (starting with rotamer 0) are written to the file",
1288 "that is the argument of [TT]-cp[tt], and if the [TT]-all[tt] flag",
1289 "is given, the rotamers as functions of time",
1290 "are written to [TT]chiproduct(RESIDUE)(nresnr).xvg[tt] ",
1291 "and their occupancies to [TT]histo-chiproduct(RESIDUE)(nresnr).xvg[tt].[PAR]",
1293 "The option [TT]-r[tt] generates a contour plot of the average [GRK]omega[grk] angle",
1294 "as a function of the [GRK]phi[grk] and [GRK]psi[grk] angles, that is, in a Ramachandran plot",
1295 "the average [GRK]omega[grk] angle is plotted using color coding.",
1299 const char *bugs[] = {
1300 "Produces MANY output files (up to about 4 times the number of residues in the protein, twice that if autocorrelation functions are calculated). Typically several hundred files are output.",
1301 "[GRK]phi[grk] and [GRK]psi[grk] dihedrals are calculated in a "
1302 "non-standard way, using H-N-CA-C for [GRK]phi[grk] instead of "
1303 "C(-)-N-CA-C, and N-CA-C-O for [GRK]psi[grk] instead of N-CA-C-N(+). "
1304 "This causes (usually small) discrepancies with the output of other "
1305 "tools like [gmx-rama].",
1306 "[TT]-r0[tt] option does not work properly",
1307 "Rotamers with multiplicity 2 are printed in [TT]chi.log[tt] as if they had multiplicity 3, with the 3rd (g(+)) always having probability 0"
1311 static int r0 = 1, ndeg = 1, maxchi = 2;
1312 static gmx_bool bAll = FALSE;
1313 static gmx_bool bPhi = FALSE, bPsi = FALSE, bOmega = FALSE;
1314 static real bfac_init = -1.0, bfac_max = 0;
1315 static const char *maxchistr[] = { nullptr, "0", "1", "2", "3", "4", "5", "6", nullptr };
1316 static gmx_bool bRama = FALSE, bShift = FALSE, bViol = FALSE, bRamOmega = FALSE;
1317 static gmx_bool bNormHisto = TRUE, bChiProduct = FALSE, bHChi = FALSE, bRAD = FALSE, bPBC = TRUE;
1318 static real core_frac = 0.5;
1320 { "-r0", FALSE, etINT, {&r0},
1321 "starting residue" },
1322 { "-phi", FALSE, etBOOL, {&bPhi},
1323 "Output for [GRK]phi[grk] dihedral angles" },
1324 { "-psi", FALSE, etBOOL, {&bPsi},
1325 "Output for [GRK]psi[grk] dihedral angles" },
1326 { "-omega", FALSE, etBOOL, {&bOmega},
1327 "Output for [GRK]omega[grk] dihedrals (peptide bonds)" },
1328 { "-rama", FALSE, etBOOL, {&bRama},
1329 "Generate [GRK]phi[grk]/[GRK]psi[grk] and [GRK]chi[grk][SUB]1[sub]/[GRK]chi[grk][SUB]2[sub] Ramachandran plots" },
1330 { "-viol", FALSE, etBOOL, {&bViol},
1331 "Write a file that gives 0 or 1 for violated Ramachandran angles" },
1332 { "-periodic", FALSE, etBOOL, {&bPBC},
1333 "Print dihedral angles modulo 360 degrees" },
1334 { "-all", FALSE, etBOOL, {&bAll},
1335 "Output separate files for every dihedral." },
1336 { "-rad", FALSE, etBOOL, {&bRAD},
1337 "in angle vs time files, use radians rather than degrees."},
1338 { "-shift", FALSE, etBOOL, {&bShift},
1339 "Compute chemical shifts from [GRK]phi[grk]/[GRK]psi[grk] angles" },
1340 { "-binwidth", FALSE, etINT, {&ndeg},
1341 "bin width for histograms (degrees)" },
1342 { "-core_rotamer", FALSE, etREAL, {&core_frac},
1343 "only the central [TT]-core_rotamer[tt]\\*(360/multiplicity) belongs to each rotamer (the rest is assigned to rotamer 0)" },
1344 { "-maxchi", FALSE, etENUM, {maxchistr},
1345 "calculate first ndih [GRK]chi[grk] dihedrals" },
1346 { "-normhisto", FALSE, etBOOL, {&bNormHisto},
1347 "Normalize histograms" },
1348 { "-ramomega", FALSE, etBOOL, {&bRamOmega},
1349 "compute average omega as a function of [GRK]phi[grk]/[GRK]psi[grk] and plot it in an [REF].xpm[ref] plot" },
1350 { "-bfact", FALSE, etREAL, {&bfac_init},
1351 "B-factor value for [REF].pdb[ref] file for atoms with no calculated dihedral order parameter"},
1352 { "-chi_prod", FALSE, etBOOL, {&bChiProduct},
1353 "compute a single cumulative rotamer for each residue"},
1354 { "-HChi", FALSE, etBOOL, {&bHChi},
1355 "Include dihedrals to sidechain hydrogens"},
1356 { "-bmax", FALSE, etREAL, {&bfac_max},
1357 "Maximum B-factor on any of the atoms that make up a dihedral, for the dihedral angle to be considere in the statistics. Applies to database work where a number of X-Ray structures is analyzed. [TT]-bmax[tt] <= 0 means no limit." }
1361 int nlist, idum, nbin;
1367 gmx_bool bChi, bCorr, bSSHisto;
1368 gmx_bool bDo_rt, bDo_oh, bDo_ot, bDo_jc;
1369 real dt = 0, traj_t_ns;
1370 gmx_output_env_t *oenv;
1371 gmx_residuetype_t *rt;
1374 int ndih, nactdih, nf;
1375 real **dih, *trans_frac, *aver_angle, *time;
1376 int i, **chi_lookup, *multiplicity;
1379 { efSTX, "-s", nullptr, ffREAD },
1380 { efTRX, "-f", nullptr, ffREAD },
1381 { efXVG, "-o", "order", ffWRITE },
1382 { efPDB, "-p", "order", ffOPTWR },
1383 { efDAT, "-ss", "ssdump", ffOPTRD },
1384 { efXVG, "-jc", "Jcoupling", ffWRITE },
1385 { efXVG, "-corr", "dihcorr", ffOPTWR },
1386 { efLOG, "-g", "chi", ffWRITE },
1387 /* add two more arguments copying from g_angle */
1388 { efXVG, "-ot", "dihtrans", ffOPTWR },
1389 { efXVG, "-oh", "trhisto", ffOPTWR },
1390 { efXVG, "-rt", "restrans", ffOPTWR },
1391 { efXVG, "-cp", "chiprodhisto", ffOPTWR }
1393 #define NFILE asize(fnm)
1398 ppa = add_acf_pargs(&npargs, pa);
1399 if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
1400 NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs,
1407 /* Handle result from enumerated type */
1408 sscanf(maxchistr[0], "%d", &maxchi);
1409 bChi = (maxchi > 0);
1411 log = gmx_ffopen(ftp2fn(efLOG, NFILE, fnm), "w");
1420 /* set some options */
1421 bDo_rt = (opt2bSet("-rt", NFILE, fnm));
1422 bDo_oh = (opt2bSet("-oh", NFILE, fnm));
1423 bDo_ot = (opt2bSet("-ot", NFILE, fnm));
1424 bDo_jc = (opt2bSet("-jc", NFILE, fnm));
1425 bCorr = (opt2bSet("-corr", NFILE, fnm));
1428 fprintf(stderr, "Will calculate autocorrelation\n");
1431 if (core_frac > 1.0)
1433 fprintf(stderr, "core_rotamer fraction > 1.0 ; will use 1.0\n");
1436 if (core_frac < 0.0)
1438 fprintf(stderr, "core_rotamer fraction < 0.0 ; will use 0.0\n");
1442 if (maxchi > MAXCHI)
1445 "Will only calculate first %d Chi dihedrals in stead of %d.\n",
1449 bSSHisto = ftp2bSet(efDAT, NFILE, fnm);
1452 /* Find the chi angles using atoms struct and a list of amino acids */
1455 read_tps_conf(ftp2fn(efSTX, NFILE, fnm), top, &ePBC, &x, nullptr, box, FALSE);
1456 t_atoms &atoms = top->atoms;
1457 if (atoms.pdbinfo == nullptr)
1459 snew(atoms.pdbinfo, atoms.nr);
1461 fprintf(log, "Title: %s\n", *top->name);
1463 gmx_residuetype_init(&rt);
1464 dlist = mk_dlist(log, &atoms, &nlist, bPhi, bPsi, bChi, bHChi, maxchi, r0, rt);
1465 fprintf(stderr, "%d residues with dihedrals found\n", nlist);
1469 gmx_fatal(FARGS, "No dihedrals in your structure!\n");
1472 /* Make a linear index for reading all. */
1473 index = make_chi_ind(nlist, dlist, &ndih);
1475 fprintf(stderr, "%d dihedrals found\n", ndih);
1479 /* COMPUTE ALL DIHEDRALS! */
1480 read_ang_dih(ftp2fn(efTRX, NFILE, fnm), FALSE, TRUE, FALSE, bPBC, 1, &idum,
1481 &nf, &time, isize, index, &trans_frac, &aver_angle, dih, oenv);
1483 dt = (time[nf-1]-time[0])/(nf-1); /* might want this for corr or n. transit*/
1488 gmx_fatal(FARGS, "Need at least 2 frames for correlation");
1492 /* put angles in -M_PI to M_PI ! and correct phase factor for phi and psi
1493 * pass nactdih instead of ndih to low_ana_dih_trans and get_chi_product_traj
1494 * to prevent accessing off end of arrays when maxchi < 5 or 6. */
1495 nactdih = reset_em_all(nlist, dlist, nf, dih, maxchi);
1499 dump_em_all(nlist, dlist, nf, time, dih, maxchi, bPhi, bPsi, bChi, bOmega, bRAD, oenv);
1502 /* Histogramming & J coupling constants & calc of S2 order params */
1503 histogramming(log, nbin, rt, nf, maxchi, dih, nlist, dlist, index,
1504 bPhi, bPsi, bOmega, bChi,
1505 bNormHisto, bSSHisto, ftp2fn(efDAT, NFILE, fnm), bfac_max, &atoms,
1506 bDo_jc, opt2fn("-jc", NFILE, fnm), oenv);
1510 * added multiplicity */
1512 snew(multiplicity, ndih);
1513 mk_multiplicity_lookup(multiplicity, maxchi, nlist, dlist, ndih);
1515 std::strcpy(grpname, "All residues, ");
1518 std::strcat(grpname, "Phi ");
1522 std::strcat(grpname, "Psi ");
1526 std::strcat(grpname, "Omega ");
1530 std::strcat(grpname, "Chi 1-");
1531 sprintf(grpname + std::strlen(grpname), "%i", maxchi);
1535 low_ana_dih_trans(bDo_ot, opt2fn("-ot", NFILE, fnm),
1536 bDo_oh, opt2fn("-oh", NFILE, fnm), maxchi,
1537 dih, nlist, dlist, nf, nactdih, grpname, multiplicity,
1538 time, FALSE, core_frac, oenv);
1540 /* Order parameters */
1541 order_params(log, opt2fn("-o", NFILE, fnm), maxchi, nlist, dlist,
1542 ftp2fn_null(efPDB, NFILE, fnm), bfac_init,
1543 &atoms, x, ePBC, box, bPhi, bPsi, bChi, oenv);
1545 /* Print ramachandran maps! */
1548 do_rama(nf, nlist, dlist, dih, bViol, bRamOmega, oenv);
1553 do_pp2shifts(log, nf, nlist, dlist, dih);
1556 /* rprint S^2, transitions, and rotamer occupancies to log */
1557 traj_t_ns = 0.001 * (time[nf-1]-time[0]);
1558 pr_dlist(log, nlist, dlist, traj_t_ns, edPrintST, bPhi, bPsi, bChi, bOmega, maxchi);
1559 pr_dlist(log, nlist, dlist, traj_t_ns, edPrintRO, bPhi, bPsi, bChi, bOmega, maxchi);
1561 /* transitions to xvg */
1564 print_transitions(opt2fn("-rt", NFILE, fnm), maxchi, nlist, dlist, traj_t_ns, oenv);
1567 /* chi_product trajectories (ie one "rotamer number" for each residue) */
1568 if (bChiProduct && bChi)
1570 snew(chi_lookup, nlist);
1571 for (i = 0; i < nlist; i++)
1573 snew(chi_lookup[i], maxchi);
1575 mk_chi_lookup(chi_lookup, maxchi, nlist, dlist);
1577 get_chi_product_traj(dih, nf, nactdih,
1578 maxchi, dlist, time, chi_lookup, multiplicity,
1579 FALSE, bNormHisto, core_frac, bAll,
1580 opt2fn("-cp", NFILE, fnm), oenv);
1582 for (i = 0; i < nlist; i++)
1584 sfree(chi_lookup[i]);
1588 /* Correlation comes last because it messes up the angles */
1591 do_dihcorr(opt2fn("-corr", NFILE, fnm), nf, ndih, dih, dt, nlist, dlist, time,
1592 maxchi, bPhi, bPsi, bChi, bOmega, oenv);
1596 do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
1597 do_view(oenv, opt2fn("-jc", NFILE, fnm), "-nxy");
1600 do_view(oenv, opt2fn("-corr", NFILE, fnm), "-nxy");
1603 gmx_residuetype_destroy(rt);