2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements gmx::analysismodules::Freevolume.
39 * \author Titov Anatoly <Wapuk-cobaka@yandex.ru>
40 * \ingroup module_trajectoryanalysis
53 #include <gromacs/trajectoryanalysis.h>
54 #include <gromacs/utility/smalloc.h>
55 #include <gromacs/math/do_fit.h>
56 #include <gromacs/trajectoryanalysis/topologyinformation.h>
57 #include "gromacs/topology/topology.h"
58 #include "gromacs/topology/index.h"
64 const std::vector< std::vector< std::vector< double > > > read_correlation_matrix_file(const char* file_name, unsigned long size, unsigned int length)
67 std::vector< std::vector< std::vector< double > > > crrlts;
68 file = std::fopen(file_name, "r+");
69 std::vector< double > c;
71 std::vector< std::vector< double > > b;
73 crrlts.resize(length + 1, b);
75 std::cout << "reading correlations from a file:\n";
76 for (unsigned int i = 0; i < length + 1; i++) {
77 //char *t1 = std::fgets(a, 100, file);
78 int t0 = 0, t1 = std::fscanf(file, "%d\n", &t0);
79 std::cout << t0 << " | ";
83 for (unsigned int j = 0; j < size; j++) {
84 for (unsigned int f = 0; f < size; f++) {
85 int t2 = std::fscanf(file, "%lf ", &crrlts[i][j][f]);
94 template< typename T >
95 unsigned int posSrch(std::vector< T > a, T b) {
96 for (unsigned i01 = 0; i01 < a.size(); i01++) {
105 void make_rout_file(double crl_border, std::vector< int > indx, std::vector< std::string > resNames, std::vector< std::vector< std::vector< std::pair< unsigned int, unsigned int > > > > rout, const char* file_name01)
108 file01 = std::fopen(file_name01, "w+");
110 unsigned int f, pre = 0;
111 std::vector< std::tuple< int, int, std::vector< int > > > table;
113 for (unsigned int i01 = 0; i01 < rout.size(); i01++) {
115 for (unsigned int i02 = i01 + 1; i02 <rout.size(); i02++) {
116 if (rout[i02] == rout[i01]) {
123 std::fprintf(file01, "\ntau = %d | correlations >= %0.2f\n\n", i01, crl_border);
125 std::fprintf(file01, "\ntau = [%d ; %d] | correlations >= %0.2f\n\n", i01, f, crl_border);
127 for (unsigned int i02 = 0; i02 < rout[i01].size(); i02++) {
128 for (unsigned int i03 = 0; i03 < rout[i01][i02].size(); i03++) {
129 std::fprintf(file01, "cgo_arrow (id %3d), (id %3d), radius=0.075\n", indx[rout[i01][i02][i03].first] + 1, indx[rout[i01][i02][i03].second] + 1);
131 std::fprintf(file01, "\n");
134 for (unsigned int i02 = 0; i02 < rout[i01].size(); i02++) {
135 for (unsigned int i03 = 0; i03 < rout[i01][i02].size(); i03++) {
137 for (unsigned int i04 = 0; i04 < table.size(); i04++) {
138 if (std::get<0>(table[i04]) == indx[rout[i01][i02][i03].first] + 1) {
139 std::get<1>(table[i04])++;
140 std::get<2>(table[i04]).push_back(indx[rout[i01][i02][i03].second] + 1);
142 } else if (std::get<0>(table[i04]) == indx[rout[i01][i02][i03].second] + 1) {
143 std::get<1>(table[i04])++;
144 std::get<2>(table[i04]).push_back(indx[rout[i01][i02][i03].first] + 1);
149 std::vector< int > a;
151 a.push_back(indx[rout[i01][i02][i03].second] + 1);
152 table.push_back(std::make_tuple(indx[rout[i01][i02][i03].first] + 1, 1, a));
154 a.push_back(indx[rout[i01][i02][i03].first] + 1);
155 table.push_back(std::make_tuple(indx[rout[i01][i02][i03].second] + 1, 1, a));
159 for (unsigned int i02 = 0; i02 < table.size(); i02++) {
160 std::fprintf(file01, "residue %s connections %d | ", (resNames[posSrch(indx, std::get<0>(table[i02]))]).c_str(), std::get<1>(table[i02]));
161 for (unsigned int i03 = 0; i03 < std::get<2>(table[i03]).size(); i03++) {
162 std::fprintf(file01, "%s ", (resNames[posSrch(indx, std::get<2>(table[i02])[i03])]).c_str());
164 std::fprintf(file01, "\n");
168 std::vector< std::vector< std::pair< unsigned int, unsigned int > > > temp01, temp02;
169 std::vector< std::pair< unsigned int, unsigned int > > temp03, temp04, temp05;
174 for (unsigned int i02 = 0; i02 < temp01.size(); i02++) {
175 for (unsigned int i03 = 0; i03 < temp01[i02].size(); i03++) {
176 temp03.push_back(temp01[i02][i03]);
179 for (unsigned int i02 = 0; i02 < temp02.size(); i02++) {
180 for (unsigned int i03 = 0; i03 < temp02[i02].size(); i03++) {
181 temp04.push_back(temp02[i02][i03]);
184 std::sort(temp03.begin(), temp03.end());
185 std::sort(temp04.begin(), temp04.end());
188 std::set_difference(temp03.begin(), temp03.end(), temp04.begin(), temp04.end(), std::inserter(temp05, temp05.begin()));
189 std::fprintf(file01, "minus:\n");
190 for (unsigned int i02 = 0; i02 < temp05.size(); i02++) {
191 std::fprintf(file01, "cgo_arrow (id %3d), (id %3d), radius=0.075\n", indx[temp05[i02].first] + 1, indx[temp05[i02].second] + 1);
195 std::set_difference(temp04.begin(), temp04.end(), temp03.begin(), temp03.end(), std::inserter(temp05, temp05.begin()));
196 std::fprintf(file01, "plus:\n");
197 for (unsigned int i02 = 0; i02 < temp05.size(); i02++) {
198 std::fprintf(file01, "cgo_arrow (id %3d), (id %3d), radius=0.075\n", indx[temp05[i02].first] + 1, indx[temp05[i02].second] + 1);
207 bool mysortfunc (std::vector< int > a, std::vector< int > b) {
208 return (a.size() > b.size());
211 bool isitsubset (std::vector< int > a, std::vector< int > b) {
215 std::sort(a.begin(), a.end());
216 std::sort(b.begin(), b.end());
218 for (unsigned int i = 0; i < a.size(); i++) {
230 void correlation_evaluation(const std::vector< RVec > ref, const std::vector< std::vector< RVec > > trajectory, const unsigned int tauE, const unsigned int window_size, const char* file_name) {
231 std::vector< std::vector< std::vector< double > > > crl;
232 std::vector< std::vector< RVec > > trj;
234 for (unsigned int istart = 0; istart < trajectory.size() - window_size - tauE; istart++) {
236 trj.resize(window_size + tauE);
237 for (unsigned int i = 0; i < window_size + tauE; i++) {
238 for (unsigned int j = 0; j < trajectory[i].size(); j++) {
239 trj[i].push_back(trajectory[i + istart][j]);
242 crl.resize(tauE + 1);
243 for (unsigned int i = 0; i < crl.size(); i++) {
244 crl[i].resize(trajectory.front().size());
245 for (unsigned int j = 0; j < trajectory.front().size(); j++) {
246 crl[i][j].resize(trajectory.front().size());
247 for (unsigned int k = 0; k < trajectory.front().size(); k++) {
252 #pragma omp parallel for ordered schedule(dynamic) shared(crl) firstprivate(trj, ref)
253 for (unsigned int i = 0; i <= tauE; i++) {
254 std::vector< std::vector< double > > a, b, c;
255 std::vector< double > d;
257 for (unsigned int j = 0; j < trajectory.front().size(); j++) {
261 for (unsigned int k = 0; k < trajectory.front().size(); k++) {
267 for (unsigned int j = 0; j < trj.size() - tauE; j++) {
268 for (unsigned int f1 = 0; f1 < trj.front().size(); f1++) {
269 for (unsigned int f2 = 0; f2 < trj.front().size(); f2++) {
271 temp1 = trj[j][f1] - ref[f1];
272 temp2 = trj[j + i][f2] - ref[f2];
273 a[f1][f2] += (static_cast<double>(temp1[0]) * static_cast<double>(temp2[0]) +
274 static_cast<double>(temp1[1]) * static_cast<double>(temp2[1]) +
275 static_cast<double>(temp1[2]) * static_cast<double>(temp2[2]));
276 b[f1][f2] += (static_cast<double>(temp1[0]) * static_cast<double>(temp1[0]) +
277 static_cast<double>(temp1[1]) * static_cast<double>(temp1[1]) +
278 static_cast<double>(temp1[2]) * static_cast<double>(temp1[2]));
279 c[f1][f2] += (static_cast<double>(temp2[0]) * static_cast<double>(temp2[0]) +
280 static_cast<double>(temp2[1]) * static_cast<double>(temp2[1]) +
281 static_cast<double>(temp2[2]) * static_cast<double>(temp2[2]));
285 for (unsigned int j = 0; j < trj.front().size(); j++) {
286 for (unsigned int f = 0; f < trj.front().size(); f++) {
287 crl[i][j][f] = a[j][f] / (std::sqrt(b[j][f] * c[j][f]));
290 /*std::cout << i << " | ";
298 // запись блока в память
299 // заход на новый круг
302 std::cout << "crl calc " << istart << "\n";
304 for (unsigned int i1 = 0; i1 < crl.size(); i1++) {
305 for (unsigned int i2 = 0; i2 < crl[i1].size(); i2++) {
306 for (unsigned int i3 = 0; i3 < crl[i1][i2].size(); i3++) {
307 crl[i1][i2][i3] = std::round(crl[i1][i2][i3] * 10000) / 10000;
314 file = std::fopen(file_name, "a");
315 for (unsigned int i = 0; i < crl.size(); i++) {
316 std::fprintf(file, "%d %d\n", istart, i);
317 for (unsigned int j = 0; j < crl[i].size(); j++) {
318 for (unsigned int f = 0; f < crl[i][j].size(); f++) {
319 std::fprintf(file, "%.6f ", crl[i][j][f]); //~16
321 std::fprintf(file, "\n");
327 std::cout << "file input " << istart << "\n";
330 // запись блока в память
331 // заход на новый круг
338 void graph_calculation( std::vector< std::vector< std::pair< double, long int > > > &graph, std::vector< std::vector< unsigned int > > &s_graph,
339 std::vector< std::vector< std::pair< unsigned int, unsigned int > > > &s_graph_rbr,
340 const std::vector< RVec > ref,
341 const std::vector< std::vector< std::vector<double > > > crl,
342 const double crl_b, const double e_rad, const unsigned int tauB, const unsigned int tauE) {
343 graph.resize(ref.size());
344 for (unsigned int i = 0; i < ref.size(); i++) {
345 graph[i].resize(ref.size(), std::make_pair(0, -1));
348 for (unsigned int i = tauB; i <= tauE; i++) {
349 for (unsigned int j = 0; j < ref.size(); j++) {
350 for (unsigned int f = j; f < ref.size(); f++) {
351 temp = ref[i] - ref[f];
352 if (std::max(std::abs(crl[i][j][f]), std::abs(crl[i][f][j])) >= crl_b &&
353 static_cast<double>(norm(temp)) <= e_rad && std::abs(graph[j][f].first) < std::max(std::abs(crl[i][j][f]), std::abs(crl[i][f][j]))) {
354 if (std::abs(crl[i][j][f]) > std::abs(crl[i][f][j])) {
355 graph[j][f].first = crl[i][j][f];
357 graph[j][f].first = crl[i][f][j];
359 graph[j][f].second = i;
364 std::cout << "crl analysed\n";
365 std::vector< bool > graph_flags;
366 graph_flags.resize(ref.size(), true);
367 std::vector< unsigned int > a;
369 std::vector< std::pair< unsigned int, unsigned int > > b;
371 std::vector< unsigned int > que1, que2, que3;
372 for (unsigned int i = 0; i < ref.size(); i++) {
373 if (graph_flags[i]) {
374 s_graph.push_back(a);
375 s_graph_rbr.push_back(b);
381 graph_flags[i] = false;
382 while(que1.size() > 0) {
384 for (unsigned int k = 0; k < que1.size(); k++) {
385 for (unsigned int j = 0; j < ref.size(); j++) {
386 if (graph[que1[k]][j].second > -1 && graph_flags[j]) {
388 graph_flags[j] = false;
393 for (unsigned int j = 0; j < que2.size(); j++) {
394 que3.push_back(que2[j]);
397 s_graph.back() = que3;
398 for (unsigned int j = 0; j < que3.size(); j++) {
399 for (unsigned int k = 0; k < ref.size(); k++) {
400 if (graph[que3[j]][k].second > -1) {
401 s_graph_rbr.back().push_back(std::make_pair(que3[j], k));
405 //std::cout << s_graph.back().size() << " ";
410 bool myfunction (const std::pair< int, double > i, const std::pair< int, double > j) {
411 return i.second < j.second;
414 bool myfuncRVecEq (const RVec a, const RVec b) {
415 return (a[0] != b[0]) || (a[1] != b[1]) || (a[2] != b[2]);
418 void graph_back_bone_evaluation(std::vector< std::vector < std::pair< unsigned int, unsigned int > > > &rout_n, const unsigned long indxSize,
419 const std::vector< std::vector< std::pair< double, long > > > graph, const std::vector< std::vector< unsigned int > > s_graph,
420 const std::vector< std::vector< std::pair< unsigned int, unsigned int > > > s_graph_rbr) {
421 std::vector< double > key;
422 std::vector< long > path;
423 std::vector< std::pair< unsigned int, double > > que;
424 std::vector< std::pair< unsigned int, unsigned int > > a;
426 for (unsigned int i = 0; i < s_graph.size(); i++) {
431 if (s_graph[i].size() > 2) {
432 key.resize(indxSize, 2);
433 path.resize(indxSize, -1);
434 key[s_graph[i][0]] = 0;
435 for (unsigned int j = 0; j < s_graph[i].size(); j++) {
436 que.push_back(std::make_pair(s_graph[i][j], key[s_graph[i][j]]));
438 std::sort(que.begin(), que.end(), myfunction);
439 while (!que.empty()) {
441 que.erase(que.begin());
442 for (unsigned int j = 0; j < s_graph_rbr[i].size(); j++) {
444 if (s_graph_rbr[i][j].first == v) {
445 u = s_graph_rbr[i][j].second;
446 } else if (s_graph_rbr[i][j].second == v) {
447 u = s_graph_rbr[i][j].first;
450 unsigned long pos = 0;
451 for (unsigned long k = 0; k < que.size(); k++) {
452 if (que[k].first == u) {
458 if (flag && key[static_cast< unsigned long >(u)] > 1 - std::abs(graph[v][static_cast< unsigned long >(u)].first)) {
459 path[static_cast< unsigned long >(u)] = v;
460 key[static_cast< unsigned long >(u)] = 1 - std::abs(graph[v][static_cast< unsigned long >(u)].first);
461 que[pos].second = key[static_cast< unsigned long >(u)];
462 sort(que.begin(), que.end(), myfunction);
468 for (unsigned int j = 0; j < indxSize; j++) {
470 rout_n.back().push_back(std::make_pair(j, path[j]));
477 gmx::RVec evaluate_com(std::vector< RVec > frame) {
482 for (unsigned int i = 0; i < frame.size(); i++) {
485 temp[0] /= frame.size();
486 temp[1] /= frame.size();
487 temp[2] /= frame.size();
492 * \ingroup module_trajectoryanalysis
495 class SpaceTimeCorr : public TrajectoryAnalysisModule
500 virtual ~SpaceTimeCorr();
502 //! Set the options and setting
503 virtual void initOptions(IOptionsContainer *options,
504 TrajectoryAnalysisSettings *settings);
506 //! First routine called by the analysis framework
507 // virtual void initAnalysis(const t_trxframe &fr, t_pbc *pbc);
508 virtual void initAnalysis(const TrajectoryAnalysisSettings &settings,
509 const TopologyInformation &top);
511 virtual void initAfterFirstFrame(const TrajectoryAnalysisSettings &settings,
512 const t_trxframe &fr);
514 //! Call for each frame of the trajectory
515 // virtual void analyzeFrame(const t_trxframe &fr, t_pbc *pbc);
516 virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
517 TrajectoryAnalysisModuleData *pdata);
519 //! Last routine called by the analysis framework
520 // virtual void finishAnalysis(t_pbc *pbc);
521 virtual void finishAnalysis(int nframes);
523 //! Routine to write output, that is additional over the built-in
524 virtual void writeOutput();
530 std::vector< std::vector< RVec > > trajectory;
531 std::vector< RVec > reference;
533 std::vector< int > index;
534 std::vector< std::string > resNms;
537 int tau = 0; // selectable
539 float crl_border = 0; // selectable
540 float eff_rad = 1.5; // selectable
541 std::string OutPutName; // selectable
542 int mode = 0; // selectable
543 std::string MtrxNm; // selectable
544 // Copy and assign disallowed by base.
547 SpaceTimeCorr::SpaceTimeCorr(): TrajectoryAnalysisModule()
551 SpaceTimeCorr::~SpaceTimeCorr()
556 SpaceTimeCorr::initOptions(IOptionsContainer *options,
557 TrajectoryAnalysisSettings *settings)
559 static const char *const desc[] = {
560 "[THISMODULE] to be done"
562 // Add the descriptive text (program help text) to the options
563 settings->setHelpText(desc);
564 // Add option for output file name
565 //options->addOption(FileNameOption("on").filetype(eftIndex).outputFile()
566 // .store(&fnNdx_).defaultBasename("domains")
567 // .description("Index file from the domains"));
568 // Add option for working mode
569 options->addOption(gmx::IntegerOption("mode")
571 .description("default 0 | rdy correlation matrixes 1, need extra params"));
572 // Add option for Matrix Input file names
573 options->addOption(StringOption("Mtrx_in_put")
575 .description("mandatory if work mode == 1"));
576 // Add option for tau constant
577 options->addOption(gmx::IntegerOption("tau")
579 .description("number of frames for time travel"));
580 // Add option for window constant
581 options->addOption(gmx::IntegerOption("window")
583 .description("size of window in frames for correlation evaluation"));
584 // Add option for crl_border constant
585 options->addOption(FloatOption("crl")
587 .description("make graph based on corrs > constant"));
588 // Add option for eff_rad constant
589 options->addOption(FloatOption("ef_rad")
591 .description("effective radius for atoms to evaluate corrs"));
592 // Add option for selection list
593 options->addOption(SelectionOption("select_domains_and_residue").storeVector(&sel_)
594 .required().dynamicMask().multiValue()
595 .description("Domains to form rigid skeleton"));
596 // Add option for output file names
597 options->addOption(StringOption("out_put")
599 .description("<your name here> + <local file tag>.txt"));
600 // Control input settings
601 settings->setFlags(TrajectoryAnalysisSettings::efNoUserPBC);
602 settings->setFlag(TrajectoryAnalysisSettings::efUseTopX);
603 settings->setPBC(true);
607 SpaceTimeCorr::initAnalysis(const TrajectoryAnalysisSettings &settings, const TopologyInformation &top)
609 ArrayRef< const int > atomind = sel_[0].atomIndices();
611 for (ArrayRef< const int >::iterator ai = atomind.begin(); (ai < atomind.end()); ai++) {
612 index.push_back(*ai);
613 resNms.push_back(*(top.atoms()->resinfo[top.atoms()->atom[*ai].resind].name) + std::to_string((top.atoms()->atom[*ai].resind + 1)));
615 trajectory.resize(0);
618 if (top.hasFullTopology()) {
619 for (unsigned int i = 0; i < index.size(); i++) {
620 reference.push_back(top.x().at(index[i]));
626 SpaceTimeCorr::initAfterFirstFrame(const TrajectoryAnalysisSettings &settings, const t_trxframe &fr)
630 // -s '*.pdb' -f '*.pdb' -n '*.ndx' -sf 'name' -tau 1000 -crl 0.20 -ef_rad 9000 -out_put OLA
631 // -s '*.tpr' -f '*.xtc' -n '*.ndx' -sf 'name' -tau 1000 -crl 0.30 -ef_rad 20 -out_put 'test_run'
634 SpaceTimeCorr::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata)
636 trajectory.resize(trajectory.size() + 1);
637 trajectory.back().resize(index.size());
638 for (unsigned int i = 0; i < index.size(); i++) {
639 trajectory.back()[i] = fr.x[index[i]];
645 SpaceTimeCorr::finishAnalysis(int nframes)
647 std::vector< std::vector< std::vector< std::pair< unsigned int, unsigned int > > > > rout_new;
648 unsigned int k = 1000, m = 0;
650 k = static_cast< unsigned int>(tau);
657 std::cout << "\nCorrelation's evaluation - start\n";
659 correlation_evaluation(reference, trajectory, k, 1000, (OutPutName + "-DumpData.txt").c_str());
661 std::cout << "Correlation's evaluation - end\n";
662 } else if (mode == 1) {
663 rout_new.resize(trajectory.size() - static_cast< unsigned long>(window) - k);
665 file = std::fopen((OutPutName + "-DumpData.txt").c_str(), "r+");
666 #pragma omp parallel for ordered schedule(dynamic) shared(rout_new) firstprivate(reference, crl_border, eff_rad, m, k)
667 for(unsigned long i = 0; i < trajectory.size() - static_cast< unsigned int>(window) - k; i++) {
668 std::vector< std::vector< std::vector< double > > > crltns;
669 std::vector< std::vector< std::pair< double, long int > > > graph;
670 std::vector< std::vector< unsigned int > > sub_graph;
671 std::vector< std::vector< std::pair< unsigned int, unsigned int > > > sub_graph_rbr;
675 crltns.resize(k + 1);
676 for (unsigned int i1 = 0; i1 < crltns.size(); i1++) {
677 crltns[i1].resize(trajectory.front().size());
678 for (unsigned int i2 = 0; i2 < trajectory.front().size(); i2++) {
679 crltns[i1][i2].resize(trajectory.front().size());
680 for (unsigned int i3 = 0; i3 < trajectory.front().size(); i3++) {
681 crltns[i1][i2][i3] = 0.;
685 for (unsigned int i1 = 0; i1 < k + 1; i1++) {
686 int t0, t1, t2 = std::fscanf(file, "%d %d\n", &t0, &t1);
687 for (unsigned int i2 = 0; i2 < trajectory.front().size(); i2++) {
688 for (unsigned int i3 = 0; i3 < trajectory.front().size(); i3++) {
689 t2 = std::fscanf(file, "%lf ", &crltns[i1][i2][i3]);
693 std::cout << "red mtrxs " << i << "\n";
696 graph_calculation(graph, sub_graph, sub_graph_rbr, reference, crltns, static_cast< double >(crl_border), static_cast< double >(eff_rad), m, k);
697 graph_back_bone_evaluation(rout_new[i], reference.size()/*index.size()*/, graph, sub_graph, sub_graph_rbr);
703 make_rout_file(static_cast< double >(crl_border), index, resNms, rout_new, (OutPutName + "-routs.txt").c_str());
705 std::cout << "Finish Analysis - end\n\n";
709 SpaceTimeCorr::writeOutput()
715 * The main function for the analysis template.
718 main(int argc, char *argv[])
720 return gmx::TrajectoryAnalysisCommandLineRunner::runAsMain<SpaceTimeCorr>(argc, argv);