Introduce SimulatorBuilder
[gromacs.git] / src / gromacs / gmxana / gmx_do_dssp.cpp
bloba466b222c2989d9a63c0a4cb7227eb53c1d971dc
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>
46 #include "gromacs/commandline/pargs.h"
47 #include "gromacs/commandline/viewit.h"
48 #include "gromacs/fileio/confio.h"
49 #include "gromacs/fileio/matio.h"
50 #include "gromacs/fileio/pdbio.h"
51 #include "gromacs/fileio/trxio.h"
52 #include "gromacs/fileio/xvgr.h"
53 #include "gromacs/gmxana/gmx_ana.h"
54 #include "gromacs/gmxana/gstat.h"
55 #include "gromacs/pbcutil/rmpbc.h"
56 #include "gromacs/topology/index.h"
57 #include "gromacs/topology/topology.h"
58 #include "gromacs/utility/arraysize.h"
59 #include "gromacs/utility/cstringutil.h"
60 #include "gromacs/utility/dir_separator.h"
61 #include "gromacs/utility/fatalerror.h"
62 #include "gromacs/utility/futil.h"
63 #include "gromacs/utility/smalloc.h"
64 #include "gromacs/utility/strdb.h"
66 #if GMX_NATIVE_WINDOWS
67 #define NULL_DEVICE "nul"
68 #define popen _popen
69 #define pclose _pclose
70 #else
71 #define NULL_DEVICE "/dev/null"
72 #endif
74 struct DsspInputStrings
76 std::string dptr;
77 std::string pdbfile;
78 std::string tmpfile;
81 static const char* prepareToRedirectStdout(bool bVerbose)
83 return bVerbose ? "" : "2>" NULL_DEVICE;
86 static void printDsspResult(char *dssp, const DsspInputStrings &strings,
87 const std::string &redirectionString)
89 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
90 sprintf(dssp, "%s -i %s %s",
91 strings.dptr.c_str(), strings.pdbfile.c_str(), redirectionString.c_str());
92 #else
93 sprintf(dssp, "%s -i %s -o %s > %s %s",
94 strings.dptr.c_str(), strings.pdbfile.c_str(), strings.tmpfile.c_str(), NULL_DEVICE, redirectionString.c_str());
95 #endif
99 static int strip_dssp(FILE *tapeout, int nres,
100 const gmx_bool bPhobres[], real t,
101 real *acc, FILE *fTArea,
102 t_matrix *mat, int average_area[],
103 const gmx_output_env_t *oenv)
105 static gmx_bool bFirst = TRUE;
106 static char *ssbuf;
107 static int xsize, frame;
108 char buf[STRLEN+1];
109 char SSTP;
110 int i, nr, iacc, nresidues;
111 int naccf, naccb; /* Count hydrophobic and hydrophilic residues */
112 real iaccf, iaccb;
113 t_xpmelmt c;
116 /* Skip header */
119 fgets2(buf, STRLEN, tapeout);
121 while (std::strstr(buf, "KAPPA") == nullptr);
122 if (bFirst)
124 /* Since we also have empty lines in the dssp output (temp) file,
125 * and some line content is saved to the ssbuf variable,
126 * we need more memory than just nres elements. To be shure,
127 * we allocate 2*nres-1, since for each chain there is a
128 * separating line in the temp file. (At most each residue
129 * could have been defined as a separate chain.) */
130 snew(ssbuf, 2*nres-1);
133 iaccb = iaccf = 0;
134 nresidues = 0;
135 naccf = 0;
136 naccb = 0;
137 for (nr = 0; (fgets2(buf, STRLEN, tapeout) != nullptr); nr++)
139 if (buf[13] == '!') /* Chain separator line has '!' at pos. 13 */
141 SSTP = '='; /* Chain separator sign '=' */
143 else
145 SSTP = buf[16] == ' ' ? '~' : buf[16];
147 ssbuf[nr] = SSTP;
149 buf[39] = '\0';
151 /* Only calculate solvent accessible area if needed */
152 if ((nullptr != acc) && (buf[13] != '!'))
154 sscanf(&(buf[34]), "%d", &iacc);
155 acc[nr] = iacc;
156 /* average_area and bPhobres are counted from 0...nres-1 */
157 average_area[nresidues] += iacc;
158 if (bPhobres[nresidues])
160 naccb++;
161 iaccb += iacc;
163 else
165 naccf++;
166 iaccf += iacc;
168 /* Keep track of the residue number (do not count chain separator lines '!') */
169 nresidues++;
172 ssbuf[nr] = '\0';
174 if (bFirst)
176 if (nullptr != acc)
178 fprintf(stderr, "%d residues were classified as hydrophobic and %d as hydrophilic.\n", naccb, naccf);
181 sprintf(mat->title, "Secondary structure");
182 mat->legend[0] = 0;
183 sprintf(mat->label_x, "%s", output_env_get_time_label(oenv).c_str());
184 sprintf(mat->label_y, "Residue");
185 mat->bDiscrete = TRUE;
186 mat->ny = nr;
187 snew(mat->axis_y, nr);
188 for (i = 0; i < nr; i++)
190 mat->axis_y[i] = i+1;
192 mat->axis_x = nullptr;
193 mat->matrix = nullptr;
194 xsize = 0;
195 frame = 0;
196 bFirst = FALSE;
198 if (frame >= xsize)
200 xsize += 10;
201 srenew(mat->axis_x, xsize);
202 srenew(mat->matrix, xsize);
204 mat->axis_x[frame] = t;
205 snew(mat->matrix[frame], nr);
206 c.c2 = 0;
207 for (i = 0; i < nr; i++)
209 c.c1 = ssbuf[i];
210 mat->matrix[frame][i] = std::max(static_cast<t_matelmt>(0), searchcmap(mat->nmap, mat->map, c));
212 frame++;
213 mat->nx = frame;
215 if (fTArea)
217 fprintf(fTArea, "%10g %10g %10g\n", t, 0.01*iaccb, 0.01*iaccf);
220 /* Return the number of lines found in the dssp file (i.e. number
221 * of redidues plus chain separator lines).
222 * This is the number of y elements needed for the area xpm file */
223 return nr;
226 static gmx_bool *bPhobics(t_atoms *atoms)
228 int j, i, nb;
229 char **cb;
230 gmx_bool *bb;
231 int n_surf;
232 char surffn[] = "surface.dat";
233 char **surf_res, **surf_lines;
236 nb = get_lines("phbres.dat", &cb);
237 snew(bb, atoms->nres);
239 n_surf = get_lines(surffn, &surf_lines);
240 snew(surf_res, n_surf);
241 for (i = 0; (i < n_surf); i++)
243 snew(surf_res[i], 5);
244 sscanf(surf_lines[i], "%s", surf_res[i]);
248 for (i = 0, j = 0; (i < atoms->nres); i++)
250 if (-1 != search_str(n_surf, surf_res, *atoms->resinfo[i].name) )
252 bb[j++] = (-1 != search_str(nb, cb, *atoms->resinfo[i].name));
256 if (i != j)
258 fprintf(stderr, "Not all residues were recognized (%d from %d), the result may be inaccurate!\n", j, i);
261 for (i = 0; (i < n_surf); i++)
263 sfree(surf_res[i]);
265 sfree(surf_res);
267 return bb;
270 static void check_oo(t_atoms *atoms)
272 char *OOO;
274 int i;
276 OOO = gmx_strdup("O");
278 for (i = 0; (i < atoms->nr); i++)
280 if (std::strcmp(*(atoms->atomname[i]), "OXT") == 0)
282 *atoms->atomname[i] = OOO;
284 else if (std::strcmp(*(atoms->atomname[i]), "O1") == 0)
286 *atoms->atomname[i] = OOO;
288 else if (std::strcmp(*(atoms->atomname[i]), "OC1") == 0)
290 *atoms->atomname[i] = OOO;
295 static void norm_acc(t_atoms *atoms, int nres,
296 const real av_area[], real norm_av_area[])
298 int i, n, n_surf;
300 char surffn[] = "surface.dat";
301 char **surf_res, **surf_lines;
302 double *surf;
304 n_surf = get_lines(surffn, &surf_lines);
305 snew(surf, n_surf);
306 snew(surf_res, n_surf);
307 for (i = 0; (i < n_surf); i++)
309 snew(surf_res[i], 5);
310 sscanf(surf_lines[i], "%s %lf", surf_res[i], &surf[i]);
313 for (i = 0; (i < nres); i++)
315 n = search_str(n_surf, surf_res, *atoms->resinfo[i].name);
316 if (n != -1)
318 norm_av_area[i] = av_area[i] / surf[n];
320 else
322 fprintf(stderr, "Residue %s not found in surface database (%s)\n",
323 *atoms->resinfo[i].name, surffn);
328 static void prune_ss_legend(t_matrix *mat)
330 gmx_bool *present;
331 int *newnum;
332 int i, r, f, newnmap;
333 t_mapping *newmap;
335 snew(present, mat->nmap);
336 snew(newnum, mat->nmap);
338 for (f = 0; f < mat->nx; f++)
340 for (r = 0; r < mat->ny; r++)
342 present[mat->matrix[f][r]] = TRUE;
346 newnmap = 0;
347 newmap = nullptr;
348 for (i = 0; i < mat->nmap; i++)
350 newnum[i] = -1;
351 if (present[i])
353 newnum[i] = newnmap;
354 newnmap++;
355 srenew(newmap, newnmap);
356 newmap[newnmap-1] = mat->map[i];
359 if (newnmap != mat->nmap)
361 mat->nmap = newnmap;
362 mat->map = newmap;
363 for (f = 0; f < mat->nx; f++)
365 for (r = 0; r < mat->ny; r++)
367 mat->matrix[f][r] = newnum[mat->matrix[f][r]];
373 static void write_sas_mat(const char *fn, real **accr, int nframe, int nres, t_matrix *mat)
375 real lo, hi;
376 int i, j, nlev;
377 t_rgb rlo = {1, 1, 1}, rhi = {0, 0, 0};
378 FILE *fp;
380 if (fn)
382 hi = lo = accr[0][0];
383 for (i = 0; i < nframe; i++)
385 for (j = 0; j < nres; j++)
387 lo = std::min(lo, accr[i][j]);
388 hi = std::max(hi, accr[i][j]);
391 fp = gmx_ffopen(fn, "w");
392 nlev = static_cast<int>(hi-lo+1);
393 write_xpm(fp, 0, "Solvent Accessible Surface", "Surface (A^2)",
394 "Time", "Residue Index", nframe, nres,
395 mat->axis_x, mat->axis_y, accr, lo, hi, rlo, rhi, &nlev);
396 gmx_ffclose(fp);
400 static void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string,
401 const gmx_output_env_t *oenv)
403 FILE *fp;
404 t_mapping *map;
405 int f, r, *count, *total, ss_count, total_count;
406 size_t s;
407 const char** leg;
409 map = mat->map;
410 snew(count, mat->nmap);
411 snew(total, mat->nmap);
412 snew(leg, mat->nmap+1);
413 leg[0] = "Structure";
414 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
416 leg[s+1] = gmx_strdup(map[s].desc);
419 fp = xvgropen(outfile, "Secondary Structure",
420 output_env_get_xvgr_tlabel(oenv), "Number of Residues", oenv);
421 if (output_env_get_print_xvgr_codes(oenv))
423 fprintf(fp, "@ subtitle \"Structure = ");
425 for (s = 0; s < std::strlen(ss_string); s++)
427 if (s > 0)
429 fprintf(fp, " + ");
431 for (f = 0; f < mat->nmap; f++)
433 if (ss_string[s] == map[f].code.c1)
435 fprintf(fp, "%s", map[f].desc);
439 fprintf(fp, "\"\n");
440 xvgr_legend(fp, mat->nmap+1, leg, oenv);
442 total_count = 0;
443 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
445 total[s] = 0;
447 for (f = 0; f < mat->nx; f++)
449 ss_count = 0;
450 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
452 count[s] = 0;
454 for (r = 0; r < mat->ny; r++)
456 count[mat->matrix[f][r]]++;
457 total[mat->matrix[f][r]]++;
459 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
461 if (std::strchr(ss_string, map[s].code.c1))
463 ss_count += count[s];
464 total_count += count[s];
467 fprintf(fp, "%8g %5d", mat->axis_x[f], ss_count);
468 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
470 fprintf(fp, " %5d", count[s]);
472 fprintf(fp, "\n");
474 /* now print column totals */
475 fprintf(fp, "%-8s %5d", "# Totals", total_count);
476 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
478 fprintf(fp, " %5d", total[s]);
480 fprintf(fp, "\n");
482 /* now print probabilities */
483 fprintf(fp, "%-8s %5.2f", "# SS pr.", total_count / static_cast<real>(mat->nx * mat->ny));
484 for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
486 fprintf(fp, " %5.2f", total[s] / static_cast<real>(mat->nx * mat->ny));
488 fprintf(fp, "\n");
490 xvgrclose(fp);
491 sfree(leg);
492 sfree(count);
495 int gmx_do_dssp(int argc, char *argv[])
497 const char *desc[] = {
498 "[THISMODULE] ",
499 "reads a trajectory file and computes the secondary structure for",
500 "each time frame ",
501 "calling the dssp program. If you do not have the dssp program,",
502 "get it from http://swift.cmbi.ru.nl/gv/dssp. [THISMODULE] assumes ",
503 "that the dssp executable is located in ",
504 "[TT]/usr/local/bin/dssp[tt]. If this is not the case, then you should",
505 "set an environment variable [TT]DSSP[tt] pointing to the dssp",
506 "executable, e.g.: [PAR]",
507 "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]",
508 "Since version 2.0.0, dssp is invoked with a syntax that differs",
509 "from earlier versions. If you have an older version of dssp,",
510 "use the [TT]-ver[tt] option to direct do_dssp to use the older syntax.",
511 "By default, do_dssp uses the syntax introduced with version 2.0.0.",
512 "Even newer versions (which at the time of writing are not yet released)",
513 "are assumed to have the same syntax as 2.0.0.[PAR]",
514 "The structure assignment for each residue and time is written to an",
515 "[REF].xpm[ref] matrix file. This file can be visualized with for instance",
516 "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].",
517 "Individual chains are separated by light grey lines in the [REF].xpm[ref] and",
518 "postscript files.",
519 "The number of residues with each secondary structure type and the",
520 "total secondary structure ([TT]-sss[tt]) count as a function of",
521 "time are also written to file ([TT]-sc[tt]).[PAR]",
522 "Solvent accessible surface (SAS) per residue can be calculated, both in",
523 "absolute values (A^2) and in fractions of the maximal accessible",
524 "surface of a residue. The maximal accessible surface is defined as",
525 "the accessible surface of a residue in a chain of glycines.",
526 "[BB]Note[bb] that the program [gmx-sas] can also compute SAS",
527 "and that is more efficient.[PAR]",
528 "Finally, this program can dump the secondary structure in a special file",
529 "[TT]ssdump.dat[tt] for usage in the program [gmx-chi]. Together",
530 "these two programs can be used to analyze dihedral properties as a",
531 "function of secondary structure type."
533 static gmx_bool bVerbose;
534 static const char *ss_string = "HEBT";
535 static int dsspVersion = 2;
536 t_pargs pa[] = {
537 { "-v", FALSE, etBOOL, {&bVerbose},
538 "HIDDENGenerate miles of useless information" },
539 { "-sss", FALSE, etSTR, {&ss_string},
540 "Secondary structures for structure count"},
541 { "-ver", FALSE, etINT, {&dsspVersion},
542 "DSSP major version. Syntax changed with version 2"}
545 t_trxstatus *status;
546 FILE *tapein, *tapeout;
547 FILE *ss, *acc, *fTArea, *tmpf;
548 const char *fnSCount, *fnArea, *fnTArea, *fnAArea;
549 const char *leg[] = { "Phobic", "Phylic" };
550 t_topology top;
551 int ePBC;
552 t_atoms *atoms;
553 t_matrix mat;
554 int nres, nr0, naccr, nres_plus_separators;
555 gmx_bool *bPhbres, bDoAccSurf;
556 real t;
557 int i, j, natoms, nframe = 0;
558 matrix box = {{0}};
559 int gnx;
560 char *grpnm, *ss_str;
561 int *index;
562 rvec *xp, *x;
563 int *average_area;
564 real **accr, *accr_ptr = nullptr, *av_area, *norm_av_area;
565 char pdbfile[32], tmpfile[32];
566 char dssp[256];
567 const char *dptr;
568 gmx_output_env_t *oenv;
569 gmx_rmpbc_t gpbc = nullptr;
571 t_filenm fnm[] = {
572 { efTRX, "-f", nullptr, ffREAD },
573 { efTPS, nullptr, nullptr, ffREAD },
574 { efNDX, nullptr, nullptr, ffOPTRD },
575 { efDAT, "-ssdump", "ssdump", ffOPTWR },
576 { efMAP, "-map", "ss", ffLIBRD },
577 { efXPM, "-o", "ss", ffWRITE },
578 { efXVG, "-sc", "scount", ffWRITE },
579 { efXPM, "-a", "area", ffOPTWR },
580 { efXVG, "-ta", "totarea", ffOPTWR },
581 { efXVG, "-aa", "averarea", ffOPTWR }
583 #define NFILE asize(fnm)
585 if (!parse_common_args(&argc, argv,
586 PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT,
587 NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
589 return 0;
591 fnSCount = opt2fn("-sc", NFILE, fnm);
592 fnArea = opt2fn_null("-a", NFILE, fnm);
593 fnTArea = opt2fn_null("-ta", NFILE, fnm);
594 fnAArea = opt2fn_null("-aa", NFILE, fnm);
595 bDoAccSurf = ((fnArea != nullptr) || (fnTArea != nullptr) || (fnAArea != nullptr));
597 read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xp, nullptr, box, FALSE);
598 atoms = &(top.atoms);
599 check_oo(atoms);
600 bPhbres = bPhobics(atoms);
602 get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpnm);
603 nres = 0;
604 nr0 = -1;
605 for (i = 0; (i < gnx); i++)
607 if (atoms->atom[index[i]].resind != nr0)
609 nr0 = atoms->atom[index[i]].resind;
610 nres++;
613 fprintf(stderr, "There are %d residues in your selected group\n", nres);
615 std::strcpy(pdbfile, "ddXXXXXX");
616 gmx_tmpnam(pdbfile);
617 if ((tmpf = fopen(pdbfile, "w")) == nullptr)
619 sprintf(pdbfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
620 gmx_tmpnam(pdbfile);
621 if ((tmpf = fopen(pdbfile, "w")) == nullptr)
623 gmx_fatal(FARGS, "Can not open tmp file %s", pdbfile);
626 fclose(tmpf);
628 std::strcpy(tmpfile, "ddXXXXXX");
629 gmx_tmpnam(tmpfile);
630 if ((tmpf = fopen(tmpfile, "w")) == nullptr)
632 sprintf(tmpfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
633 gmx_tmpnam(tmpfile);
634 if ((tmpf = fopen(tmpfile, "w")) == nullptr)
636 gmx_fatal(FARGS, "Can not open tmp file %s", tmpfile);
639 fclose(tmpf);
641 if ((dptr = getenv("DSSP")) == nullptr)
643 dptr = "/usr/local/bin/dssp";
645 if (!gmx_fexist(dptr))
647 gmx_fatal(FARGS, "DSSP executable (%s) does not exist (use setenv DSSP)",
648 dptr);
650 std::string redirectionString;
651 redirectionString = prepareToRedirectStdout(bVerbose);
652 DsspInputStrings dsspStrings;
653 dsspStrings.dptr = dptr;
654 dsspStrings.pdbfile = pdbfile;
655 dsspStrings.tmpfile = tmpfile;
656 if (dsspVersion >= 2)
658 if (dsspVersion > 2)
660 printf("\nWARNING: You use DSSP version %d, which is not explicitly\nsupported by do_dssp. Assuming version 2 syntax.\n\n", dsspVersion);
663 printDsspResult(dssp, dsspStrings, redirectionString);
665 else
667 if (bDoAccSurf)
669 dsspStrings.dptr.clear();
671 else
673 dsspStrings.dptr = "-na";
675 printDsspResult(dssp, dsspStrings, redirectionString);
677 fprintf(stderr, "dssp cmd='%s'\n", dssp);
679 if (fnTArea)
681 fTArea = xvgropen(fnTArea, "Solvent Accessible Surface Area",
682 output_env_get_xvgr_tlabel(oenv), "Area (nm\\S2\\N)", oenv);
683 xvgr_legend(fTArea, 2, leg, oenv);
685 else
687 fTArea = nullptr;
690 mat.map = nullptr;
691 mat.nmap = readcmap(opt2fn("-map", NFILE, fnm), &(mat.map));
693 natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
694 if (natoms > atoms->nr)
696 gmx_fatal(FARGS, "\nTrajectory does not match topology!");
698 if (gnx > natoms)
700 gmx_fatal(FARGS, "\nTrajectory does not match selected group!");
703 snew(average_area, atoms->nres);
704 snew(av_area, atoms->nres);
705 snew(norm_av_area, atoms->nres);
706 accr = nullptr;
707 naccr = 0;
709 gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
712 t = output_env_conv_time(oenv, t);
713 if (bDoAccSurf && nframe >= naccr)
715 naccr += 10;
716 srenew(accr, naccr);
717 for (i = naccr-10; i < naccr; i++)
719 snew(accr[i], 2*atoms->nres-1);
722 gmx_rmpbc(gpbc, natoms, box, x);
723 tapein = gmx_ffopen(pdbfile, "w");
724 write_pdbfile_indexed(tapein, nullptr, atoms, x, ePBC, box, ' ', -1, gnx, index, nullptr, FALSE);
725 gmx_ffclose(tapein);
726 /* strip_dssp returns the number of lines found in the dssp file, i.e.
727 * the number of residues plus the separator lines */
729 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
730 if (nullptr == (tapeout = popen(dssp, "r")))
731 #else
732 if (0 != system(dssp) || nullptr == (tapeout = gmx_ffopen(tmpfile, "r")))
733 #endif
735 remove(pdbfile);
736 remove(tmpfile);
737 gmx_fatal(FARGS, "Failed to execute command: %s\n"
738 "Try specifying your dssp version with the -ver option.", dssp);
740 if (bDoAccSurf)
742 accr_ptr = accr[nframe];
744 /* strip_dssp returns the number of lines found in the dssp file, i.e.
745 * the number of residues plus the separator lines */
746 nres_plus_separators = strip_dssp(tapeout, nres, bPhbres, t,
747 accr_ptr, fTArea, &mat, average_area, oenv);
748 #if HAVE_PIPES || GMX_NATIVE_WINDOWS
749 pclose(tapeout);
750 #else
751 gmx_ffclose(tapeout);
752 #endif
753 remove(tmpfile);
754 remove(pdbfile);
755 nframe++;
757 while (read_next_x(oenv, status, &t, x, box));
758 fprintf(stderr, "\n");
759 close_trx(status);
760 if (fTArea)
762 xvgrclose(fTArea);
764 gmx_rmpbc_done(gpbc);
766 prune_ss_legend(&mat);
768 ss = opt2FILE("-o", NFILE, fnm, "w");
769 mat.flags = 0;
770 write_xpm_m(ss, mat);
771 gmx_ffclose(ss);
773 if (opt2bSet("-ssdump", NFILE, fnm))
775 ss = opt2FILE("-ssdump", NFILE, fnm, "w");
776 snew(ss_str, nres+1);
777 fprintf(ss, "%d\n", nres);
778 for (j = 0; j < mat.nx; j++)
780 for (i = 0; (i < mat.ny); i++)
782 ss_str[i] = mat.map[mat.matrix[j][i]].code.c1;
784 ss_str[i] = '\0';
785 fprintf(ss, "%s\n", ss_str);
787 gmx_ffclose(ss);
788 sfree(ss_str);
790 analyse_ss(fnSCount, &mat, ss_string, oenv);
792 if (bDoAccSurf)
794 write_sas_mat(fnArea, accr, nframe, nres_plus_separators, &mat);
796 for (i = 0; i < atoms->nres; i++)
798 av_area[i] = (average_area[i] / static_cast<real>(nframe));
801 norm_acc(atoms, nres, av_area, norm_av_area);
803 if (fnAArea)
805 acc = xvgropen(fnAArea, "Average Accessible Area",
806 "Residue", "A\\S2", oenv);
807 for (i = 0; (i < nres); i++)
809 fprintf(acc, "%5d %10g %10g\n", i+1, av_area[i], norm_av_area[i]);
811 xvgrclose(acc);
815 view_all(oenv, NFILE, fnm);
817 return 0;