Remove unused function generate_excls and make clean_excls static
[gromacs.git] / src / gromacs / gmxana / gmx_do_dssp.cpp
blobe0ab634dc4d7912d5ebeaa2bf29da3e490223cc7
1 /*
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) 2012,2013,2014,2015,2017,2018,2019, 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.
37 #include "gmxpre.h"
39 #include "config.h"
41 #include <cstdlib>
42 #include <cstring>
44 #include <algorithm>
45 #include <numeric>
47 #include "gromacs/commandline/pargs.h"
48 #include "gromacs/commandline/viewit.h"
49 #include "gromacs/fileio/confio.h"
50 #include "gromacs/fileio/matio.h"
51 #include "gromacs/fileio/pdbio.h"
52 #include "gromacs/fileio/trxio.h"
53 #include "gromacs/fileio/xvgr.h"
54 #include "gromacs/gmxana/gmx_ana.h"
55 #include "gromacs/gmxana/gstat.h"
56 #include "gromacs/pbcutil/rmpbc.h"
57 #include "gromacs/topology/index.h"
58 #include "gromacs/topology/topology.h"
59 #include "gromacs/utility/arraysize.h"
60 #include "gromacs/utility/cstringutil.h"
61 #include "gromacs/utility/dir_separator.h"
62 #include "gromacs/utility/fatalerror.h"
63 #include "gromacs/utility/futil.h"
64 #include "gromacs/utility/smalloc.h"
65 #include "gromacs/utility/strdb.h"
67 #if GMX_NATIVE_WINDOWS
68 #define NULL_DEVICE "nul"
69 #define popen _popen
70 #define pclose _pclose
71 #else
72 #define NULL_DEVICE "/dev/null"
73 #endif
75 struct DsspInputStrings
77 std::string dptr;
78 std::string pdbfile;
79 std::string tmpfile;
82 static const char* prepareToRedirectStdout(bool bVerbose)
84 return bVerbose ? "" : "2>" NULL_DEVICE;
87 static void printDsspResult(char *dssp, const DsspInputStrings &strings,
88 const std::string &redirectionString)
90 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
91 sprintf(dssp, "%s -i %s %s",
92 strings.dptr.c_str(), strings.pdbfile.c_str(), redirectionString.c_str());
93 #else
94 sprintf(dssp, "%s -i %s -o %s > %s %s",
95 strings.dptr.c_str(), strings.pdbfile.c_str(), strings.tmpfile.c_str(), NULL_DEVICE, redirectionString.c_str());
96 #endif
100 static int strip_dssp(FILE *tapeout, int nres,
101 const gmx_bool bPhobres[], real t,
102 real *acc, FILE *fTArea,
103 t_matrix *mat, int average_area[],
104 const gmx_output_env_t *oenv)
106 static gmx_bool bFirst = TRUE;
107 static char *ssbuf;
108 char buf[STRLEN+1];
109 char SSTP;
110 int nr, iacc, nresidues;
111 int naccf, naccb; /* Count hydrophobic and hydrophilic residues */
112 real iaccf, iaccb;
115 /* Skip header */
118 fgets2(buf, STRLEN, tapeout);
120 while (std::strstr(buf, "KAPPA") == nullptr);
121 if (bFirst)
123 /* Since we also have empty lines in the dssp output (temp) file,
124 * and some line content is saved to the ssbuf variable,
125 * we need more memory than just nres elements. To be shure,
126 * we allocate 2*nres-1, since for each chain there is a
127 * separating line in the temp file. (At most each residue
128 * could have been defined as a separate chain.) */
129 snew(ssbuf, 2*nres-1);
132 iaccb = iaccf = 0;
133 nresidues = 0;
134 naccf = 0;
135 naccb = 0;
136 for (nr = 0; (fgets2(buf, STRLEN, tapeout) != nullptr); nr++)
138 if (buf[13] == '!') /* Chain separator line has '!' at pos. 13 */
140 SSTP = '='; /* Chain separator sign '=' */
142 else
144 SSTP = buf[16] == ' ' ? '~' : buf[16];
146 ssbuf[nr] = SSTP;
148 buf[39] = '\0';
150 /* Only calculate solvent accessible area if needed */
151 if ((nullptr != acc) && (buf[13] != '!'))
153 sscanf(&(buf[34]), "%d", &iacc);
154 acc[nr] = iacc;
155 /* average_area and bPhobres are counted from 0...nres-1 */
156 average_area[nresidues] += iacc;
157 if (bPhobres[nresidues])
159 naccb++;
160 iaccb += iacc;
162 else
164 naccf++;
165 iaccf += iacc;
167 /* Keep track of the residue number (do not count chain separator lines '!') */
168 nresidues++;
171 ssbuf[nr] = '\0';
173 if (bFirst)
175 if (nullptr != acc)
177 fprintf(stderr, "%d residues were classified as hydrophobic and %d as hydrophilic.\n", naccb, naccf);
180 mat->title = "Secondary structure";
181 mat->legend = "";
182 mat->label_x = output_env_get_time_label(oenv);
183 mat->label_y = "Residue";
184 mat->bDiscrete = true;
185 mat->ny = nr;
186 mat->axis_y.resize(nr);
187 std::iota(mat->axis_y.begin(), mat->axis_y.end(), 1);
188 mat->axis_x.resize(0);
189 mat->matrix.resize(0, 0);
190 bFirst = false;
192 mat->axis_x.push_back(t);
193 mat->matrix.resize(mat->matrix.extent(0), nr);
194 mat->nx = mat->matrix.extent(0);
195 auto columnIndex = mat->nx - 1;
196 for (int i = 0; i < nr; i++)
198 t_xpmelmt c = {ssbuf[i], 0};
199 mat->matrix(columnIndex, i) = std::max(static_cast<t_matelmt>(0), searchcmap(mat->map, c));
202 if (fTArea)
204 fprintf(fTArea, "%10g %10g %10g\n", t, 0.01*iaccb, 0.01*iaccf);
207 /* Return the number of lines found in the dssp file (i.e. number
208 * of redidues plus chain separator lines).
209 * This is the number of y elements needed for the area xpm file */
210 return nr;
213 static gmx_bool *bPhobics(t_atoms *atoms)
215 int j, i, nb;
216 char **cb;
217 gmx_bool *bb;
218 int n_surf;
219 char surffn[] = "surface.dat";
220 char **surf_res, **surf_lines;
223 nb = get_lines("phbres.dat", &cb);
224 snew(bb, atoms->nres);
226 n_surf = get_lines(surffn, &surf_lines);
227 snew(surf_res, n_surf);
228 for (i = 0; (i < n_surf); i++)
230 snew(surf_res[i], 5);
231 sscanf(surf_lines[i], "%s", surf_res[i]);
235 for (i = 0, j = 0; (i < atoms->nres); i++)
237 if (-1 != search_str(n_surf, surf_res, *atoms->resinfo[i].name) )
239 bb[j++] = (-1 != search_str(nb, cb, *atoms->resinfo[i].name));
243 if (i != j)
245 fprintf(stderr, "Not all residues were recognized (%d from %d), the result may be inaccurate!\n", j, i);
248 for (i = 0; (i < n_surf); i++)
250 sfree(surf_res[i]);
252 sfree(surf_res);
254 return bb;
257 static void check_oo(t_atoms *atoms)
259 char *OOO;
261 int i;
263 OOO = gmx_strdup("O");
265 for (i = 0; (i < atoms->nr); i++)
267 if (std::strcmp(*(atoms->atomname[i]), "OXT") == 0)
269 *atoms->atomname[i] = OOO;
271 else if (std::strcmp(*(atoms->atomname[i]), "O1") == 0)
273 *atoms->atomname[i] = OOO;
275 else if (std::strcmp(*(atoms->atomname[i]), "OC1") == 0)
277 *atoms->atomname[i] = OOO;
282 static void norm_acc(t_atoms *atoms, int nres,
283 const real av_area[], real norm_av_area[])
285 int i, n, n_surf;
287 char surffn[] = "surface.dat";
288 char **surf_res, **surf_lines;
289 double *surf;
291 n_surf = get_lines(surffn, &surf_lines);
292 snew(surf, n_surf);
293 snew(surf_res, n_surf);
294 for (i = 0; (i < n_surf); i++)
296 snew(surf_res[i], 5);
297 sscanf(surf_lines[i], "%s %lf", surf_res[i], &surf[i]);
300 for (i = 0; (i < nres); i++)
302 n = search_str(n_surf, surf_res, *atoms->resinfo[i].name);
303 if (n != -1)
305 norm_av_area[i] = av_area[i] / surf[n];
307 else
309 fprintf(stderr, "Residue %s not found in surface database (%s)\n",
310 *atoms->resinfo[i].name, surffn);
315 static void prune_ss_legend(t_matrix *mat)
317 std::vector<bool> isPresent(mat->map.size());
318 std::vector<int> newnum(mat->map.size());
319 std::vector<t_mapping> newmap;
321 for (int f = 0; f < mat->nx; f++)
323 for (int r = 0; r < mat->ny; r++)
325 isPresent[mat->matrix(f, r)] = true;
329 for (size_t i = 0; i < mat->map.size(); i++)
331 newnum[i] = -1;
332 if (isPresent[i])
334 newnum[i] = newmap.size();
335 newmap.emplace_back(mat->map[i]);
338 if (newmap.size() != mat->map.size())
340 std::swap(mat->map, newmap);
341 for (int f = 0; f < mat->nx; f++)
343 for (int r = 0; r < mat->ny; r++)
345 mat->matrix(f, r) = newnum[mat->matrix(f, r)];
351 static void write_sas_mat(const char *fn, real **accr, int nframe, int nres, t_matrix *mat)
353 real lo, hi;
354 int i, j, nlev;
355 t_rgb rlo = {1, 1, 1}, rhi = {0, 0, 0};
356 FILE *fp;
358 if (fn)
360 hi = lo = accr[0][0];
361 for (i = 0; i < nframe; i++)
363 for (j = 0; j < nres; j++)
365 lo = std::min(lo, accr[i][j]);
366 hi = std::max(hi, accr[i][j]);
369 fp = gmx_ffopen(fn, "w");
370 nlev = static_cast<int>(hi-lo+1);
371 write_xpm(fp, 0, "Solvent Accessible Surface", "Surface (A^2)",
372 "Time", "Residue Index", nframe, nres,
373 mat->axis_x.data(), mat->axis_y.data(), accr, lo, hi, rlo, rhi, &nlev);
374 gmx_ffclose(fp);
378 static void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string,
379 const gmx_output_env_t *oenv)
381 FILE *fp;
382 int ss_count, total_count;
384 gmx::ArrayRef<t_mapping> map = mat->map;
385 std::vector<int> count(map.size());
386 std::vector<int> total(map.size(), 0);
387 // This copying would not be necessary if xvgr_legend could take a
388 // view of string views
389 std::vector<std::string> leg;
390 leg.reserve(map.size()+1);
391 leg.emplace_back("Structure");
392 for (const auto &m : map)
394 leg.emplace_back(m.desc);
397 fp = xvgropen(outfile, "Secondary Structure",
398 output_env_get_xvgr_tlabel(oenv), "Number of Residues", oenv);
399 if (output_env_get_print_xvgr_codes(oenv))
401 fprintf(fp, "@ subtitle \"Structure = ");
403 for (size_t s = 0; s < std::strlen(ss_string); s++)
405 if (s > 0)
407 fprintf(fp, " + ");
409 for (const auto &m : map)
411 if (ss_string[s] == m.code.c1)
413 fprintf(fp, "%s", m.desc);
417 fprintf(fp, "\"\n");
418 xvgrLegend(fp, leg, oenv);
420 total_count = 0;
421 for (int f = 0; f < mat->nx; f++)
423 ss_count = 0;
424 for (auto &c : count)
426 c = 0;
428 for (int r = 0; r < mat->ny; r++)
430 count[mat->matrix(f, r)]++;
431 total[mat->matrix(f, r)]++;
433 for (gmx::index s = 0; s != gmx::ssize(map); ++s)
435 if (std::strchr(ss_string, map[s].code.c1))
437 ss_count += count[s];
438 total_count += count[s];
441 fprintf(fp, "%8g %5d", mat->axis_x[f], ss_count);
442 for (const auto &c : count)
444 fprintf(fp, " %5d", c);
446 fprintf(fp, "\n");
448 /* now print column totals */
449 fprintf(fp, "%-8s %5d", "# Totals", total_count);
450 for (const auto &t : total)
452 fprintf(fp, " %5d", t);
454 fprintf(fp, "\n");
456 /* now print probabilities */
457 fprintf(fp, "%-8s %5.2f", "# SS pr.", total_count / static_cast<real>(mat->nx * mat->ny));
458 for (const auto &t : total)
460 fprintf(fp, " %5.2f", t / static_cast<real>(mat->nx * mat->ny));
462 fprintf(fp, "\n");
464 xvgrclose(fp);
467 int gmx_do_dssp(int argc, char *argv[])
469 const char *desc[] = {
470 "[THISMODULE] ",
471 "reads a trajectory file and computes the secondary structure for",
472 "each time frame ",
473 "calling the dssp program. If you do not have the dssp program,",
474 "get it from http://swift.cmbi.ru.nl/gv/dssp. [THISMODULE] assumes ",
475 "that the dssp executable is located in ",
476 "[TT]/usr/local/bin/dssp[tt]. If this is not the case, then you should",
477 "set an environment variable [TT]DSSP[tt] pointing to the dssp",
478 "executable, e.g.: [PAR]",
479 "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]",
480 "Since version 2.0.0, dssp is invoked with a syntax that differs",
481 "from earlier versions. If you have an older version of dssp,",
482 "use the [TT]-ver[tt] option to direct do_dssp to use the older syntax.",
483 "By default, do_dssp uses the syntax introduced with version 2.0.0.",
484 "Even newer versions (which at the time of writing are not yet released)",
485 "are assumed to have the same syntax as 2.0.0.[PAR]",
486 "The structure assignment for each residue and time is written to an",
487 "[REF].xpm[ref] matrix file. This file can be visualized with for instance",
488 "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].",
489 "Individual chains are separated by light grey lines in the [REF].xpm[ref] and",
490 "postscript files.",
491 "The number of residues with each secondary structure type and the",
492 "total secondary structure ([TT]-sss[tt]) count as a function of",
493 "time are also written to file ([TT]-sc[tt]).[PAR]",
494 "Solvent accessible surface (SAS) per residue can be calculated, both in",
495 "absolute values (A^2) and in fractions of the maximal accessible",
496 "surface of a residue. The maximal accessible surface is defined as",
497 "the accessible surface of a residue in a chain of glycines.",
498 "[BB]Note[bb] that the program [gmx-sas] can also compute SAS",
499 "and that is more efficient.[PAR]",
500 "Finally, this program can dump the secondary structure in a special file",
501 "[TT]ssdump.dat[tt] for usage in the program [gmx-chi]. Together",
502 "these two programs can be used to analyze dihedral properties as a",
503 "function of secondary structure type."
505 static gmx_bool bVerbose;
506 static const char *ss_string = "HEBT";
507 static int dsspVersion = 2;
508 t_pargs pa[] = {
509 { "-v", FALSE, etBOOL, {&bVerbose},
510 "HIDDENGenerate miles of useless information" },
511 { "-sss", FALSE, etSTR, {&ss_string},
512 "Secondary structures for structure count"},
513 { "-ver", FALSE, etINT, {&dsspVersion},
514 "DSSP major version. Syntax changed with version 2"}
517 t_trxstatus *status;
518 FILE *tapein, *tapeout;
519 FILE *ss, *acc, *fTArea, *tmpf;
520 const char *fnSCount, *fnArea, *fnTArea, *fnAArea;
521 const char *leg[] = { "Phobic", "Phylic" };
522 t_topology top;
523 int ePBC;
524 t_atoms *atoms;
525 t_matrix mat;
526 int nres, nr0, naccr, nres_plus_separators;
527 gmx_bool *bPhbres, bDoAccSurf;
528 real t;
529 int natoms, nframe = 0;
530 matrix box = {{0}};
531 int gnx;
532 char *grpnm;
533 int *index;
534 rvec *xp, *x;
535 int *average_area;
536 real **accr, *accr_ptr = nullptr, *av_area, *norm_av_area;
537 char pdbfile[32], tmpfile[32];
538 char dssp[256];
539 const char *dptr;
540 gmx_output_env_t *oenv;
541 gmx_rmpbc_t gpbc = nullptr;
543 t_filenm fnm[] = {
544 { efTRX, "-f", nullptr, ffREAD },
545 { efTPS, nullptr, nullptr, ffREAD },
546 { efNDX, nullptr, nullptr, ffOPTRD },
547 { efDAT, "-ssdump", "ssdump", ffOPTWR },
548 { efMAP, "-map", "ss", ffLIBRD },
549 { efXPM, "-o", "ss", ffWRITE },
550 { efXVG, "-sc", "scount", ffWRITE },
551 { efXPM, "-a", "area", ffOPTWR },
552 { efXVG, "-ta", "totarea", ffOPTWR },
553 { efXVG, "-aa", "averarea", ffOPTWR }
555 #define NFILE asize(fnm)
557 if (!parse_common_args(&argc, argv,
558 PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT,
559 NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
561 return 0;
563 fnSCount = opt2fn("-sc", NFILE, fnm);
564 fnArea = opt2fn_null("-a", NFILE, fnm);
565 fnTArea = opt2fn_null("-ta", NFILE, fnm);
566 fnAArea = opt2fn_null("-aa", NFILE, fnm);
567 bDoAccSurf = ((fnArea != nullptr) || (fnTArea != nullptr) || (fnAArea != nullptr));
569 read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xp, nullptr, box, FALSE);
570 atoms = &(top.atoms);
571 check_oo(atoms);
572 bPhbres = bPhobics(atoms);
574 get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpnm);
575 nres = 0;
576 nr0 = -1;
577 for (int i = 0; (i < gnx); i++)
579 if (atoms->atom[index[i]].resind != nr0)
581 nr0 = atoms->atom[index[i]].resind;
582 nres++;
585 fprintf(stderr, "There are %d residues in your selected group\n", nres);
587 std::strcpy(pdbfile, "ddXXXXXX");
588 gmx_tmpnam(pdbfile);
589 if ((tmpf = fopen(pdbfile, "w")) == nullptr)
591 sprintf(pdbfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
592 gmx_tmpnam(pdbfile);
593 if ((tmpf = fopen(pdbfile, "w")) == nullptr)
595 gmx_fatal(FARGS, "Can not open tmp file %s", pdbfile);
598 fclose(tmpf);
600 std::strcpy(tmpfile, "ddXXXXXX");
601 gmx_tmpnam(tmpfile);
602 if ((tmpf = fopen(tmpfile, "w")) == nullptr)
604 sprintf(tmpfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
605 gmx_tmpnam(tmpfile);
606 if ((tmpf = fopen(tmpfile, "w")) == nullptr)
608 gmx_fatal(FARGS, "Can not open tmp file %s", tmpfile);
611 fclose(tmpf);
613 if ((dptr = getenv("DSSP")) == nullptr)
615 dptr = "/usr/local/bin/dssp";
617 if (!gmx_fexist(dptr))
619 gmx_fatal(FARGS, "DSSP executable (%s) does not exist (use setenv DSSP)",
620 dptr);
622 std::string redirectionString;
623 redirectionString = prepareToRedirectStdout(bVerbose);
624 DsspInputStrings dsspStrings;
625 dsspStrings.dptr = dptr;
626 dsspStrings.pdbfile = pdbfile;
627 dsspStrings.tmpfile = tmpfile;
628 if (dsspVersion >= 2)
630 if (dsspVersion > 2)
632 printf("\nWARNING: You use DSSP version %d, which is not explicitly\nsupported by do_dssp. Assuming version 2 syntax.\n\n", dsspVersion);
635 printDsspResult(dssp, dsspStrings, redirectionString);
637 else
639 if (bDoAccSurf)
641 dsspStrings.dptr.clear();
643 else
645 dsspStrings.dptr = "-na";
647 printDsspResult(dssp, dsspStrings, redirectionString);
649 fprintf(stderr, "dssp cmd='%s'\n", dssp);
651 if (fnTArea)
653 fTArea = xvgropen(fnTArea, "Solvent Accessible Surface Area",
654 output_env_get_xvgr_tlabel(oenv), "Area (nm\\S2\\N)", oenv);
655 xvgr_legend(fTArea, 2, leg, oenv);
657 else
659 fTArea = nullptr;
662 mat.map = readcmap(opt2fn("-map", NFILE, fnm));
664 natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
665 if (natoms > atoms->nr)
667 gmx_fatal(FARGS, "\nTrajectory does not match topology!");
669 if (gnx > natoms)
671 gmx_fatal(FARGS, "\nTrajectory does not match selected group!");
674 snew(average_area, atoms->nres);
675 snew(av_area, atoms->nres);
676 snew(norm_av_area, atoms->nres);
677 accr = nullptr;
678 naccr = 0;
680 gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
683 t = output_env_conv_time(oenv, t);
684 if (bDoAccSurf && nframe >= naccr)
686 naccr += 10;
687 srenew(accr, naccr);
688 for (int i = naccr-10; i < naccr; i++)
690 snew(accr[i], 2*atoms->nres-1);
693 gmx_rmpbc(gpbc, natoms, box, x);
694 tapein = gmx_ffopen(pdbfile, "w");
695 write_pdbfile_indexed(tapein, nullptr, atoms, x, ePBC, box, ' ', -1, gnx, index, nullptr, FALSE);
696 gmx_ffclose(tapein);
697 /* strip_dssp returns the number of lines found in the dssp file, i.e.
698 * the number of residues plus the separator lines */
700 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
701 if (nullptr == (tapeout = popen(dssp, "r")))
702 #else
703 if (0 != system(dssp) || nullptr == (tapeout = gmx_ffopen(tmpfile, "r")))
704 #endif
706 remove(pdbfile);
707 remove(tmpfile);
708 gmx_fatal(FARGS, "Failed to execute command: %s\n"
709 "Try specifying your dssp version with the -ver option.", dssp);
711 if (bDoAccSurf)
713 accr_ptr = accr[nframe];
715 /* strip_dssp returns the number of lines found in the dssp file, i.e.
716 * the number of residues plus the separator lines */
717 nres_plus_separators = strip_dssp(tapeout, nres, bPhbres, t,
718 accr_ptr, fTArea, &mat, average_area, oenv);
719 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
720 pclose(tapeout);
721 #else
722 gmx_ffclose(tapeout);
723 #endif
724 remove(tmpfile);
725 remove(pdbfile);
726 nframe++;
728 while (read_next_x(oenv, status, &t, x, box));
729 fprintf(stderr, "\n");
730 close_trx(status);
731 if (fTArea)
733 xvgrclose(fTArea);
735 gmx_rmpbc_done(gpbc);
737 prune_ss_legend(&mat);
739 ss = opt2FILE("-o", NFILE, fnm, "w");
740 mat.flags = 0;
741 write_xpm_m(ss, mat);
742 gmx_ffclose(ss);
744 if (opt2bSet("-ssdump", NFILE, fnm))
746 ss = opt2FILE("-ssdump", NFILE, fnm, "w");
747 fprintf(ss, "%d\n", nres);
748 for (gmx::index j = 0; j != mat.matrix.extent(0); ++j)
750 auto row = mat.matrix.asView()[j];
751 for (gmx::index i = 0; i != row.extent(0); ++i)
753 fputc(mat.map[row[i]].code.c1, ss);
755 fputc('\n', ss);
757 gmx_ffclose(ss);
759 analyse_ss(fnSCount, &mat, ss_string, oenv);
761 if (bDoAccSurf)
763 write_sas_mat(fnArea, accr, nframe, nres_plus_separators, &mat);
765 for (int i = 0; i < atoms->nres; i++)
767 av_area[i] = (average_area[i] / static_cast<real>(nframe));
770 norm_acc(atoms, nres, av_area, norm_av_area);
772 if (fnAArea)
774 acc = xvgropen(fnAArea, "Average Accessible Area",
775 "Residue", "A\\S2", oenv);
776 for (int i = 0; (i < nres); i++)
778 fprintf(acc, "%5d %10g %10g\n", i+1, av_area[i], norm_av_area[i]);
780 xvgrclose(acc);
784 view_all(oenv, NFILE, fnm);
786 return 0;