- fixed a bug with sel_[1 and 2]
[alexxy/gromacs-colorvec.git] / src / colorvec.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements gmx::analysismodules::Freevolume.
38  *
39  * \author Titov Anatoly <Wapuk-cobaka@yandex.ru>
40  * \ingroup module_trajectoryanalysis
41  */
42
43 #include <gromacs/trajectoryanalysis.h>
44 #include <gromacs/trajectoryanalysis/topologyinformation.h>
45 #include <gromacs/selection/nbsearch.h>
46
47 #include <iostream>
48 #include <fstream>
49 //#include <chrono>
50 #include <cfloat>
51 #include <omp.h>
52 #include <vector>
53 #include <cstdio>
54 #include <iomanip>
55
56 // структура углов для одной краски
57 struct colorLocalAngles {
58     gmx::RVec   a1{0., 0., 0.}, a2{0., 0., 0.};
59     gmx::RVec   b1{0., 0., 0.}, b2{0., 0., 0.};
60     gmx::RVec   n1{0., 0., 0.}, n2{0., 0., 0.};
61     double      a12 {0}, b12 {0}, n12 {0};
62     std::vector< double > betaAngles;
63 };
64
65 // функция парсинга одной строки
66 void parseBetaListDATLine(const std::string &currentLine, std::vector< std::vector< unsigned int > > &localInputBL) {
67     size_t                      equalCount = 0;
68     std::vector< unsigned int > a;
69     a.resize(0);
70     for (size_t i = 0; i < currentLine.size(); ++i) {
71         if (currentLine[i] == '=') { // подсчитываем число "пустых" символов
72             ++equalCount;
73         } else {
74             size_t temp {i};
75             for (size_t j = temp + 1; j < currentLine.size(); ++j) {
76                 if (currentLine[j] == 'B' || currentLine[j] == 'E') {
77                     ++temp;
78                 }
79             }
80             if (temp - i > 3) {
81                 localInputBL.push_back(a);
82                 for (size_t j = i; j <= temp; ++j) {
83                     localInputBL.back().push_back(j - equalCount);
84                 }
85                 i = temp;
86             }
87         }
88     }
89 }
90
91 // функция нахождения бета-листов в структуре по файлу ДССП
92 void betaListDigestion(const std::string &inputFile, std::vector< std::vector< std::vector< unsigned int > > > &inputBL) {
93     inputBL.resize(0);
94     std::ifstream   file(inputFile);
95     std::string     line;
96     getline(file, line); // считываем число в первой строке - кол-во осмысленных элементов в строках - нам не нужно
97     getline(file, line);
98     if (line.size() > 3) {
99         do {
100             inputBL.resize(inputBL.size() + 1);
101             parseBetaListDATLine(line, inputBL.back());
102             line = "";
103             getline(file, line);
104         } while (line.size() > 3);
105     } else {
106         throw "DSSP DAT FILE IS EMPTY";
107     }
108     file.close();
109 }
110
111 // функция выделения индексов для бэталистов
112 inline void aminoacidsIndexation(const std::vector< size_t > &inputIndex, const gmx::TopologyInformation &top, std::vector< std::vector< size_t > > &aminoacidsIndex) {
113     aminoacidsIndex.resize(0);
114     for (size_t i = 0; i < inputIndex.size(); ++i) {
115         aminoacidsIndex.resize(std::max(aminoacidsIndex.size(), static_cast< size_t >(top.atoms()->atom[inputIndex[i]].resind + 1)));
116         aminoacidsIndex[top.atoms()->atom[inputIndex[i]].resind].push_back(inputIndex[i]);
117     }
118 }
119
120 // функция поиска RVec в кадре по имени->индексу
121 gmx::RVec returnRVec(const std::vector< gmx::RVec > &frame, const std::vector< std::pair< std::string, size_t > > &colorsIndex, const std::string &toFind) {
122     for (auto &i : colorsIndex) {
123         if (i.first == toFind) {
124             return frame[i.second];
125         }
126     }
127     throw "WRONG COLOR ATOM NAME TO EVALUATE VECTORS";
128 }
129
130 // функция векторного произведения двух RVec'ов
131 inline void RVecVecMultiply(gmx::RVec &n, const gmx::RVec &a, const gmx::RVec &b) {
132     n[0] = a[1] * b[2] - a[2] * b[1];
133     n[1] = a[2] * b[0] - a[0] * b[2];
134     n[2] = a[0] * b[1] - a[2] * b[0];
135 }
136
137 // поиск угла между двумя RVec'ами
138 inline double RVecAngle(const gmx::RVec &a, const gmx::RVec &b) {
139     return std::acos((a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (a.norm() * b.norm())) * 180.0 / 3.14159265;
140 }
141
142 // вычисление внутренних углов в краске
143 void colorsAnglesEvaluation(const std::vector< gmx::RVec > &frame, const std::vector< std::vector< std::pair< std::string, size_t > > > &colorsIndex,
144                             std::vector< colorLocalAngles > &colorStruct) {
145     colorStruct.resize(colorsIndex.size());
146     #pragma omp parallel for ordered schedule(dynamic)
147     for (size_t i = 0; i < colorsIndex.size(); ++i) {
148         colorStruct[i].betaAngles.resize(0);
149         // "левый" блок
150         colorStruct[i].a1 = returnRVec(frame, colorsIndex[i], "CAF") - returnRVec(frame, colorsIndex[i], "CAJ") + returnRVec(frame, colorsIndex[i], "CAK") - returnRVec(frame, colorsIndex[i], "CAO");
151         colorStruct[i].a1 /= colorStruct[i].a1.norm();
152         colorStruct[i].b1 = returnRVec(frame, colorsIndex[i], "CAO") - returnRVec(frame, colorsIndex[i], "CAJ") + returnRVec(frame, colorsIndex[i], "CAM") - returnRVec(frame, colorsIndex[i], "CAH") + returnRVec(frame, colorsIndex[i], "CAK") - returnRVec(frame, colorsIndex[i], "CAF");
153         colorStruct[i].b1 /= colorStruct[i].b1.norm();
154         RVecVecMultiply(colorStruct[i].n1, colorStruct[i].a1, colorStruct[i].b1);
155         colorStruct[i].n1 /= colorStruct[i].n1.norm();
156         // "правый" блок
157         colorStruct[i].a2 = returnRVec(frame, colorsIndex[i], "CAB") - returnRVec(frame, colorsIndex[i], "CBQ") + returnRVec(frame, colorsIndex[i], "CBP") - returnRVec(frame, colorsIndex[i], "CBL");
158         colorStruct[i].a2 /= colorStruct[i].a2.norm();
159         colorStruct[i].b2 = returnRVec(frame, colorsIndex[i], "CBL") - returnRVec(frame, colorsIndex[i], "CBQ") + returnRVec(frame, colorsIndex[i], "CBN") - returnRVec(frame, colorsIndex[i], "CBS") + returnRVec(frame, colorsIndex[i], "CBP") - returnRVec(frame, colorsIndex[i], "CAB");
160         colorStruct[i].b2 /= colorStruct[i].b2.norm();
161         RVecVecMultiply(colorStruct[i].n2, colorStruct[i].a2, colorStruct[i].b2);
162         colorStruct[i].n2 *= -1; // для "сонаправленности" векторов нормали
163         colorStruct[i].n2 /= colorStruct[i].n2.norm();
164         colorStruct[i].a12 = RVecAngle(colorStruct[i].a1, colorStruct[i].a2);
165         colorStruct[i].b12 = RVecAngle(colorStruct[i].b1, colorStruct[i].b2);
166         colorStruct[i].n12 = RVecAngle(colorStruct[i].n1, colorStruct[i].n2);
167     }
168     #pragma omp barrier
169 }
170
171 // вычисление направляющего вектора в бэта-листе
172 inline void betaListsRVecsEvaluation(const std::vector< gmx::RVec > &frame, const std::vector< std::vector< unsigned int > > &inputBetaLists,
173                                      std::vector< gmx::RVec > &temp, const std::vector< size_t > &inputCA) {
174     temp.resize(0);
175     gmx::RVec tempA;
176     for (const auto &i : inputBetaLists) {
177         tempA = frame[inputCA[i[i.size() - 1]]] + frame[inputCA[i[i.size() - 2]]] - frame[inputCA[i[1]]] - frame[inputCA[i[0]]];
178         tempA /= tempA.norm();
179         temp.push_back(tempA);
180     }
181 }
182
183 //// определение близко ли к белку находится краска
184 //bool isNearPeptide(const t_trxframe &fr, const t_pbc *pbc, const std::vector< gmx::RVec > &inputFrame,
185 //                          /*gmx::AnalysisNeighborhood &nbhood, */const std::vector< size_t > &inputIndex,
186 //                          const std::vector< std::pair< std::string, size_t > > &inputColor) {
187 //    /*gmx::AnalysisNeighborhoodSearch     nbsearch = nbhood.initSearch(pbc, gmx::AnalysisNeighborhoodPositions(fr.x, fr.natoms));
188 //    gmx::AnalysisNeighborhoodPair       pair;*/
189
190 //    for (size_t i = 0; i < inputColor.size(); ++i) {
191 //        std::cout << inputColor[i].first << " " << i << " / "  << inputColor.size() << std::endl;
192 //        gmx::AnalysisNeighborhood           nbhood;
193 //        nbhood.setCutoff(0.8);
194 //        gmx::AnalysisNeighborhoodSearch     nbsearch = nbhood.initSearch(pbc, gmx::AnalysisNeighborhoodPositions(fr.x, fr.natoms));
195 //        gmx::AnalysisNeighborhoodPair       pair;
196 //        gmx::AnalysisNeighborhoodPairSearch pairSearch = nbsearch.startPairSearch(inputFrame[inputColor[i].second].as_vec());
197 //        int count1 {0};
198 //        while (pairSearch.findNextPair(&pair)) {
199 //            std::cout << ++count1 << " ";
200 //            for (size_t j = 0; j < inputIndex.size(); ++j) {
201 //                if (pair.refIndex() == inputIndex[j]) {
202 //                    return true;
203 //                }
204 //            }
205 //        }
206 //        std::cout << inputColor[i].first << " atom done" << std::endl;
207 //    }
208 //    return false;
209 //}
210
211 // определение близко ли к белку находится краска
212 bool isNearPeptide( const std::vector< gmx::RVec > &inputFrame, const std::vector< size_t > &inputIndex,
213                     const std::vector< std::pair< std::string, size_t > > &inputColor, const double cutOff) {
214     for (size_t i {0}; i < inputColor.size(); ++i) {
215         for (size_t j {0}; j < inputIndex.size(); ++j) {
216             if ((inputFrame[inputIndex[j]] - inputFrame[inputColor[i].second]).norm() <= cutOff) {
217                 return true;
218             }
219         }
220     }
221     return false;
222 }
223
224 // поиск ближайших к краске бэта-листов
225 //inline void searchNearBetaLists(const t_trxframe &fr, const t_pbc *pbc, const std::vector< gmx::RVec > &inputFrame,
226 //                                gmx::AnalysisNeighborhood &nbhood,
227 //                                const std::vector< std::vector< unsigned int > > &inputBLists,
228 //                                const std::vector< std::pair< std::string, size_t > > &inputColor,
229 //                                std::vector< bool > &outputList, const std::vector< std::vector< size_t > > &inputAminoacids) {
230 //    outputList.resize(0);
231 //    outputList.resize(inputBLists.size(), false);
232 //    gmx::AnalysisNeighborhoodSearch      nbsearch = nbhood.initSearch(pbc, gmx::AnalysisNeighborhoodPositions(fr.x, fr.natoms));
233 //    gmx::AnalysisNeighborhoodPair        pair;
234 //    for (const auto &i : inputColor) {
235 //        while (nbsearch.startPairSearch(inputFrame[i.second].as_vec()).findNextPair(&pair)) {
236 //            for (size_t j = 0; j < inputBLists.size(); ++j) {
237 //                for (size_t k = 0; k < inputBLists[j].size(); ++k) {
238 //                    for (size_t m = 0; m < inputAminoacids[inputBLists[j][k]].size(); ++m) {
239 //                        if (pair.testIndex() == inputAminoacids[inputBLists[j][k]][m]) {
240 //                            outputList[j] = true;
241 //                        }
242 //                    }
243 //                }
244 //            }
245 //        }
246 //    }
247 //}
248
249 inline void searchNearBetaLists(const std::vector< gmx::RVec > &inputFrame, const std::vector< std::vector< unsigned int > > &inputBLists,
250                                 const std::vector< std::pair< std::string, size_t > > &inputColor, std::vector< bool > &outputList,
251                                 const std::vector< std::vector< size_t > > &inputAminoacids, const double cutOff) {
252     outputList.resize(0);
253     outputList.resize(inputBLists.size(), false);
254     //std::cout << inputColor.size() << " " << inputBLists.size() << " " << inputAminoacids.size() << "\n";
255     for (size_t i {0}; i < inputColor.size(); ++i) {
256         for (size_t j = 0; j < inputBLists.size(); ++j) {
257             for (size_t k = 0; k < inputBLists[j].size(); ++k) {
258                 for (size_t m = 0; m < inputAminoacids[inputBLists[j][k]].size(); ++m) {
259                     std::cout << inputFrame[inputAminoacids[inputBLists[j][k]][m]][0] << " " << inputFrame[inputAminoacids[inputBLists[j][k]][m]][1] << " " <<
260                               inputFrame[inputAminoacids[inputBLists[j][k]][m]][2] << "\n";
261                     if ((inputFrame[inputAminoacids[inputBLists[j][k]][m]] - inputFrame[inputColor[i].second]).norm() <= cutOff) {
262                         outputList[j] = true;
263                         std::cout << "yes";
264                         m = inputAminoacids[inputBLists[j][k]].size() + 1;
265                         k = inputBLists[j].size() + 1;
266                     }
267                 }
268             }
269         }
270     }
271 }
272
273 // определение углов между краской и направляющим вектором бэта-листа
274 inline void computeAnglesColorsVsBeta(const gmx::RVec &inputBetaRVec, colorLocalAngles &colorFormation) {
275     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a1));
276     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b1));
277     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n1));
278     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a2));
279     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b2));
280     colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n2));
281 }
282
283 // функция записи в файл значений углов для кадра
284 void anglesFileDump(const int frameNum, const std::string &output, const std::vector< bool > &toPeptide, const std::vector< colorLocalAngles > &colorFormation) {
285     std::ofstream   file(output, std::ofstream::app);
286     int temp = 0;
287     std::vector< double > betaTemp;
288     betaTemp.resize(0);
289     file << "frame =" << std::setw(8) << frameNum << std::endl;
290     for (size_t i = 0; i < colorFormation.size(); ++i) {
291         file << "color #" << std::setw(3) << i;
292         if (toPeptide[i]) {
293             file << std::setw(4) << "yes";
294         } else {
295             file << std::setw(4) << "no";
296         }
297         file << std::setw(7) << std::setprecision(2) << colorFormation[i].a12 << std::setw(7) << colorFormation[i].b12 << std::setw(7) << colorFormation[i].n12;
298         temp = colorFormation[i].betaAngles.size() / 6;
299         if (temp == 0) {
300             file << std::setw(4) << 0;
301         } else {
302             betaTemp.resize(6, 0.); // magic number, meh
303             for (size_t j = 0; j < colorFormation[i].betaAngles.size(); ++j) {
304                 betaTemp[j % 6] += colorFormation[i].betaAngles[j];
305             }
306             for (size_t j = 0; j < betaTemp.size(); ++j) {
307                 betaTemp[j] /= temp;
308             }
309             file << std::setw(4) << temp;
310             for (size_t j = 0; j < betaTemp.size(); ++j) {
311                 file << std::setw(7) << std::setprecision(2) << betaTemp[j];
312             }
313             for (size_t j = 0; j < colorFormation[i].betaAngles.size(); ++j) {
314                 file << std::setw(7) << std::setprecision(2) << colorFormation[i].betaAngles[j];
315             }
316         }
317         file << std::endl;
318     }
319     file.close();
320 }
321
322 /*! \brief
323  * \ingroup module_trajectoryanalysis
324  */
325 class colorVec : public gmx::TrajectoryAnalysisModule
326 {
327     public:
328
329         colorVec();
330         virtual ~colorVec();
331
332         //! Set the options and setting
333         virtual void initOptions(gmx::IOptionsContainer          *options,
334                                  gmx::TrajectoryAnalysisSettings *settings);
335
336         //! First routine called by the analysis framework
337         // virtual void initAnalysis(const t_trxframe &fr, t_pbc *pbc);
338         virtual void initAnalysis(const gmx::TrajectoryAnalysisSettings &settings,
339                                   const gmx::TopologyInformation        &top);
340
341         //! Call for each frame of the trajectory
342         // virtual void analyzeFrame(const t_trxframe &fr, t_pbc *pbc);
343         virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
344                                   gmx::TrajectoryAnalysisModuleData *pdata);
345
346         //! Last routine called by the analysis framework
347         // virtual void finishAnalysis(t_pbc *pbc);
348         virtual void finishAnalysis(int nframes);
349
350         //! Routine to write output, that is additional over the built-in
351         virtual void writeOutput();
352
353     private:
354
355         gmx::SelectionList                                              sel_;
356         std::string                                                     fnOut           {"name"};   // selectable
357         std::string                                                     fnBetaListsDat;             // selectable
358         float                                                           effRad          {0.8};      // selectable
359         std::vector< size_t >                                           index;
360         std::vector< size_t >                                           indexCA;
361         std::vector< std::vector< size_t > >                            aminoacidsIndex;
362         std::vector< std::vector< std::pair< std::string, size_t > > >  colorsNames;
363         std::vector< std::vector< std::vector< unsigned int > > >       betaLists;
364         gmx::AnalysisNeighborhood                                       nb_;
365
366         // Copy and assign disallowed by base.
367 };
368
369 colorVec::colorVec(): TrajectoryAnalysisModule()
370 {
371 }
372
373 colorVec::~colorVec()
374 {
375 }
376
377 /*
378  * ndx:
379  * [peptide]
380  * [CA]
381  * [color_{i}]
382  *
383  */
384
385 void
386 colorVec::initOptions(  gmx::IOptionsContainer          *options,
387                         gmx::TrajectoryAnalysisSettings *settings)
388 {
389     static const char *const desc[] = {
390         "[THISMODULE] to be done"
391     };
392     // Add the descriptive text (program help text) to the options
393     settings->setHelpText(desc);
394     // Add option for selection list
395     options->addOption(gmx::SelectionOption("sel")
396                             .storeVector(&sel_)
397                             .required().dynamicMask().multiValue()
398                             .description("select pepride and colors / -sf"));
399     // Add option for input file names
400     options->addOption(gmx::StringOption("dat")
401                             .store(&fnBetaListsDat)
402                             .description("a file to make dynamic beta lists"));
403     // Add option for output file name
404     options->addOption(gmx::StringOption("out")
405                             .store(&fnOut)
406                             .description("Index file for the algorithm output."));
407     // Add option for effRad constant
408     options->addOption(gmx::FloatOption("efRad")
409                             .store(&effRad)
410                             .description("max distance from colors to peptide in nm to consider to be \"near\""));
411     // Control input settings
412     settings->setFlags(gmx::TrajectoryAnalysisSettings::efNoUserPBC);
413     settings->setFlag(gmx::TrajectoryAnalysisSettings::efUseTopX);
414     //settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
415     settings->setPBC(true);
416 }
417
418 void
419 colorVec::initAnalysis( const gmx::TrajectoryAnalysisSettings   &settings,
420                         const gmx::TopologyInformation          &top)
421 {
422     // считывание индекса
423     index.resize(0);
424     for (gmx::ArrayRef< const int >::iterator ai {sel_.front().atomIndices().begin()}; (ai < sel_.front().atomIndices().end()); ai++) {
425         index.push_back(static_cast< size_t >(*ai));
426     }
427     // считывание индекса
428     indexCA.resize(0);
429     for (gmx::ArrayRef< const int >::iterator ai {sel_[1].atomIndices().begin()}; (ai < sel_[1].atomIndices().end()); ai++) {
430         index.push_back(static_cast< size_t >(*ai));
431     }
432     // считывание красок
433     colorsNames.resize(sel_.size() - 2);
434     for (size_t i = 2; i < sel_.size(); ++i) {
435         for (gmx::ArrayRef< const int >::iterator ai {sel_[i].atomIndices().begin()}; (ai < sel_[i].atomIndices().end()); ai++) {
436             colorsNames[i - 2].push_back(std::make_pair(*(top.atoms()->atomname[*ai]), static_cast< size_t >(*ai)));
437         }
438     }
439     // разбор dat файла для создания бэта листов
440     betaListDigestion(fnBetaListsDat, betaLists);
441     // разбор топологии для индексации бета листов
442     aminoacidsIndexation(index, top, aminoacidsIndex);
443     // задание радиуса рассматриваемых соседей
444     nb_.setCutoff(effRad);
445     /*
446      * формально можно сделать:
447      * найти соотношение между именами для углов и индексными номерами
448      * заполнить std::vector< std::vector< size_t > > nameToIndex;
449      * и в последствии считать:
450      * a1 = frame[nameToIndex[0][1] + ... - ... - ...
451      * b1 a2 b2 по аналогии только для [@<-[1, 2, 3]]
452      *
453      */
454 }
455
456 void
457 colorVec::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, gmx::TrajectoryAnalysisModuleData *pdata)
458 {
459     std::vector< gmx::RVec > trajectoryFrame;
460     trajectoryFrame.resize(0);
461     // считывания текущего фрейма траектории
462     for (size_t i {0}; i < fr.natoms; ++i) {
463         trajectoryFrame.push_back(fr.x[i]);
464     }
465     // подсчёт углов в красках
466     std::vector< colorLocalAngles > colorFormation;
467     colorsAnglesEvaluation(trajectoryFrame, colorsNames, colorFormation);
468     // рассчёт положения относительно белка
469     /*
470      * формально можно совместить определение близости с белком и определение ближайших бэта-листов
471      * для этого думаю нужно как-то соотнести или сделать соотношение между индексом и бэта-листами (т.е. хранить что бы за О(1) делать)
472      *
473      */
474
475     std::vector< bool >     colorsToPeptide;
476     colorsToPeptide.resize(0);
477     colorsToPeptide.resize(colorsNames.size(), false);
478     for (size_t i = 0; i < colorsNames.size(); ++i) {
479         colorsToPeptide[i] = isNearPeptide(trajectoryFrame, index, colorsNames[i], effRad * 9000);
480     }
481     // расчёт угла и среднего угла с ближайшими бета листами
482     std::vector< std::vector< bool > > colorsToBeta;
483     colorsToBeta.resize(0);
484     colorsToBeta.resize(colorsNames.size());
485     std::vector< std::vector< double > > colorsToBetaAngles;
486     colorsToBetaAngles.resize(0);
487     std::vector< gmx::RVec > betaListsRVecs;
488     std::cout << "\n\nttest\n";
489     betaListsRVecsEvaluation(trajectoryFrame, betaLists[frnr], betaListsRVecs, indexCA);
490     for (size_t i = 0; i < colorsToPeptide.size(); ++i) {
491         if (colorsToPeptide[i]) {
492             searchNearBetaLists(trajectoryFrame, betaLists[frnr], colorsNames[i], colorsToBeta[i], aminoacidsIndex, effRad * 9000);
493         }
494     }
495     for (size_t i = 0; i < colorsToBeta.size(); ++i) {
496         for (size_t j = 0; j < colorsToBeta[i].size(); ++j) {
497             if (colorsToBeta[i][j]) {
498                 computeAnglesColorsVsBeta(betaListsRVecs[j], colorFormation[i]);
499             }
500         }
501     }
502     // вывод в файл(ы) информацию для фрейма
503     anglesFileDump(frnr, fnOut, colorsToPeptide, colorFormation);
504 }
505
506 void
507 colorVec::finishAnalysis(int nframes)
508 {
509
510 }
511
512 void
513 colorVec::writeOutput()
514 {
515     /*
516      *
517      * frame #<current frame number>
518      * color #<color number> <yes/no for "close" to peptide> a12 b12 n12 <number of beta lists> <6 avg beta angles> [<6 angles for each beta list>]
519      *
520      */
521 }
522
523 /*! \brief
524  * The main function for the analysis template.
525  */
526 int
527 main(int argc, char *argv[])
528 {
529     return gmx::TrajectoryAnalysisCommandLineRunner::runAsMain<colorVec>(argc, argv);
530 }