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.
7 * Copyright (c) 2018,2019,2020,2021, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
46 #include "gromacs/commandline/pargs.h"
47 #include "gromacs/commandline/viewit.h"
48 #include "gromacs/correlationfunctions/autocorr.h"
49 #include "gromacs/fileio/confio.h"
50 #include "gromacs/fileio/matio.h"
51 #include "gromacs/fileio/pdbio.h"
52 #include "gromacs/fileio/xvgr.h"
53 #include "gromacs/gmxana/gmx_ana.h"
54 #include "gromacs/gmxana/gstat.h"
55 #include "gromacs/math/units.h"
56 #include "gromacs/math/utilities.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/topology/residuetypes.h"
59 #include "gromacs/topology/topology.h"
60 #include "gromacs/utility/arraysize.h"
61 #include "gromacs/utility/cstringutil.h"
62 #include "gromacs/utility/fatalerror.h"
63 #include "gromacs/utility/futil.h"
64 #include "gromacs/utility/smalloc.h"
65 #include "gromacs/utility/stringutil.h"
67 static gmx_bool bAllowed(real phi, real psi)
69 static const char* map[] = { "1100000000000000001111111000000000001111111111111111111111111",
70 "1100000000000000001111110000000000011111111111111111111111111",
71 "1100000000000000001111110000000000011111111111111111111111111",
72 "1100000000000000001111100000000000111111111111111111111111111",
73 "1100000000000000001111100000000000111111111111111111111111111",
74 "1100000000000000001111100000000001111111111111111111111111111",
75 "1100000000000000001111100000000001111111111111111111111111111",
76 "1100000000000000001111100000000011111111111111111111111111111",
77 "1110000000000000001111110000000111111111111111111111111111111",
78 "1110000000000000001111110000001111111111111111111111111111111",
79 "1110000000000000001111111000011111111111111111111111111111111",
80 "1110000000000000001111111100111111111111111111111111111111111",
81 "1110000000000000001111111111111111111111111111111111111111111",
82 "1110000000000000001111111111111111111111111111111111111111111",
83 "1110000000000000001111111111111111111111111111111111111111111",
84 "1110000000000000001111111111111111111111111111111111111111111",
85 "1110000000000000001111111111111110011111111111111111111111111",
86 "1110000000000000001111111111111100000111111111111111111111111",
87 "1110000000000000001111111111111000000000001111111111111111111",
88 "1100000000000000001111111111110000000000000011111111111111111",
89 "1100000000000000001111111111100000000000000011111111111111111",
90 "1000000000000000001111111111000000000000000001111111111111110",
91 "0000000000000000001111111110000000000000000000111111111111100",
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 "0000000000000000000000000000000000000000000000000000000000000",
107 "0000000000000000000000000000000000111111111111000000000000000",
108 "1100000000000000000000000000000001111111111111100000000000111",
109 "1100000000000000000000000000000001111111111111110000000000111",
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",
129 "0000000000000000000000000000000000000000000000000000000000000" };
132 #define INDEX(ppp) (((static_cast<int>(360 + (ppp)*gmx::c_rad2Deg)) % 360) / 6)
137 return map[x][y] == '1';
140 static int* make_chi_ind(int nl, t_dlist dl[], int* ndih)
145 /* There are nl residues with max edMax dihedrals with 4 atoms each */
146 snew(id, nl * edMax * 4);
149 for (i = 0; (i < nl); i++)
151 /* Phi, fake the first one */
152 dl[i].j0[edPhi] = n / 4;
153 if (dl[i].atm.minC >= 0)
155 id[n++] = dl[i].atm.minC;
159 id[n++] = dl[i].atm.H;
161 id[n++] = dl[i].atm.N;
162 id[n++] = dl[i].atm.Cn[1];
163 id[n++] = dl[i].atm.C;
165 for (i = 0; (i < nl); i++)
167 /* Psi, fake the last one */
168 dl[i].j0[edPsi] = n / 4;
169 id[n++] = dl[i].atm.N;
170 id[n++] = dl[i].atm.Cn[1];
171 id[n++] = dl[i].atm.C;
174 id[n++] = dl[i + 1].atm.N;
178 id[n++] = dl[i].atm.O;
181 for (i = 0; (i < nl); i++)
184 if (has_dihedral(edOmega, &(dl[i])))
186 dl[i].j0[edOmega] = n / 4;
187 id[n++] = dl[i].atm.minCalpha;
188 id[n++] = dl[i].atm.minC;
189 id[n++] = dl[i].atm.N;
190 id[n++] = dl[i].atm.Cn[1];
193 for (Xi = 0; (Xi < MAXCHI); Xi++)
196 for (i = 0; (i < nl); i++)
198 if (dl[i].atm.Cn[Xi + 3] != -1)
200 dl[i].j0[edChi1 + Xi] = n / 4;
201 id[n++] = dl[i].atm.Cn[Xi];
202 id[n++] = dl[i].atm.Cn[Xi + 1];
203 id[n++] = dl[i].atm.Cn[Xi + 2];
204 id[n++] = dl[i].atm.Cn[Xi + 3];
213 static void do_dihcorr(const char* fn,
226 const gmx_output_env_t* oenv)
228 char name1[256], name2[256];
231 do_autocorr(fn, oenv, "Dihedral Autocorrelation Function", 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, dih[j]);
242 for (i = 0; (i < nlist); i++)
246 print_one(oenv, "corrpsi", dlist[i].name, "Psi ACF for", "C(t)", nf / 2, time, dih[j]);
250 for (i = 0; (i < nlist); i++)
252 if (has_dihedral(edOmega, &dlist[i]))
256 print_one(oenv, "corromega", dlist[i].name, "Omega ACF for", "C(t)", nf / 2, time, dih[j]);
261 for (Xi = 0; (Xi < maxchi); Xi++)
263 sprintf(name1, "corrchi%d", Xi + 1);
264 sprintf(name2, "Chi%d ACF for", Xi + 1);
265 for (i = 0; (i < nlist); i++)
267 if (dlist[i].atm.Cn[Xi + 3] != -1)
271 print_one(oenv, name1, dlist[i].name, name2, "C(t)", nf / 2, time, dih[j]);
277 fprintf(stderr, "\n");
280 static void copy_dih_data(const real in[], real out[], int nf, gmx_bool bLEAVE)
282 /* if bLEAVE, do nothing to data in copying to out
283 * otherwise multiply by 180/pi to convert rad to deg */
292 mult = (180.0 / M_PI);
294 for (i = 0; (i < nf); i++)
296 out[i] = in[i] * mult;
300 static void dump_em_all(int nlist,
311 const gmx_output_env_t* oenv)
313 char name[256], titlestr[256], ystr[256];
320 std::strcpy(ystr, "Angle (rad)");
324 std::strcpy(ystr, "Angle (degrees)");
329 for (i = 0; (i < nlist); i++)
331 /* grs debug printf("OK i %d j %d\n", i, j) ; */
334 copy_dih_data(dih[j], data, nf, bRAD);
335 print_one(oenv, "phi", dlist[i].name, "\\xf\\f{}", ystr, nf, time, data);
339 for (i = 0; (i < nlist); i++)
343 copy_dih_data(dih[j], data, nf, bRAD);
344 print_one(oenv, "psi", dlist[i].name, "\\xy\\f{}", ystr, nf, time, data);
348 for (i = 0; (i < nlist); i++)
350 if (has_dihedral(edOmega, &(dlist[i])))
354 copy_dih_data(dih[j], data, nf, bRAD);
355 print_one(oenv, "omega", dlist[i].name, "\\xw\\f{}", ystr, nf, time, data);
361 for (Xi = 0; (Xi < maxchi); Xi++)
363 for (i = 0; (i < nlist); i++)
365 if (dlist[i].atm.Cn[Xi + 3] != -1)
369 sprintf(name, "chi%d", Xi + 1);
370 sprintf(titlestr, "\\xc\\f{}\\s%d\\N", Xi + 1);
371 copy_dih_data(dih[j], data, nf, bRAD);
372 print_one(oenv, name, dlist[i].name, titlestr, ystr, nf, time, data);
378 fprintf(stderr, "\n");
381 static void reset_one(real dih[], int nf, real phase)
385 for (j = 0; (j < nf); j++)
388 while (dih[j] < -M_PI)
392 while (dih[j] >= M_PI)
399 static int reset_em_all(int nlist, t_dlist dlist[], int nf, real** dih, int maxchi)
406 for (i = 0; (i < nlist); i++)
408 if (dlist[i].atm.minC == -1)
410 reset_one(dih[j++], nf, M_PI);
414 reset_one(dih[j++], nf, 0);
418 for (i = 0; (i < nlist - 1); i++)
420 reset_one(dih[j++], nf, 0);
422 /* last Psi is faked from O */
423 reset_one(dih[j++], nf, M_PI);
426 for (i = 0; (i < nlist); i++)
428 if (has_dihedral(edOmega, &dlist[i]))
430 reset_one(dih[j++], nf, 0);
433 /* Chi 1 thru maxchi */
434 for (Xi = 0; (Xi < maxchi); Xi++)
436 for (i = 0; (i < nlist); i++)
438 if (dlist[i].atm.Cn[Xi + 3] != -1)
440 reset_one(dih[j], nf, 0);
445 fprintf(stderr, "j after resetting (nr. active dihedrals) = %d\n", j);
449 static void histogramming(FILE* log,
466 const t_atoms* atoms,
469 const gmx_output_env_t* oenv)
471 /* also gets 3J couplings and order parameters S2 */
472 // Avoid warnings about narrowing conversions from double to real
474 # pragma warning(disable : 4838)
476 t_karplus kkkphi[] = { { "J_NHa1", 6.51, -1.76, 1.6, -M_PI / 3, 0.0, 0.0 },
477 { "J_NHa2", 6.51, -1.76, 1.6, M_PI / 3, 0.0, 0.0 },
478 { "J_HaC'", 4.0, 1.1, 0.1, 0.0, 0.0, 0.0 },
479 { "J_NHCb", 4.7, -1.5, -0.2, M_PI / 3, 0.0, 0.0 },
480 { "J_Ci-1Hai", 4.5, -1.3, -1.2, 2 * M_PI / 3, 0.0, 0.0 } };
481 t_karplus kkkpsi[] = { { "J_HaN", -0.88, -0.61, -0.27, M_PI / 3, 0.0, 0.0 } };
482 t_karplus kkkchi1[] = { { "JHaHb2", 9.5, -1.6, 1.8, -M_PI / 3, 0, 0.0 },
483 { "JHaHb3", 9.5, -1.6, 1.8, 0, 0, 0.0 } };
485 # pragma warning(default : 4838)
487 #define NKKKPHI asize(kkkphi)
488 #define NKKKPSI asize(kkkpsi)
489 #define NKKKCHI asize(kkkchi1)
490 #define NJC (NKKKPHI + NKKKPSI + NKKKCHI)
492 FILE * fp, *ssfp[3] = { nullptr, nullptr, nullptr };
493 const char* sss[3] = { "sheet", "helix", "coil" };
497 int**** his_aa_ss = nullptr;
498 int *** his_aa, *histmp;
499 int i, j, k, m, n, nn, Dih, nres, hindex, angle;
500 gmx_bool bBfac, bOccup;
501 char hisfile[256], hhisfile[256], title[256], *ss_str = nullptr;
503 const char* residue_name;
506 rt_size = rt->numberOfEntries();
509 fp = gmx_ffopen(ssdump, "r");
510 if (1 != fscanf(fp, "%d", &nres))
512 gmx_fatal(FARGS, "Error reading from file %s", ssdump);
515 snew(ss_str, nres + 1);
516 if (1 != fscanf(fp, "%s", ss_str))
518 gmx_fatal(FARGS, "Error reading from file %s", ssdump);
522 /* Four dimensional array... Very cool */
524 for (i = 0; (i < 3); i++)
526 snew(his_aa_ss[i], rt_size + 1);
527 for (j = 0; (j <= rt_size); j++)
529 snew(his_aa_ss[i][j], edMax);
530 for (Dih = 0; (Dih < edMax); Dih++)
532 snew(his_aa_ss[i][j][Dih], nbin + 1);
538 for (Dih = 0; (Dih < edMax); Dih++)
540 snew(his_aa[Dih], rt_size + 1);
541 for (i = 0; (i <= rt_size); i++)
543 snew(his_aa[Dih][i], nbin + 1);
550 for (i = 0; (i < nlist); i++)
558 for (Dih = 0; (Dih < NONCHI + maxchi); Dih++)
560 for (i = 0; (i < nlist); i++)
562 if (((Dih < edOmega)) || ((Dih == edOmega) && (has_dihedral(edOmega, &(dlist[i]))))
563 || ((Dih > edOmega) && (dlist[i].atm.Cn[Dih - NONCHI + 3] != -1)))
565 make_histo(log, nf, dih[j], nbin, histmp, -M_PI, M_PI);
569 /* Assume there is only one structure, the first.
570 * Compute index in histogram.
572 /* Check the atoms to see whether their B-factors are low enough
573 * Check atoms to see their occupancy is 1.
575 bBfac = bOccup = TRUE;
576 for (nn = 0; (nn < 4); nn++, n++)
578 bBfac = bBfac && (atoms->pdbinfo[index[n]].bfac <= bfac_max);
579 bOccup = bOccup && (atoms->pdbinfo[index[n]].occup == 1);
581 if (bOccup && ((bfac_max <= 0) || bBfac))
583 hindex = static_cast<int>(((dih[j][0] + M_PI) * nbin) / (2 * M_PI));
584 range_check(hindex, 0, nbin);
586 /* Assign dihedral to either of the structure determined
589 switch (ss_str[dlist[i].resnr])
591 case 'E': his_aa_ss[0][dlist[i].index][Dih][hindex]++; break;
592 case 'H': his_aa_ss[1][dlist[i].index][Dih][hindex]++; break;
593 default: his_aa_ss[2][dlist[i].index][Dih][hindex]++; break;
598 fprintf(debug, "Res. %d has imcomplete occupancy or bfacs > %g\n", dlist[i].resnr, bfac_max);
609 calc_distribution_props(nbin, histmp, -M_PI, NKKKPHI, kkkphi, &S2);
611 for (m = 0; (m < NKKKPHI); m++)
613 Jc[i][m] = kkkphi[m].Jc;
614 Jcsig[i][m] = kkkphi[m].Jcsig;
618 calc_distribution_props(nbin, histmp, -M_PI, NKKKPSI, kkkpsi, &S2);
620 for (m = 0; (m < NKKKPSI); m++)
622 Jc[i][NKKKPHI + m] = kkkpsi[m].Jc;
623 Jcsig[i][NKKKPHI + m] = kkkpsi[m].Jcsig;
627 calc_distribution_props(nbin, histmp, -M_PI, NKKKCHI, kkkchi1, &S2);
628 for (m = 0; (m < NKKKCHI); m++)
630 Jc[i][NKKKPHI + NKKKPSI + m] = kkkchi1[m].Jc;
631 Jcsig[i][NKKKPHI + NKKKPSI + m] = kkkchi1[m].Jcsig;
634 default: /* covers edOmega and higher Chis than Chi1 */
635 calc_distribution_props(nbin, histmp, -M_PI, 0, nullptr, &S2);
638 dlist[i].S2[Dih] = S2;
640 /* Sum distribution per amino acid type as well */
641 for (k = 0; (k < nbin); k++)
643 his_aa[Dih][dlist[i].index][k] += histmp[k];
648 else /* dihed not defined */
650 dlist[i].S2[Dih] = 0.0;
656 /* Print out Jcouplings */
657 fprintf(log, "\n *** J-Couplings from simulation (plus std. dev.) ***\n\n");
658 fprintf(log, "Residue ");
659 for (i = 0; (i < NKKKPHI); i++)
661 fprintf(log, "%7s SD", kkkphi[i].name);
663 for (i = 0; (i < NKKKPSI); i++)
665 fprintf(log, "%7s SD", kkkpsi[i].name);
667 for (i = 0; (i < NKKKCHI); i++)
669 fprintf(log, "%7s SD", kkkchi1[i].name);
672 for (i = 0; (i < NJC + 1); i++)
674 fprintf(log, "------------");
677 for (i = 0; (i < nlist); i++)
679 fprintf(log, "%-10s", dlist[i].name);
680 for (j = 0; (j < NJC); j++)
682 fprintf(log, " %5.2f %4.2f", Jc[i][j], Jcsig[i][j]);
688 /* and to -jc file... */
691 fp = xvgropen(fn, "\\S3\\NJ-Couplings from Karplus Equation", "Residue", "Coupling", oenv);
693 for (i = 0; (i < NKKKPHI); i++)
695 leg[i] = gmx_strdup(kkkphi[i].name);
697 for (i = 0; (i < NKKKPSI); i++)
699 leg[i + NKKKPHI] = gmx_strdup(kkkpsi[i].name);
701 for (i = 0; (i < NKKKCHI); i++)
703 leg[i + NKKKPHI + NKKKPSI] = gmx_strdup(kkkchi1[i].name);
705 xvgr_legend(fp, NJC, leg, oenv);
706 fprintf(fp, "%5s ", "#Res.");
707 for (i = 0; (i < NJC); i++)
709 fprintf(fp, "%10s ", leg[i]);
712 for (i = 0; (i < nlist); i++)
714 fprintf(fp, "%5d ", dlist[i].resnr);
715 for (j = 0; (j < NJC); j++)
717 fprintf(fp, " %8.3f", Jc[i][j]);
722 for (i = 0; (i < NJC); i++)
727 /* finished -jc stuff */
729 snew(normhisto, nbin);
730 for (i = 0; (i < rt_size); i++)
732 for (Dih = 0; (Dih < edMax); Dih++)
734 /* First check whether something is in there */
735 for (j = 0; (j < nbin); j++)
737 if (his_aa[Dih][i][j] != 0)
743 && ((bPhi && (Dih == edPhi)) || (bPsi && (Dih == edPsi))
744 || (bOmega && (Dih == edOmega)) || (bChi && (Dih >= edChi1))))
748 normalize_histo(nbin, his_aa[Dih][i], (360.0 / nbin), normhisto);
751 std::string residueName = rt->nameFromResidueIndex(i);
752 residue_name = residueName.c_str();
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", Dih - NONCHI + 1, residue_name);
771 std::strcpy(hhisfile, hisfile);
772 std::strcat(hhisfile, ".xvg");
773 fp = xvgropen(hhisfile, title, "Degrees", "", oenv);
774 if (output_env_get_print_xvgr_codes(oenv))
776 fprintf(fp, "@ with g0\n");
778 xvgr_world(fp, -180, 0, 180, 0.1, oenv);
779 if (output_env_get_print_xvgr_codes(oenv))
782 "# this effort to set graph size fails unless you run with -autoscale "
783 "none or -autoscale y flags\n");
784 fprintf(fp, "@ xaxis tick on\n");
785 fprintf(fp, "@ xaxis tick major 90\n");
786 fprintf(fp, "@ xaxis tick minor 30\n");
787 fprintf(fp, "@ xaxis ticklabel prec 0\n");
788 fprintf(fp, "@ yaxis tick off\n");
789 fprintf(fp, "@ yaxis ticklabel off\n");
790 fprintf(fp, "@ type xy\n");
794 for (k = 0; (k < 3); k++)
796 std::string sshisfile = gmx::formatString("%s-%s.xvg", hisfile, sss[k]);
797 ssfp[k] = gmx_ffopen(sshisfile, "w");
800 for (j = 0; (j < nbin); j++)
802 angle = -180 + (360 / nbin) * j;
805 fprintf(fp, "%5d %10g\n", angle, normhisto[j]);
809 fprintf(fp, "%5d %10d\n", angle, his_aa[Dih][i][j]);
813 for (k = 0; (k < 3); k++)
815 fprintf(ssfp[k], "%5d %10d\n", angle, 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, const char* yaxis, const gmx_output_env_t* oenv)
858 fp = xvgropen(fn, title, xaxis, yaxis, oenv);
859 if (output_env_get_print_xvgr_codes(oenv))
861 fprintf(fp, "@ with g0\n");
863 xvgr_world(fp, -180, -180, 180, 180, oenv);
864 if (output_env_get_print_xvgr_codes(oenv))
866 fprintf(fp, "@ xaxis tick on\n");
867 fprintf(fp, "@ xaxis tick major 90\n");
868 fprintf(fp, "@ xaxis tick minor 30\n");
869 fprintf(fp, "@ xaxis ticklabel prec 0\n");
870 fprintf(fp, "@ yaxis tick on\n");
871 fprintf(fp, "@ yaxis tick major 90\n");
872 fprintf(fp, "@ yaxis tick minor 30\n");
873 fprintf(fp, "@ yaxis ticklabel prec 0\n");
874 fprintf(fp, "@ s0 type xy\n");
875 fprintf(fp, "@ s0 symbol 2\n");
876 fprintf(fp, "@ s0 symbol size 0.410000\n");
877 fprintf(fp, "@ s0 symbol fill 1\n");
878 fprintf(fp, "@ s0 symbol color 1\n");
879 fprintf(fp, "@ s0 symbol linewidth 1\n");
880 fprintf(fp, "@ s0 symbol linestyle 1\n");
881 fprintf(fp, "@ s0 symbol center false\n");
882 fprintf(fp, "@ s0 symbol char 0\n");
883 fprintf(fp, "@ s0 skip 0\n");
884 fprintf(fp, "@ s0 linestyle 0\n");
885 fprintf(fp, "@ s0 linewidth 1\n");
886 fprintf(fp, "@ type xy\n");
891 static void do_rama(int nf,
897 const gmx_output_env_t* oenv)
899 FILE * fp, *gp = nullptr;
902 int i, j, k, Xi1, Xi2, Phi, Psi, Om = 0, nlevels;
903 constexpr int NMAT = 120;
904 real ** mat = nullptr, phi, psi, omega, axis[NMAT], lo, hi;
905 t_rgb rlo = { 1.0, 0.0, 0.0 };
906 t_rgb rmid = { 1.0, 1.0, 1.0 };
907 t_rgb rhi = { 0.0, 0.0, 1.0 };
909 for (i = 0; (i < nlist); i++)
911 if ((has_dihedral(edPhi, &(dlist[i]))) && (has_dihedral(edPsi, &(dlist[i]))))
913 sprintf(fn, "ramaPhiPsi%s.xvg", dlist[i].name);
914 fp = rama_file(fn, "Ramachandran Plot", "\\8f\\4 (deg)", "\\8y\\4 (deg)", oenv);
915 bOm = bRamOmega && has_dihedral(edOmega, &(dlist[i]));
918 Om = dlist[i].j0[edOmega];
920 for (j = 0; (j < NMAT); j++)
923 axis[j] = -180 + gmx::exactDiv(360 * j, NMAT);
928 sprintf(fn, "violPhiPsi%s.xvg", dlist[i].name);
929 gp = gmx_ffopen(fn, "w");
931 Phi = dlist[i].j0[edPhi];
932 Psi = dlist[i].j0[edPsi];
933 for (j = 0; (j < nf); j++)
935 phi = gmx::c_rad2Deg * dih[Phi][j];
936 psi = gmx::c_rad2Deg * dih[Psi][j];
937 fprintf(fp, "%10g %10g\n", phi, psi);
942 static_cast<int>(!bAllowed(dih[Phi][j], gmx::c_rad2Deg * dih[Psi][j])));
946 omega = gmx::c_rad2Deg * dih[Om][j];
947 mat[static_cast<int>(((phi * NMAT) / 360) + gmx::exactDiv(NMAT, 2))]
948 [static_cast<int>(((psi * NMAT) / 360) + gmx::exactDiv(NMAT, 2))] += omega;
958 sprintf(fn, "ramomega%s.xpm", dlist[i].name);
959 fp = gmx_ffopen(fn, "w");
961 for (j = 0; (j < NMAT); j++)
963 for (k = 0; (k < NMAT); k++)
966 lo = std::min(mat[j][k], lo);
967 hi = std::max(mat[j][k], hi);
971 if (std::abs(lo) > std::abs(hi))
980 for (j = 0; (j < NMAT); j++)
982 for (k = 0; (k < NMAT); k++)
992 "Omega/Ramachandran Plot",
1009 for (j = 0; (j < NMAT); j++)
1016 if ((has_dihedral(edChi1, &(dlist[i]))) && (has_dihedral(edChi2, &(dlist[i]))))
1018 sprintf(fn, "ramaX1X2%s.xvg", dlist[i].name);
1020 "\\8c\\4\\s1\\N-\\8c\\4\\s2\\N Ramachandran Plot",
1021 "\\8c\\4\\s1\\N (deg)",
1022 "\\8c\\4\\s2\\N (deg)",
1024 Xi1 = dlist[i].j0[edChi1];
1025 Xi2 = dlist[i].j0[edChi2];
1026 for (j = 0; (j < nf); j++)
1028 fprintf(fp, "%10g %10g\n", gmx::c_rad2Deg * dih[Xi1][j], gmx::c_rad2Deg * dih[Xi2][j]);
1034 fprintf(stderr, "No chi1 & chi2 angle for %s\n", dlist[i].name);
1040 static void print_transitions(const char* fn, int maxchi, int nlist, t_dlist dlist[], real dt, const gmx_output_env_t* oenv)
1042 /* based on order_params below */
1046 /* must correspond with enum in pp2shift.h:38 */
1049 leg[0] = gmx_strdup("Phi");
1050 leg[1] = gmx_strdup("Psi");
1051 leg[2] = gmx_strdup("Omega");
1052 leg[3] = gmx_strdup("Chi1");
1053 leg[4] = gmx_strdup("Chi2");
1054 leg[5] = gmx_strdup("Chi3");
1055 leg[6] = gmx_strdup("Chi4");
1056 leg[7] = gmx_strdup("Chi5");
1057 leg[8] = gmx_strdup("Chi6");
1059 /* Print order parameters */
1060 fp = xvgropen(fn, "Dihedral Rotamer Transitions", "Residue", "Transitions/ns", oenv);
1061 xvgr_legend(fp, NONCHI + maxchi, leg, oenv);
1063 fprintf(fp, "%5s ", "#Res.");
1064 fprintf(fp, "%10s %10s %10s ", leg[edPhi], leg[edPsi], leg[edOmega]);
1065 for (Xi = 0; Xi < maxchi; Xi++)
1067 fprintf(fp, "%10s ", leg[NONCHI + Xi]);
1071 for (i = 0; (i < nlist); i++)
1073 fprintf(fp, "%5d ", dlist[i].resnr);
1074 for (Dih = 0; (Dih < NONCHI + maxchi); Dih++)
1076 fprintf(fp, "%10.3f ", dlist[i].ntr[Dih] / dt);
1078 /* fprintf(fp,"%12s\n",dlist[i].name); this confuses xmgrace */
1084 static void order_params(FILE* log,
1098 const gmx_output_env_t* oenv)
1105 /* except for S2Min/Max, must correspond with enum in pp2shift.h:38 */
1106 const char* const_leg[2 + edMax] = { "S2Min", "S2Max", "Phi", "Psi", "Omega", "Chi1",
1107 "Chi2", "Chi3", "Chi4", "Chi5", "Chi6" };
1108 #define NLEG asize(leg)
1110 char* leg[2 + edMax];
1112 for (i = 0; i < NLEG; i++)
1114 leg[i] = gmx_strdup(const_leg[i]);
1117 /* Print order parameters */
1118 fp = xvgropen(fn, "Dihedral Order Parameters", "Residue", "S2", oenv);
1119 xvgr_legend(fp, 2 + NONCHI + maxchi, const_leg, oenv);
1121 for (Dih = 0; (Dih < edMax); Dih++)
1126 fprintf(fp, "%5s ", "#Res.");
1127 fprintf(fp, "%10s %10s ", leg[0], leg[1]);
1128 fprintf(fp, "%10s %10s %10s ", leg[2 + edPhi], leg[2 + edPsi], leg[2 + edOmega]);
1129 for (Xi = 0; Xi < maxchi; Xi++)
1131 fprintf(fp, "%10s ", leg[2 + NONCHI + Xi]);
1135 for (i = 0; (i < nlist); i++)
1139 for (Dih = 0; (Dih < NONCHI + maxchi); Dih++)
1141 if (dlist[i].S2[Dih] != 0)
1143 if (dlist[i].S2[Dih] > S2Max)
1145 S2Max = dlist[i].S2[Dih];
1147 if (dlist[i].S2[Dih] < S2Min)
1149 S2Min = dlist[i].S2[Dih];
1152 if (dlist[i].S2[Dih] > 0.8)
1157 fprintf(fp, "%5d ", dlist[i].resnr);
1158 fprintf(fp, "%10.3f %10.3f ", S2Min, S2Max);
1159 for (Dih = 0; (Dih < NONCHI + maxchi); Dih++)
1161 fprintf(fp, "%10.3f ", dlist[i].S2[Dih]);
1164 /* fprintf(fp,"%12s\n",dlist[i].name); this confuses xmgrace */
1168 if (nullptr != pdbfn)
1172 atoms->havePdbInfo = TRUE;
1174 if (nullptr == atoms->pdbinfo)
1176 snew(atoms->pdbinfo, atoms->nr);
1178 for (i = 0; (i < atoms->nr); i++)
1180 atoms->pdbinfo[i].bfac = bfac_init;
1183 for (i = 0; (i < nlist); i++)
1185 atoms->pdbinfo[dlist[i].atm.N].bfac = -dlist[i].S2[0]; /* Phi */
1186 atoms->pdbinfo[dlist[i].atm.H].bfac = -dlist[i].S2[0]; /* Phi */
1187 atoms->pdbinfo[dlist[i].atm.C].bfac = -dlist[i].S2[1]; /* Psi */
1188 atoms->pdbinfo[dlist[i].atm.O].bfac = -dlist[i].S2[1]; /* Psi */
1189 for (Xi = 0; (Xi < maxchi); Xi++) /* Chi's */
1191 if (dlist[i].atm.Cn[Xi + 3] != -1)
1193 atoms->pdbinfo[dlist[i].atm.Cn[Xi + 1]].bfac = -dlist[i].S2[NONCHI + Xi];
1198 fp = gmx_ffopen(pdbfn, "w");
1199 fprintf(fp, "REMARK generated by g_chi\n");
1202 "B-factor field contains negative of dihedral order parameters\n");
1203 write_pdbfile(fp, nullptr, atoms, x, pbcType, box, ' ', 0, nullptr);
1204 x0 = y0 = z0 = 1000.0;
1205 for (i = 0; (i < atoms->nr); i++)
1207 x0 = std::min(x0, x[i][XX]);
1208 y0 = std::min(y0, x[i][YY]);
1209 z0 = std::min(z0, x[i][ZZ]);
1211 x0 *= 10.0; /* nm -> angstrom */
1212 y0 *= 10.0; /* nm -> angstrom */
1213 z0 *= 10.0; /* nm -> angstrom */
1214 for (i = 0; (i < 10); i++)
1216 gmx_fprintf_pdb_atomline(fp,
1217 PdbRecordType::Atom,
1235 fprintf(log, "Dihedrals with S2 > 0.8\n");
1236 fprintf(log, "Dihedral: ");
1239 fprintf(log, " Phi ");
1243 fprintf(log, " Psi ");
1247 for (Xi = 0; (Xi < maxchi); Xi++)
1249 fprintf(log, " %s ", leg[2 + NONCHI + Xi]);
1252 fprintf(log, "\nNumber: ");
1255 fprintf(log, "%4d ", nh[0]);
1259 fprintf(log, "%4d ", nh[1]);
1263 for (Xi = 0; (Xi < maxchi); Xi++)
1265 fprintf(log, "%4d ", nh[NONCHI + Xi]);
1270 for (i = 0; i < NLEG; i++)
1276 int gmx_chi(int argc, char* argv[])
1278 const char* desc[] = {
1279 "[THISMODULE] computes [GRK]phi[grk], [GRK]psi[grk], [GRK]omega[grk],",
1280 "and [GRK]chi[grk] dihedrals for all your",
1281 "amino acid backbone and sidechains.",
1282 "It can compute dihedral angle as a function of time, and as",
1283 "histogram distributions.",
1284 "The distributions [TT](histo-(dihedral)(RESIDUE).xvg[tt]) are cumulative over all ",
1285 "residues of each type.[PAR]",
1286 "If option [TT]-corr[tt] is given, the program will",
1287 "calculate dihedral autocorrelation functions. The function used",
1288 "is C(t) = [CHEVRON][COS][GRK]chi[grk]([GRK]tau[grk])[cos] ",
1289 "[COS][GRK]chi[grk]([GRK]tau[grk]+t)[cos][chevron]. The use of cosines",
1290 "rather than angles themselves, resolves the problem of periodicity.",
1291 "(Van der Spoel & Berendsen (1997), Biophys. J. 72, 2032-2041).",
1292 "Separate files for each dihedral of each residue",
1293 "[TT](corr(dihedral)(RESIDUE)(nresnr).xvg[tt]) are output, as well as a",
1294 "file containing the information for all residues (argument of [TT]-corr[tt]).[PAR]",
1295 "With option [TT]-all[tt], the angles themselves as a function of time for",
1296 "each residue are printed to separate files [TT](dihedral)(RESIDUE)(nresnr).xvg[tt].",
1297 "These can be in radians or degrees.[PAR]",
1298 "A log file (argument [TT]-g[tt]) is also written. This contains",
1300 " * information about the number of residues of each type.",
1301 " * The NMR ^3J coupling constants from the Karplus equation.",
1302 " * a table for each residue of the number of transitions between ",
1303 " rotamers per nanosecond, and the order parameter S^2 of each dihedral.",
1304 " * a table for each residue of the rotamer occupancy.",
1306 "All rotamers are taken as 3-fold, except for [GRK]omega[grk] and [GRK]chi[grk] dihedrals",
1307 "to planar groups (i.e. [GRK]chi[grk][SUB]2[sub] of aromatics, Asp and Asn; ",
1308 "[GRK]chi[grk][SUB]3[sub] of Glu",
1309 "and Gln; and [GRK]chi[grk][SUB]4[sub] of Arg), which are 2-fold. \"rotamer 0\" means ",
1310 "that the dihedral was not in the core region of each rotamer. ",
1311 "The width of the core region can be set with [TT]-core_rotamer[tt][PAR]",
1313 "The S^2 order parameters are also output to an [REF].xvg[ref] file",
1314 "(argument [TT]-o[tt] ) and optionally as a [REF].pdb[ref] file with",
1315 "the S^2 values as B-factor (argument [TT]-p[tt]). ",
1316 "The total number of rotamer transitions per timestep",
1317 "(argument [TT]-ot[tt]), the number of transitions per rotamer",
1318 "(argument [TT]-rt[tt]), and the ^3J couplings (argument [TT]-jc[tt]), ",
1319 "can also be written to [REF].xvg[ref] files. Note that the analysis",
1320 "of rotamer transitions assumes that the supplied trajectory frames",
1321 "are equally spaced in time.[PAR]",
1323 "If [TT]-chi_prod[tt] is set (and [TT]-maxchi[tt] > 0), cumulative rotamers, e.g.",
1324 "1+9([GRK]chi[grk][SUB]1[sub]-1)+3([GRK]chi[grk][SUB]2[sub]-1)+",
1325 "([GRK]chi[grk][SUB]3[sub]-1) (if the residue has three 3-fold ",
1326 "dihedrals and [TT]-maxchi[tt] >= 3)",
1327 "are calculated. As before, if any dihedral is not in the core region,",
1328 "the rotamer is taken to be 0. The occupancies of these cumulative ",
1329 "rotamers (starting with rotamer 0) are written to the file",
1330 "that is the argument of [TT]-cp[tt], and if the [TT]-all[tt] flag",
1331 "is given, the rotamers as functions of time",
1332 "are written to [TT]chiproduct(RESIDUE)(nresnr).xvg[tt] ",
1333 "and their occupancies to [TT]histo-chiproduct(RESIDUE)(nresnr).xvg[tt].[PAR]",
1335 "The option [TT]-r[tt] generates a contour plot of the average [GRK]omega[grk] angle",
1336 "as a function of the [GRK]phi[grk] and [GRK]psi[grk] angles, that is, in a Ramachandran ",
1337 "plot the average [GRK]omega[grk] angle is plotted using color coding.",
1341 const char* bugs[] = {
1342 "Produces MANY output files (up to about 4 times the number of residues in the "
1343 "protein, twice that if autocorrelation functions are calculated). Typically "
1344 "several hundred files are output.",
1345 "[GRK]phi[grk] and [GRK]psi[grk] dihedrals are calculated in a "
1346 "non-standard way, using H-N-CA-C for [GRK]phi[grk] instead of "
1347 "C(-)-N-CA-C, and N-CA-C-O for [GRK]psi[grk] instead of N-CA-C-N(+). "
1348 "This causes (usually small) discrepancies with the output of other "
1349 "tools like [gmx-rama].",
1350 "[TT]-r0[tt] option does not work properly",
1351 "Rotamers with multiplicity 2 are printed in [TT]chi.log[tt] as if they had ",
1352 "multiplicity 3, with the 3rd (g(+)) always having probability 0"
1356 static int r0 = 1, ndeg = 1, maxchi = 2;
1357 static gmx_bool bAll = FALSE;
1358 static gmx_bool bPhi = FALSE, bPsi = FALSE, bOmega = FALSE;
1359 static real bfac_init = -1.0, bfac_max = 0;
1360 static const char* maxchistr[] = { nullptr, "0", "1", "2", "3", "4", "5", "6", nullptr };
1361 static gmx_bool bRama = FALSE, bShift = FALSE, bViol = FALSE, bRamOmega = FALSE;
1362 static gmx_bool bNormHisto = TRUE, bChiProduct = FALSE, bHChi = FALSE, bRAD = FALSE, bPBC = TRUE;
1363 static real core_frac = 0.5;
1365 { "-r0", FALSE, etINT, { &r0 }, "starting residue" },
1366 { "-phi", FALSE, etBOOL, { &bPhi }, "Output for [GRK]phi[grk] dihedral angles" },
1367 { "-psi", FALSE, etBOOL, { &bPsi }, "Output for [GRK]psi[grk] dihedral angles" },
1372 "Output for [GRK]omega[grk] dihedrals (peptide bonds)" },
1377 "Generate [GRK]phi[grk]/[GRK]psi[grk] and "
1378 "[GRK]chi[grk][SUB]1[sub]/[GRK]chi[grk][SUB]2[sub] Ramachandran plots" },
1383 "Write a file that gives 0 or 1 for violated Ramachandran angles" },
1384 { "-periodic", FALSE, etBOOL, { &bPBC }, "Print dihedral angles modulo 360 degrees" },
1385 { "-all", FALSE, etBOOL, { &bAll }, "Output separate files for every dihedral." },
1390 "in angle vs time files, use radians rather than degrees." },
1395 "Compute chemical shifts from [GRK]phi[grk]/[GRK]psi[grk] angles" },
1396 { "-binwidth", FALSE, etINT, { &ndeg }, "bin width for histograms (degrees)" },
1401 "only the central [TT]-core_rotamer[tt]\\*(360/multiplicity) belongs to each rotamer "
1402 "(the rest is assigned to rotamer 0)" },
1403 { "-maxchi", FALSE, etENUM, { maxchistr }, "calculate first ndih [GRK]chi[grk] dihedrals" },
1404 { "-normhisto", FALSE, etBOOL, { &bNormHisto }, "Normalize histograms" },
1409 "compute average omega as a function of [GRK]phi[grk]/[GRK]psi[grk] and plot it in an "
1410 "[REF].xpm[ref] plot" },
1415 "B-factor value for [REF].pdb[ref] file for atoms with no calculated dihedral order "
1421 "compute a single cumulative rotamer for each residue" },
1422 { "-HChi", FALSE, etBOOL, { &bHChi }, "Include dihedrals to sidechain hydrogens" },
1427 "Maximum B-factor on any of the atoms that make up a dihedral, for the dihedral angle to "
1428 "be considere in the statistics. Applies to database work where a number of X-Ray "
1429 "structures is analyzed. [TT]-bmax[tt] <= 0 means no limit." }
1433 int nlist, idum, nbin;
1439 gmx_bool bChi, bCorr, bSSHisto;
1440 gmx_bool bDo_rt, bDo_oh, bDo_ot, bDo_jc;
1441 real dt = 0, traj_t_ns;
1442 gmx_output_env_t* oenv;
1445 int ndih, nactdih, nf;
1446 real **dih, *trans_frac, *aver_angle, *time;
1447 int i, **chi_lookup, *multiplicity;
1449 t_filenm fnm[] = { { efSTX, "-s", nullptr, ffREAD },
1450 { efTRX, "-f", nullptr, ffREAD },
1451 { efXVG, "-o", "order", ffWRITE },
1452 { efPDB, "-p", "order", ffOPTWR },
1453 { efDAT, "-ss", "ssdump", ffOPTRD },
1454 { efXVG, "-jc", "Jcoupling", ffWRITE },
1455 { efXVG, "-corr", "dihcorr", ffOPTWR },
1456 { efLOG, "-g", "chi", ffWRITE },
1457 /* add two more arguments copying from g_angle */
1458 { efXVG, "-ot", "dihtrans", ffOPTWR },
1459 { efXVG, "-oh", "trhisto", ffOPTWR },
1460 { efXVG, "-rt", "restrans", ffOPTWR },
1461 { efXVG, "-cp", "chiprodhisto", ffOPTWR } };
1462 #define NFILE asize(fnm)
1467 ppa = add_acf_pargs(&npargs, pa);
1468 if (!parse_common_args(
1469 &argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs, &oenv))
1475 /* Handle result from enumerated type */
1476 sscanf(maxchistr[0], "%d", &maxchi);
1477 bChi = (maxchi > 0);
1479 log = gmx_ffopen(ftp2fn(efLOG, NFILE, fnm), "w");
1488 /* set some options */
1489 bDo_rt = (opt2bSet("-rt", NFILE, fnm));
1490 bDo_oh = (opt2bSet("-oh", NFILE, fnm));
1491 bDo_ot = (opt2bSet("-ot", NFILE, fnm));
1492 bDo_jc = (opt2bSet("-jc", NFILE, fnm));
1493 bCorr = (opt2bSet("-corr", NFILE, fnm));
1496 fprintf(stderr, "Will calculate autocorrelation\n");
1499 if (core_frac > 1.0)
1501 fprintf(stderr, "core_rotamer fraction > 1.0 ; will use 1.0\n");
1504 if (core_frac < 0.0)
1506 fprintf(stderr, "core_rotamer fraction < 0.0 ; will use 0.0\n");
1510 if (maxchi > MAXCHI)
1512 fprintf(stderr, "Will only calculate first %d Chi dihedrals instead of %d.\n", MAXCHI, maxchi);
1515 bSSHisto = ftp2bSet(efDAT, NFILE, fnm);
1518 /* Find the chi angles using atoms struct and a list of amino acids */
1521 read_tps_conf(ftp2fn(efSTX, NFILE, fnm), top, &pbcType, &x, nullptr, box, FALSE);
1522 t_atoms& atoms = top->atoms;
1523 if (atoms.pdbinfo == nullptr)
1525 snew(atoms.pdbinfo, atoms.nr);
1527 fprintf(log, "Title: %s\n", *top->name);
1530 dlist = mk_dlist(log, &atoms, &nlist, bPhi, bPsi, bChi, bHChi, maxchi, r0, &rt);
1531 fprintf(stderr, "%d residues with dihedrals found\n", nlist);
1535 gmx_fatal(FARGS, "No dihedrals in your structure!\n");
1538 /* Make a linear index for reading all. */
1539 index = make_chi_ind(nlist, dlist, &ndih);
1541 fprintf(stderr, "%d dihedrals found\n", ndih);
1545 /* COMPUTE ALL DIHEDRALS! */
1547 ftp2fn(efTRX, NFILE, fnm), FALSE, TRUE, FALSE, bPBC, 1, &idum, &nf, &time, isize, index, &trans_frac, &aver_angle, dih, oenv);
1549 dt = (time[nf - 1] - time[0]) / (nf - 1); /* might want this for corr or n. transit*/
1554 gmx_fatal(FARGS, "Need at least 2 frames for correlation");
1558 /* put angles in -M_PI to M_PI ! and correct phase factor for phi and psi
1559 * pass nactdih instead of ndih to low_ana_dih_trans
1560 * to prevent accessing off end of arrays when maxchi < 5 or 6. */
1561 nactdih = reset_em_all(nlist, dlist, nf, dih, maxchi);
1565 dump_em_all(nlist, dlist, nf, time, dih, maxchi, bPhi, bPsi, bChi, bOmega, bRAD, oenv);
1568 /* Histogramming & J coupling constants & calc of S2 order params */
1584 ftp2fn(efDAT, NFILE, fnm),
1588 opt2fn("-jc", NFILE, fnm),
1593 * added multiplicity */
1595 snew(multiplicity, ndih);
1596 mk_multiplicity_lookup(multiplicity, maxchi, nlist, dlist, ndih);
1598 std::strcpy(grpname, "All residues, ");
1601 std::strcat(grpname, "Phi ");
1605 std::strcat(grpname, "Psi ");
1609 std::strcat(grpname, "Omega ");
1613 std::strcat(grpname, "Chi 1-");
1614 sprintf(grpname + std::strlen(grpname), "%i", maxchi);
1618 low_ana_dih_trans(bDo_ot,
1619 opt2fn("-ot", NFILE, fnm),
1621 opt2fn("-oh", NFILE, fnm),
1635 /* Order parameters */
1637 opt2fn("-o", NFILE, fnm),
1641 ftp2fn_null(efPDB, NFILE, fnm),
1652 /* Print ramachandran maps! */
1655 do_rama(nf, nlist, dlist, dih, bViol, bRamOmega, oenv);
1660 do_pp2shifts(log, nf, nlist, dlist, dih);
1663 /* rprint S^2, transitions, and rotamer occupancies to log */
1664 traj_t_ns = 0.001 * (time[nf - 1] - time[0]);
1665 pr_dlist(log, nlist, dlist, traj_t_ns, edPrintST, bPhi, bPsi, bChi, bOmega, maxchi);
1666 pr_dlist(log, nlist, dlist, traj_t_ns, edPrintRO, bPhi, bPsi, bChi, bOmega, maxchi);
1668 /* transitions to xvg */
1671 print_transitions(opt2fn("-rt", NFILE, fnm), maxchi, nlist, dlist, traj_t_ns, oenv);
1674 /* chi_product trajectories (ie one "rotamer number" for each residue) */
1675 if (bChiProduct && bChi)
1677 snew(chi_lookup, nlist);
1678 for (i = 0; i < nlist; i++)
1680 snew(chi_lookup[i], maxchi);
1682 mk_chi_lookup(chi_lookup, maxchi, nlist, dlist);
1684 get_chi_product_traj(dih,
1696 opt2fn("-cp", NFILE, fnm),
1699 for (i = 0; i < nlist; i++)
1701 sfree(chi_lookup[i]);
1705 /* Correlation comes last because it messes up the angles */
1708 do_dihcorr(opt2fn("-corr", NFILE, fnm), nf, ndih, dih, dt, nlist, dlist, time, maxchi, bPhi, bPsi, bChi, bOmega, oenv);
1712 do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
1713 do_view(oenv, opt2fn("-jc", NFILE, fnm), "-nxy");
1716 do_view(oenv, opt2fn("-corr", NFILE, fnm), "-nxy");