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
43 #include <gromacs/trajectoryanalysis.h>
44 #include <gromacs/trajectoryanalysis/topologyinformation.h>
45 #include <gromacs/selection/nbsearch.h>
46 #include <gromacs/pbcutil/pbc.h>
57 // структура углов для одной краски
58 struct colorLocalAngles {
59 gmx::RVec a1{0., 0., 0.}, a2{0., 0., 0.};
60 gmx::RVec b1{0., 0., 0.}, b2{0., 0., 0.};
61 gmx::RVec n1{0., 0., 0.}, n2{0., 0., 0.};
62 double a12 {0}, b12 {0}, n12 {0};
63 std::vector< double > betaAngles;
66 struct colorAnglesPairs
68 std::vector< std::pair<size_t, size_t> > a1, a2;
69 std::vector< std::pair<size_t, size_t> > b1, b2;
72 struct massChargePair {
76 // функция парсинга одной строки
77 void parseBetaListDATLine(const std::string ¤tLine,
78 std::vector< std::vector< unsigned int > > &localInputBL) {
79 size_t equalCount {0};
80 std::vector< unsigned int > a;
82 for (size_t i {0}; i < currentLine.size(); ++i) {
83 if (currentLine[i] == '=') { // подсчитываем число "пустых" символов
87 for (size_t j {i + 1}; j < currentLine.size(); ++j) {
88 if (currentLine[j] == 'B' || currentLine[j] == 'E') {
95 localInputBL.push_back(a);
96 for (size_t j {i}; j <= temp; ++j) {
97 localInputBL.back().push_back(j - equalCount);
105 // функция нахождения бета-листов в структуре по файлу ДССП
106 void betaListDigestion(const std::string &inputFile,
107 std::vector< std::vector< std::vector< unsigned int > > > &inputBL) {
109 std::ifstream file(inputFile);
111 getline(file, line); // считываем число в первой строке - кол-во осмысленных элементов в строках - нам не нужно
113 if (line.size() > 3) {
115 inputBL.resize(inputBL.size() + 1);
116 parseBetaListDATLine(line, inputBL.back());
119 } while (line.size() > 3);
121 throw "DSSP DAT FILE IS EMPTY";
126 // функция выделения индексов для бэталистов
127 inline void aminoacidsIndexation(const std::vector< size_t > &inputIndex,
128 const gmx::TopologyInformation &top,
129 std::vector< std::vector< size_t > > &aminoacidsIndex) {
130 aminoacidsIndex.resize(0);
131 for (size_t i {0}; i < inputIndex.size(); ++i) {
132 aminoacidsIndex.resize(std::max(aminoacidsIndex.size(), static_cast< size_t >(top.atoms()->atom[inputIndex[i]].resind + 1)));
133 aminoacidsIndex[top.atoms()->atom[inputIndex[i]].resind].push_back(inputIndex[i]);
137 // функция векторного произведения двух RVec'ов
138 inline void RVecVecMultiply(gmx::RVec &n, const gmx::RVec &a, const gmx::RVec &b) {
139 n[0] = a[1] * b[2] - a[2] * b[1];
140 n[1] = a[2] * b[0] - a[0] * b[2];
141 n[2] = a[0] * b[1] - a[2] * b[0];
144 // поиск угла между двумя RVec'ами
145 inline double RVecAngle(const gmx::RVec &a, const gmx::RVec &b) {
146 return std::acos((a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (a.norm() * b.norm())) * 180.0 / 3.14159265;
149 // вычисление внутренних углов в краске
150 void colorsAnglesEvaluation(const std::vector< gmx::RVec > &frame,
151 const std::vector< colorAnglesPairs > &inputPairs,
152 std::vector< colorLocalAngles > &colorStruct) {
153 colorStruct.resize(0);
154 colorStruct.resize(inputPairs.size());
155 #pragma omp parallel for ordered schedule(dynamic)
156 for (size_t i = 0; i < inputPairs.size(); ++i) {
157 colorStruct[i].betaAngles.resize(0);
159 for (size_t j {0}; j < inputPairs[i].a1.size(); ++j) {
160 colorStruct[i].a1 += frame[inputPairs[i].a1[j].first] - frame[inputPairs[i].a1[j].second];
162 for (size_t j {0}; j < inputPairs[i].b1.size(); ++j) {
163 colorStruct[i].b1 += frame[inputPairs[i].b1[j].first] - frame[inputPairs[i].b1[j].second];
165 RVecVecMultiply(colorStruct[i].n1, colorStruct[i].a1, colorStruct[i].b1);
167 for (size_t j {0}; j < inputPairs[i].a2.size(); ++j) {
168 colorStruct[i].a2 += frame[inputPairs[i].a2[j].first] - frame[inputPairs[i].a2[j].second];
170 for (size_t j {0}; j < inputPairs[i].b2.size(); ++j) {
171 colorStruct[i].b2 += frame[inputPairs[i].b2[j].first] - frame[inputPairs[i].b2[j].second];
173 RVecVecMultiply(colorStruct[i].n2, colorStruct[i].a2, colorStruct[i].b2);
174 colorStruct[i].n2 *= -1; // для "сонаправленности" векторов нормали
175 colorStruct[i].a12 = RVecAngle(colorStruct[i].a1, colorStruct[i].a2);
176 colorStruct[i].b12 = RVecAngle(colorStruct[i].b1, colorStruct[i].b2);
177 colorStruct[i].n12 = RVecAngle(colorStruct[i].n1, colorStruct[i].n2);
182 // функция поиска индекса в краске по имени->индексу
183 size_t returnRVecIndex(const std::vector< std::pair< std::string, size_t > > &colorsIndex, const std::string &toFind) {
184 for (auto &i : colorsIndex) {
185 if (i.first == toFind) {
189 throw "WRONG COLOR ATOM NAME TO EVALUATE VECTORS";
192 // заполнение пресетов для поиска средних векторов в краске
193 void colorAnglesPairsEvaluation(const std::vector< std::vector< std::pair< std::string, size_t > > > &colorsIndex,
194 std::vector< colorAnglesPairs > &output) {
195 for (size_t i {0}; i < output.size(); ++i) {
196 output[i].a1.resize(0);
197 output[i].a1.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAF"), returnRVecIndex(colorsIndex[i], "CAJ")));
198 output[i].a1.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAK"), returnRVecIndex(colorsIndex[i], "CAO")));
199 output[i].b1.resize(0);
200 output[i].b1.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAO"), returnRVecIndex(colorsIndex[i], "CAJ")));
201 output[i].b1.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAM"), returnRVecIndex(colorsIndex[i], "CAH")));
202 output[i].b1.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAK"), returnRVecIndex(colorsIndex[i], "CAF")));
203 output[i].a2.resize(0);
204 output[i].a2.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CAB"), returnRVecIndex(colorsIndex[i], "CBQ")));
205 output[i].a2.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CBP"), returnRVecIndex(colorsIndex[i], "CBL")));
206 output[i].b2.resize(0);
207 output[i].b2.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CBL"), returnRVecIndex(colorsIndex[i], "CBQ")));
208 output[i].b2.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CBN"), returnRVecIndex(colorsIndex[i], "CBS")));
209 output[i].b2.push_back(std::make_pair(returnRVecIndex(colorsIndex[i], "CBP"), returnRVecIndex(colorsIndex[i], "CAB")));
213 // вычисление направляющего вектора в бэта-листе
214 inline void betaListsRVecsEvaluation(const std::vector< gmx::RVec > &frame,
215 const std::vector< std::vector< unsigned int > > &inputBetaLists,
216 std::vector< gmx::RVec > &temp,
217 const std::vector< size_t > &inputCA) {
220 for (const auto &i : inputBetaLists) {
221 tempA = frame[inputCA[i[i.size() - 1]]] + frame[inputCA[i[i.size() - 2]]] - frame[inputCA[i[1]]] - frame[inputCA[i[0]]];
222 tempA /= tempA.norm();
223 temp.push_back(tempA);
227 // определение близко ли к белку находится краска
228 bool isNearPeptide( const t_pbc *inputPBC,
229 const std::vector< gmx::RVec > &inputFrame,
230 const std::vector< size_t > &inputIndex,
231 const std::vector< std::pair< std::string, size_t > > &inputColor, const double cutOff) {
233 for (size_t i {0}; i < inputColor.size(); ++i) {
234 for (size_t j {0}; j < inputIndex.size(); ++j) {
235 pbc_dx(inputPBC, inputFrame[inputIndex[j]], inputFrame[inputColor[i].second], tempRVec);
236 if (tempRVec.norm() <= cutOff) {
244 // поиск ближайших к краске бэта-листов
245 inline void searchNearBetaLists(const t_pbc *inputPBC,
246 const std::vector< gmx::RVec > &inputFrame, const std::vector< std::vector< unsigned int > > &inputBLists,
247 const std::vector< std::pair< std::string, size_t > > &inputColor, std::vector< bool > &outputList,
248 const std::vector< std::vector< size_t > > &inputAminoacids, const double cutOff) {
249 outputList.resize(0);
250 outputList.resize(inputBLists.size(), false);
252 for (size_t i {0}; i < inputColor.size(); ++i) {
253 for (size_t j {0}; j < inputBLists.size(); ++j) {
254 for (size_t k {0}; k < inputBLists[j].size(); ++k) {
255 for (size_t m {0}; m < inputAminoacids[inputBLists[j][k]].size(); ++m) {
256 pbc_dx(inputPBC, inputFrame[inputAminoacids[inputBLists[j][k]][m]], inputFrame[inputColor[i].second], tempRVec);
257 if (tempRVec.norm() <= cutOff) {
258 outputList[j] = true;
267 // определение углов между краской и направляющим вектором бэта-листа
268 inline void computeAnglesColorsVsBeta(const gmx::RVec &inputBetaRVec, colorLocalAngles &colorFormation) {
269 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a1));
270 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b1));
271 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n1));
272 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a2));
273 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b2));
274 colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n2));
277 // поиск стаков красок
278 void colorsStackingSearch(const t_pbc *inputPBC, const std::vector< gmx::RVec > &inputFrame,
279 const std::vector< std::vector< std::pair< std::string, size_t > > > &colorsIndex,
280 const float radius, const float epsi,
281 std::vector< std::vector< int > > &output) {
282 std::vector< std::vector< int > > outputTemp;
283 outputTemp.resize(0);
284 outputTemp.resize(colorsIndex.size());
285 for (size_t i {0}; i < colorsIndex.size(); ++i) {
286 outputTemp[i].resize(0);
287 outputTemp[i].resize(colorsIndex.size(), 0);
290 #pragma omp parallel for ordered schedule(dynamic)
291 for (size_t i = 0; i < colorsIndex.size(); ++i) {
292 for (size_t j {i + 1}; j < colorsIndex.size(); ++j) {
293 for (size_t k1 {0}; k1 < colorsIndex[i].size(); ++k1) {
294 for (size_t k2 {0}; k2 < colorsIndex[j].size(); ++k2) {
295 pbc_dx(inputPBC, inputFrame[colorsIndex[i][k1].second], inputFrame[colorsIndex[j][k2].second], temp);
296 if (temp.norm() <= radius) {
306 output.resize(colorsIndex.size());
307 for (size_t i {0}; i < colorsIndex.size(); ++i) {
310 for (size_t i {0}; i < outputTemp.size(); ++i) {
311 for (size_t j {i + 1}; j < outputTemp[i].size(); ++j) {
312 if (static_cast< float >(outputTemp[i][j]) >= static_cast< float >(colorsIndex.size()) * epsi) {
313 output[i].push_back(j);
314 output[j].push_back(i);
320 // запоминаем массу/заряды атомов красок
321 void colorMassChargesEval( const std::vector< std::pair< std::string, size_t > > &color,
322 const gmx::TopologyInformation &top,
323 std::vector< std::pair< size_t, massChargePair > > &outputIndexMassChargePair) {
324 outputIndexMassChargePair.resize(0);
326 for (size_t i {0}; i < color.size(); ++i) {
327 temp.m = top.atoms()->atom[color[i].second].m;
328 temp.ch = top.atoms()->atom[color[i].second].q;
329 outputIndexMassChargePair.push_back(std::make_pair(color[i].second, temp));
333 // вычисляем дипольный вектор краски
334 gmx::RVec colorDipoleEval(const std::vector< std::pair< size_t, massChargePair > > &inputIndexMassChargePair,
335 const std::vector< gmx::RVec > &inputFrame) {
336 gmx::RVec temp {0., 0., 0.};
338 for (auto &i : inputIndexMassChargePair) {
339 temp += inputFrame[i.first] * static_cast< float >(i.second.m);
342 temp /= static_cast< float >(temp2);
346 // функция записи в файл значений углов для кадра
347 void anglesFileDump(const int frameNum, const std::string &output,
348 const std::vector< bool > &toPeptide,
349 const std::vector< colorLocalAngles > &colorFormation,
350 const std::vector< std::vector< int > > &inputStack,
351 const std::vector< std::vector< double > > &dipoleBetaAngles) {
352 std::ofstream file(output, std::ofstream::app);
353 file << "frame =" << std::setw(8) << frameNum << std::endl;
354 for (size_t i {0}; i < colorFormation.size(); ++i) {
355 file << "color #" << std::setw(3) << i;
357 file << std::setw(4) << "yes";
359 file << std::setw(4) << "no";
362 file << std::setw(8) << std::setprecision(2) << colorFormation[i].a12;
363 file << std::setw(8) << std::setprecision(2) << colorFormation[i].b12;
364 file << std::setw(8) << std::setprecision(2) << colorFormation[i].n12;
365 if (colorFormation[i].betaAngles.size() == 0) {
366 file << std::setw(4) << 0 << " [] ";
368 int temp = colorFormation[i].betaAngles.size() / 6;
369 std::vector< double > betaTemp;
371 betaTemp.resize(6, 0.); // magic number, meh
372 for (size_t j {0}; j < colorFormation[i].betaAngles.size(); ++j) {
373 betaTemp[j % 6] += colorFormation[i].betaAngles[j];
375 for (size_t j {0}; j < betaTemp.size(); ++j) {
376 betaTemp[j] /= static_cast< double >(temp);
378 file << std::setw(4) << temp << " [ ";
379 for (size_t j {0}; j < betaTemp.size(); ++j) {
380 file << std::setw(8) << std::setprecision(2) << betaTemp[j];
382 for (size_t j {0}; j < colorFormation[i].betaAngles.size(); ++j) {
383 file << std::setw(8) << std::setprecision(2) << colorFormation[i].betaAngles[j];
387 if (inputStack[i].size() == 0) {
388 file << std::setw(4) << "no []";
390 file << std::setw(4) << "yes [ ";
391 file << std::setw(4) << inputStack[i].size();
392 for (size_t j {0}; j < inputStack[i].size(); ++j) {
393 file << std::setw(4) << inputStack[i][j];
397 if (dipoleBetaAngles[i].size() == 0) {
400 double tempDBangle {0.};
401 for (size_t j {0}; j < dipoleBetaAngles[i].size(); ++j) {
402 tempDBangle += dipoleBetaAngles[i][j];
404 file << std::setw(8) << std::setprecision(2) << tempDBangle / dipoleBetaAngles[i].size();
405 for (size_t j {0}; j < dipoleBetaAngles[i].size(); ++j) {
406 file << std::setw(8) << std::setprecision(2) << dipoleBetaAngles[i][j];
415 * \ingroup module_trajectoryanalysis
417 class colorVec : public gmx::TrajectoryAnalysisModule
424 //! Set the options and setting
425 virtual void initOptions(gmx::IOptionsContainer *options,
426 gmx::TrajectoryAnalysisSettings *settings);
428 //! First routine called by the analysis framework
429 // virtual void initAnalysis(const t_trxframe &fr, t_pbc *pbc);
430 virtual void initAnalysis(const gmx::TrajectoryAnalysisSettings &settings,
431 const gmx::TopologyInformation &top);
433 //! Call for each frame of the trajectory
434 // virtual void analyzeFrame(const t_trxframe &fr, t_pbc *pbc);
435 virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
436 gmx::TrajectoryAnalysisModuleData *pdata);
438 //! Last routine called by the analysis framework
439 // virtual void finishAnalysis(t_pbc *pbc);
440 virtual void finishAnalysis(int nframes);
442 //! Routine to write output, that is additional over the built-in
443 virtual void writeOutput();
447 gmx::SelectionList sel_;
448 std::string fnOut {"name"}; // selectable
449 std::string fnBetaListsDat; // selectable
450 float effRad {0.4}; // selectable
451 float stackRad {0.5}; // selectable
452 float stackCoef {0.66}; // selectable
453 std::vector< size_t > index;
454 std::vector< size_t > indexCA;
455 std::vector< std::vector< size_t > > aminoacidsIndex;
456 std::vector< std::vector< std::pair< std::string, size_t > > > colorsNames;
457 std::vector< colorAnglesPairs > colorsVectorsIndex;
458 std::vector< colorLocalAngles > colorsAngles;
459 std::vector< std::vector< std::pair< size_t, massChargePair > > > colorsMassCharges;
460 std::vector< std::vector< std::vector< unsigned int > > > betaLists;
462 std::vector< gmx::RVec > trajectoryFrame;
464 // Copy and assign disallowed by base.
467 colorVec::colorVec(): TrajectoryAnalysisModule()
471 colorVec::~colorVec()
484 colorVec::initOptions( gmx::IOptionsContainer *options,
485 gmx::TrajectoryAnalysisSettings *settings)
487 static const char *const desc[] = {
488 "[THISMODULE] to be done"
490 // Add the descriptive text (program help text) to the options
491 settings->setHelpText(desc);
492 // Add option for selection list
493 options->addOption(gmx::SelectionOption("sel")
495 .required().dynamicMask().multiValue()
496 .description("select pepride and colors / -sf"));
497 // Add option for input file names
498 options->addOption(gmx::StringOption("dat")
499 .store(&fnBetaListsDat)
500 .description("a file to make dynamic beta lists"));
501 // Add option for output file name
502 options->addOption(gmx::StringOption("out")
504 .description("Index file for the algorithm output."));
505 // Add option for effRad constant
506 options->addOption(gmx::FloatOption("efRad")
508 .description("max distance from colors to peptide in nm to consider to be \"near\" - default == 0.4"));
509 // Add option for effRad constant
510 options->addOption(gmx::FloatOption("stackRad")
512 .description("max distance from color to color in nm to consider to be \"stacked\" - default == 0.5"));
513 // Add option for effRad constant
514 options->addOption(gmx::FloatOption("stackCoef")
516 .description("min % (1 == 100%) stacked mass of a colorto be considered \"stacked\" - default == 0.66"));
517 // Control input settings
518 settings->setFlags(gmx::TrajectoryAnalysisSettings::efNoUserPBC);
519 settings->setFlag(gmx::TrajectoryAnalysisSettings::efUseTopX);
520 //settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
521 settings->setPBC(true);
525 colorVec::initAnalysis( const gmx::TrajectoryAnalysisSettings &settings,
526 const gmx::TopologyInformation &top)
528 // считывание индекса
530 for (gmx::ArrayRef< const int >::iterator ai {sel_.front().atomIndices().begin()}; (ai < sel_.front().atomIndices().end()); ++ai) {
531 index.push_back(static_cast< size_t >(*ai));
533 // считывание индекса
535 for (gmx::ArrayRef< const int >::iterator ai {sel_[1].atomIndices().begin()}; (ai < sel_[1].atomIndices().end()); ++ai) {
536 indexCA.push_back(static_cast< size_t >(*ai));
539 colorsNames.resize(0);
540 colorsNames.resize(sel_.size() - 2);
541 for (size_t i {2}; i < sel_.size(); ++i) {
542 for (gmx::ArrayRef< const int >::iterator ai {sel_[i].atomIndices().begin()}; (ai < sel_[i].atomIndices().end()); ++ai) {
543 colorsNames[i - 2].push_back(std::make_pair(*(top.atoms()->atomname[*ai]), static_cast< size_t >(*ai)));
546 colorsVectorsIndex.resize(0);
547 colorsVectorsIndex.resize(colorsNames.size());
548 colorAnglesPairsEvaluation(colorsNames, colorsVectorsIndex);
549 // разбор dat файла для создания бэта листов
550 betaListDigestion(fnBetaListsDat, betaLists);
551 // разбор топологии для индексации бета листов
552 aminoacidsIndexation(index, top, aminoacidsIndex);
554 // запоминание распределения зарядов в красках
555 colorsMassCharges.resize(0);
556 colorsMassCharges.resize(colorsNames.size());
557 for (size_t i {0}; i < colorsNames.size(); ++i) {
558 colorMassChargesEval(colorsNames[i], top, colorsMassCharges[i]);
561 // вывод базовых значений
562 std::cout << std::endl;
563 std::cout << "effective radius = " << std::setw(30) << effRad << std::endl;
564 std::cout << "DAT file = " << std::setw(30) << fnBetaListsDat << std::endl;
565 std::cout << "output file = " << std::setw(30) << fnOut << std::endl;
566 std::cout << "peptide atoms # = " << std::setw(30) << index.size() << std::endl;
567 std::cout << "CA-atmos # = " << std::setw(30) << indexCA.size() << std::endl;
568 std::cout << "Beta frames = " << std::setw(30) << betaLists.size() << std::endl;
569 std::cout << "residue # = " << std::setw(30) << aminoacidsIndex.size() << std::endl;
570 std::cout << "colors # = " << std::setw(30) << colorsNames.size() << std::endl;
574 colorVec::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, gmx::TrajectoryAnalysisModuleData *pdata)
576 trajectoryFrame.resize(0);
577 // считывания текущего фрейма траектории
578 for (size_t i {0}; i < fr.natoms; ++i) {
579 trajectoryFrame.push_back(fr.x[i]);
581 // подсчёт углов в красках
582 colorsAngles.resize(0);
583 colorsAnglesEvaluation(trajectoryFrame, colorsVectorsIndex, colorsAngles);
584 // рассчёт положения относительно белка
585 std::vector< bool > colorsToPeptide;
586 colorsToPeptide.resize(0);
587 colorsToPeptide.resize(colorsNames.size(), false);
588 for (size_t i {0}; i < colorsNames.size(); ++i) {
589 colorsToPeptide[i] = isNearPeptide(pbc, trajectoryFrame, index, colorsNames[i], effRad);
591 // расчёт угла и среднего угла с ближайшими бета листами
592 std::vector< std::vector< bool > > colorsToBeta;
593 colorsToBeta.resize(0);
594 colorsToBeta.resize(colorsNames.size());
595 std::vector< std::vector< double > > colorsToBetaAngles;
596 colorsToBetaAngles.resize(0);
597 std::vector< gmx::RVec > betaListsRVecs;
598 // подсчёт направляющей beta листа
599 betaListsRVecsEvaluation(trajectoryFrame, betaLists[frnr], betaListsRVecs, indexCA);
600 // поиск ближайших beta листов
601 for (size_t i {0}; i < colorsToPeptide.size(); ++i) {
602 if (colorsToPeptide[i]) {
603 searchNearBetaLists(pbc, trajectoryFrame, betaLists[frnr], colorsNames[i], colorsToBeta[i], aminoacidsIndex, effRad);
606 // подсчёт углов между векторами краски и beta листами
607 for (size_t i {0}; i < colorsToBeta.size(); ++i) {
608 for (size_t j {0}; j < colorsToBeta[i].size(); ++j) {
609 if (colorsToBeta[i][j]) {
610 computeAnglesColorsVsBeta(betaListsRVecs[j], colorsAngles[i]);
614 // поиск стакированных красок
615 std::vector< std::vector< int > > colorStack;
616 colorsStackingSearch(pbc, trajectoryFrame, colorsNames, stackRad, stackCoef, colorStack);
617 // рассчёт дипольных моментов для красок
618 std::vector< gmx::RVec > colorsDipole;
619 std::vector< std::vector< double > > dipoleBetaAngles;
620 colorsDipole.resize(0);
621 dipoleBetaAngles.resize(0);
622 dipoleBetaAngles.resize(colorsNames.size());
623 for (auto &i : colorsMassCharges) {
624 colorsDipole.push_back(colorDipoleEval(i, trajectoryFrame));
626 for (size_t i {0}; i < colorsToBeta.size(); ++i) {
627 dipoleBetaAngles[i].resize(0);
628 for (size_t j {0}; j < colorsToBeta[i].size(); ++j) {
629 if (colorsToBeta[i][j]) {
630 dipoleBetaAngles[i].push_back(RVecAngle(colorsDipole[i], betaListsRVecs[j]));
634 // вывод в файл(ы) информацию для фрейма
635 anglesFileDump(frnr, fnOut, colorsToPeptide, colorsAngles, colorStack, dipoleBetaAngles);
636 std::cout << "frame number = " << std::setw(8) << frnr << " trajectory time = " << std::setw(8) << fr.time << std::endl;
640 colorVec::finishAnalysis(int nframes)
646 colorVec::writeOutput()
650 * frame #<current frame number>
651 * 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>]
657 * The main function for the analysis template.
660 main(int argc, char *argv[])
662 return gmx::TrajectoryAnalysisCommandLineRunner::runAsMain<colorVec>(argc, argv);