- first implementation of angle search utility
authorAnatoly <Titov_AI@pnpi.nrcki.ru>
Tue, 20 Oct 2020 13:09:18 +0000 (16:09 +0300)
committerAnatoly <Titov_AI@pnpi.nrcki.ru>
Tue, 20 Oct 2020 13:09:18 +0000 (16:09 +0300)
CMakeLists.txt
src/CMakeLists.txt
src/colorvec.cpp [new file with mode: 0644]
src/domains.cpp [deleted file]

index 41f14534537486de59b0cb52a9a7ddd58cf9271f..b1dd68dd28c98dd155b5a58608eb8c4109b4967d 100644 (file)
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.9.6)
 
-project(gromacs-domains CXX)
+project(gromacs-colorvec CXX)
 
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
index c262023df3169816d93310f56f9d46aba7c1f007..1686a4bf8d88bd23c8b482197228009dc5d4cccd 100644 (file)
@@ -28,13 +28,13 @@ endfunction()
 
 set(GROMACS_CXX_FLAGS "${GROMACS_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
 
-add_executable(domains domains.cpp domaintype.cpp newfit.cpp)
+add_executable(colorvec colorvec.cpp domaintype.cpp newfit.cpp)
 include_directories(
         ${GROMACS_INCLUDE_DIRS}
         ${CMAKE_SOURCE_DIR}/include)
-set_target_properties(domains PROPERTIES
+set_target_properties(colorvec PROPERTIES
        COMPILE_FLAGS "${GROMACS_CXX_FLAGS}")
-target_link_libraries(domains ${GROMACS_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
+target_link_libraries(colorvec ${GROMACS_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
 
 
 cxx_library(gtest "${cxx_strict}" gtest/src/gtest-all.cc)
diff --git a/src/colorvec.cpp b/src/colorvec.cpp
new file mode 100644 (file)
index 0000000..31fc750
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements gmx::analysismodules::Freevolume.
+ *
+ * \author Titov Anatoly <Wapuk-cobaka@yandex.ru>
+ * \ingroup module_trajectoryanalysis
+ */
+
+#include "domaintype.h"
+#include "newfit.h"
+
+#include <gromacs/trajectoryanalysis.h>
+#include <gromacs/trajectoryanalysis/topologyinformation.h>
+#include <gromacs/selection/nbsearch.h>
+
+#include <iostream>
+#include <fstream>
+//#include <chrono>
+#include <cfloat>
+#include <omp.h>
+#include <vector>
+#include <cstdio>
+
+// структура углов для одной краски
+struct colorLocalAngles {
+    gmx::RVec   a1, a2;
+    gmx::RVec   b1, b2;
+    gmx::RVec   n1, n2;
+    double      a12, b12, n12;
+    std::vector< double > betaAngles;
+};
+
+// хрен пойми почему, но захотелось рекурсивно сделать | можно сделать и через вайл
+long long returnBetaEnd(const std::string &currentLine, long long pos) {
+    switch (currentLine[pos]) {
+        case 'B' :
+            returnBetaEnd(currentLine, pos + 1);
+            break;
+        case 'E' :
+            returnBetaEnd(currentLine, pos + 1);
+            break;
+        default :
+            return (pos - 1);
+            break;
+    }
+    return (pos - 1); // формально логически лишняя строчка, но Qt ругается
+}
+
+// функция парсинга одной строки
+void parseBetaListDATLine(const std::string &currentLine, std::vector< std::vector< unsigned int > > &localInputBL) {
+    size_t                      equalCount = 0;
+    std::vector< unsigned int > a;
+    a.resize(0);
+    for (size_t i = 0; i < currentLine.size(); ++i) {
+        if (currentLine[i] == '=') { // подсчитываем число "пустых" символов
+            ++equalCount;
+        } else {
+            long long temp = returnBetaEnd(currentLine, i);
+            if (temp - i > 3) {
+                localInputBL.push_back(a);
+                for (size_t j = i; j <= temp; ++j) {
+                    localInputBL.back().push_back(j - equalCount);
+                }
+                i = temp;
+            }
+        }
+    }
+}
+
+// функция нахождения бета-листов в структуре по файлу ДССП
+void betaListDigestion(const std::string &inputFile, std::vector< std::vector< std::vector< unsigned int > > > &inputBL) {
+    inputBL.resize(0);
+    std::ifstream   file(inputFile);
+    std::string     line;
+    getline(file, line); // считываем число в первой строке - кол-во осмысленных элементов в строках - нам не нужно
+    getline(file, line);
+    if (line.size() > 0) {
+        do {
+            inputBL.resize(inputBL.size() + 1);
+            parseBetaListDATLine(line, inputBL.back());
+            getline(file, line);
+        } while (line.size() > 0);
+    } else {
+        throw "DSSP DAT FILE IS EMPTY";
+    }
+    file.close();
+}
+
+// функция поиска RVec в кадре по имени->индексу
+gmx::RVec returnRVec(const std::vector< RVec > &frame, const std::vector< std::pair< std::string, size_t > > &colorsIndex, std::string toFind) {
+    for (auto &i : colorsIndex) {
+        if (i.first == toFind) {
+            return frame[i.second];
+        }
+    }
+    throw "WRONG COLOR ATOM NAME TO EVALUATE VECTORS";
+}
+
+// функция векторного произведения двух RVec'ов
+inline void RVecVecMultiply(gmx::RVec &n, const gmx::RVec &a, const gmx::RVec &b) {
+    n[0] = a[1] * b[2] - a[2] * b[1];
+    n[1] = a[2] * b[0] - a[0] * b[2];
+    n[2] = a[0] * b[1] - a[2] * b[0];
+}
+
+// поиск угла между двумя RVec'ами
+inline double RVecAngle(const gmx::RVec &a, const gmx::RVec &b) {
+    return std::acos((a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / (a.norm() * b.norm()));
+}
+
+// вычисление внутренних углов в краске
+void colorsAnglesEvaluation(const std::vector< RVec > &frame, const std::vector< std::vector< std::pair< std::string, size_t > > > &colorsIndex, std::vector< colorLocalAngles > &colorStruct) {
+    colorStruct.resize(colorsIndex.size());
+    #pragma omp parallel for ordered schedule(dynamic)
+    for (size_t i = 0; i < colorsIndex.size(); ++i) {
+        colorStruct[i].betaAngles.resize(0);
+        // "левый" блок
+        colorStruct[i].a1 = returnRVec(frame, colorsIndex[i], "CAF") - returnRVec(frame, colorsIndex[i], "CAJ") + returnRVec(frame, colorsIndex[i], "CAK") - returnRVec(frame, colorsIndex[i], "CAO");
+        colorStruct[i].a1 /= colorStruct[i].a1.norm();
+        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");
+        colorStruct[i].b1 /= colorStruct[i].b1.norm();
+        RVecVecMultiply(colorStruct[i].n1, colorStruct[i].a1, colorStruct[i].b1);
+        colorStruct[i].n1 /= colorStruct[i].n1.norm();
+        // "правый" блок
+        colorStruct[i].a2 = returnRVec(frame, colorsIndex[i], "CAB") - returnRVec(frame, colorsIndex[i], "CBQ") + returnRVec(frame, colorsIndex[i], "CBP") - returnRVec(frame, colorsIndex[i], "CBL");
+        colorStruct[i].a2 /= colorStruct[i].a2.norm();
+        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");
+        colorStruct[i].b2 /= colorStruct[i].b2.norm();
+        RVecVecMultiply(colorStruct[i].n2, colorStruct[i].a2, colorStruct[i].b2);
+        colorStruct[i].n2 *= -1; // для "сонаправленности" векторов нормали
+        colorStruct[i].n2 /= colorStruct[i].n2.norm();
+        colorStruct[i].a12 = RVecAngle(colorStruct[i].a1, colorStruct[i].a2);
+        colorStruct[i].b12 = RVecAngle(colorStruct[i].b1, colorStruct[i].b2);
+        colorStruct[i].n12 = RVecAngle(colorStruct[i].n1, colorStruct[i].n2);
+    }
+    #pragma omp barrier
+}
+
+// вычисление направляющего вектора в бэта-листе
+inline void betaListsRVecsEvaluation(const std::vector< RVec > &frame, const std::vector< std::vector< unsigned int > > &inputBetaLists, std::vector< gmx::RVec > &temp) {
+    temp.resize(0);
+    gmx::RVec tempA;
+    for (const auto &i : inputBetaLists) {
+        tempA = frame[i[i.size() - 1]] + frame[i[i.size() - 2]] - frame[i[1]] - frame[i[0]];
+        tempA /= tempA.norm();
+        temp.push_back(tempA);
+    }
+}
+
+// определение близко ли к белку находится краска
+bool isNearPeptide(const t_trxframe &fr, const t_pbc *pbc, const std::vector< RVec > inputFrame,
+                          gmx::AnalysisNeighborhood &nbhood, const std::vector< size_t > &inputIndex,
+                          const std::vector< std::pair< std::string, size_t > > &inputColor) {
+    gmx::AnalysisNeighborhoodSearch      nbsearch = nbhood.initSearch(pbc, gmx::AnalysisNeighborhoodPositions(fr.x, fr.natoms));
+    gmx::AnalysisNeighborhoodPair        pair;
+    for (const auto &i : inputColor) {
+        while (nbsearch.startPairSearch(inputFrame[i.second].as_vec()).findNextPair(&pair)) {
+            for (const auto &j : inputIndex) {
+                if (pair.testIndex() == j) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+// поиск ближайших к краске бэта-листов
+inline void searchNearBetaLists(const t_trxframe &fr, const t_pbc *pbc, const std::vector< RVec > inputFrame,
+                                gmx::AnalysisNeighborhood &nbhood,
+                                const std::vector< std::vector< unsigned int > > inputBLists,
+                                const std::vector< std::pair< std::string, size_t > > &inputColor,
+                                std::vector< bool > &outputList) {
+    outputList.resize(0);
+    outputList.resize(inputBLists.size(), false);
+    gmx::AnalysisNeighborhoodSearch      nbsearch = nbhood.initSearch(pbc, gmx::AnalysisNeighborhoodPositions(fr.x, fr.natoms));
+    gmx::AnalysisNeighborhoodPair        pair;
+    for (const auto &i : inputColor) {
+        while (nbsearch.startPairSearch(inputFrame[i.second].as_vec()).findNextPair(&pair)) {
+            for (size_t j = 0; j < inputBLists.size(); ++j) {
+                for (size_t k = 0; k < inputBLists[j].size(); ++k) {
+                    if (pair.testIndex() == inputBLists[j][k]) {
+                        outputList[j] = true;
+                    }
+                }
+            }
+        }
+    }
+
+}
+
+// определение углов между краской и направляющим вектором бэта-листа
+inline void computeAnglesColorsVsBeta(const gmx::RVec &inputBetaRVec, colorLocalAngles &colorFormation) {
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a1));
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b1));
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n1));
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.a2));
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.b2));
+    colorFormation.betaAngles.push_back(RVecAngle(inputBetaRVec, colorFormation.n2));
+}
+
+// функция записи в файл значений углов для кадра
+void anglesFileDump(const int frameNum, const std::string &output, const std::vector< bool > &toPeptide, const std::vector< colorLocalAngles > &colorFormation) {
+    std::ofstream   file(output);
+    int temp = 0;
+    std::vector< double > betaTemp;
+    betaTemp.resize(0);
+    file << "frame =" << std::setw(8) << frameNum << std::endl;
+    for (size_t i = 0; i < colorFormation.size(); ++i) {
+        file << "color #" << std::setw(3) << i;
+        if (toPeptide[i]) {
+            file << std::setw(4) << "yes";
+        } else {
+            file << std::setw(4) << "no";
+        }
+        file << std::setw(7) << std::setprecision(2) << colorFormation[i].a12 << colorFormation[i].b12 << colorFormation[i].n12;
+        temp = colorFormation[i].betaAngles.size() / 6;
+        if (temp == 0) {
+            file << std::setw(4) << 0;
+        } else {
+            betaTemp.resize(6, 0.); // magic number, meh
+            for (size_t j = 0; j < colorFormation[i].betaAngles.size(); ++j) {
+                betaTemp[j % 6] += colorFormation[i].betaAngles[j];
+            }
+            for (size_t j = 0; j < betaTemp.size(); ++j) {
+                betaTemp[j] /= temp;
+            }
+            file << std::setw(4) << temp;
+            for (size_t j = 0; j < betaTemp.size(); ++j) {
+                file << std::setw(7) << std::setprecision(2) << betaTemp[j];
+            }
+            for (size_t j = 0; j < colorFormation[i].betaAngles.size(); ++j) {
+                file << std::setw(7) << std::setprecision(2) << colorFormation[i].betaAngles[j];
+            }
+        }
+    }
+    file.close();
+}
+
+/*! \brief
+ * \ingroup module_trajectoryanalysis
+ */
+class colorVec : public TrajectoryAnalysisModule
+{
+    public:
+
+        colorVec();
+        virtual ~colorVec();
+
+        //! Set the options and setting
+        virtual void initOptions(IOptionsContainer          *options,
+                                 TrajectoryAnalysisSettings *settings);
+
+        //! First routine called by the analysis framework
+        // virtual void initAnalysis(const t_trxframe &fr, t_pbc *pbc);
+        virtual void initAnalysis(const TrajectoryAnalysisSettings &settings,
+                                  const TopologyInformation        &top);
+
+        //! Call for each frame of the trajectory
+        // virtual void analyzeFrame(const t_trxframe &fr, t_pbc *pbc);
+        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+                                  TrajectoryAnalysisModuleData *pdata);
+
+        //! Last routine called by the analysis framework
+        // virtual void finishAnalysis(t_pbc *pbc);
+        virtual void finishAnalysis(int nframes);
+
+        //! Routine to write output, that is additional over the built-in
+        virtual void writeOutput();
+
+    private:
+
+        SelectionList                                                   sel_;
+        std::string                                                     fnOut;                  // selectable
+        std::string                                                     fnBetaListsDat;         // selectable
+        float                                                           effRad          {0.8};  // selectable
+        std::vector< size_t >                                           index;
+        std::vector< std::vector< std::pair< std::string, size_t > > >  colorsNames;
+        std::vector< std::vector< std::vector< unsigned int > > >       betaLists;
+        AnalysisNeighborhood                                            nb_;
+
+        // Copy and assign disallowed by base.
+};
+
+colorVec::colorVec(): TrajectoryAnalysisModule()
+{
+}
+
+colorVec::~colorVec()
+{
+}
+
+/*
+ * ndx:
+ * [peptide]
+ * [color_{i}]
+ *
+ */
+
+void
+colorVec::initOptions(IOptionsContainer         *options,
+                     TrajectoryAnalysisSettings *settings)
+{
+    static const char *const desc[] = {
+        "[THISMODULE] to be done"
+    };
+    // Add the descriptive text (program help text) to the options
+    settings->setHelpText(desc);
+    // Add option for selection list
+    options->addOption(SelectionOption("sel")
+                            .storeVector(&sel_)
+                            .required().dynamicMask().multiValue()
+                            .description("select residue and domains to form a rigid skeleton / -sf"));
+    // Add option for output file name
+    options->addOption(FileNameOption("dat").filetype(eftOptionFileType_NR).inputFile()
+                            .store(&fnBetaListsDat).description("a file to make dynamic beta lists"));
+    // Add option for output file name
+    options->addOption(FileNameOption("out").filetype(eftOptionFileType_NR).outputFile()
+                            .store(&fnOut).defaultBasename("colorAngles")
+                            .description("Index file for the algorithm output."));
+    // Add option for effRad constant
+    options->addOption(FloatOption("efRad")
+                            .store(&effRad)
+                            .description("max distance from colors to peptide in nm to consider to be \"near\""));
+    // Control input settings
+    settings->setFlags(TrajectoryAnalysisSettings::efNoUserPBC);
+    settings->setFlag(TrajectoryAnalysisSettings::efUseTopX);
+    //settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
+    settings->setPBC(true);
+}
+
+void
+colorVec::initAnalysis(const TrajectoryAnalysisSettings &settings,
+                      const TopologyInformation         &top)
+{
+    // считывание индекса
+    index.resize(0);
+    for (ArrayRef< const int >::iterator ai {sel_.front().atomIndices().begin()}; (ai < sel_.front().atomIndices().end()); ai++) {
+        index.push_back(static_cast< size_t >(*ai));
+    }
+    // считывание красок
+    colorsNames.resize(sel_.size() - 1);
+    for (size_t i = 1; i < sel_.size(); ++i) {
+        for (ArrayRef< const int >::iterator ai {sel_[i].atomIndices().begin()}; (ai < sel_[i].atomIndices().end()); ai++) {
+            colorsNames[i - 1].push_back(std::make_pair(*(top.atoms()->resinfo[top.atoms()->atom[*ai].resind].name), static_cast< size_t >(*ai)));
+        }
+    }
+    // разбор dat файла для создания бэта листов
+    betaListDigestion(fnBetaListsDat, betaLists);
+    // задание радиуса рассматриваемых соседей
+    nb_.setCutoff(effRad);
+    /*
+     * формально можно сделать:
+     * найти соотношение между именами для углов и индексными номерами
+     * заполнить std::vector< std::vector< size_t > > nameToIndex;
+     * и в последствии считать:
+     * a1 = frame[nameToIndex[0][1] + ... - ... - ...
+     * b1 a2 b2 по аналогии только для [@<-[1, 2, 3]]
+     *
+     */
+}
+
+void
+colorVec::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata)
+{
+    std::vector< RVec > trajectoryFrame;
+    trajectoryFrame.resize(0);
+    // считывания текущего фрейма траектории
+    for (size_t i {0}; i < index.size(); ++i) {
+        trajectoryFrame.push_back(fr.x[index[i]]);
+    }
+    // подсчёт углов в красках
+    std::vector< colorLocalAngles > colorFormation;
+    colorsAnglesEvaluation(trajectoryFrame, colorsNames, colorFormation);
+    // рассчёт положения относительно белка
+    /*
+     * формально можно совместить определение близости с белком и определение ближайших бэта-листов
+     * для этого думаю нужно как-то соотнести или сделать соотношение между индексом и бэта-листами (т.е. хранить что бы за О(1) делать)
+     *
+     */
+
+    std::vector< bool >     colorsToPeptide;
+    colorsToPeptide.resize(0);
+    colorsToPeptide.resize(colorsNames.size(), false);
+    for (size_t i = 0; i < colorsNames.size(); ++i) {
+        colorsToPeptide[i] = isNearPeptide(fr, pbc, trajectoryFrame, nb_, index, colorsNames[i]);
+    }
+    // расчёт угла и среднего угла с ближайшими бета листами
+    std::vector< std::vector< bool > > colorsToBeta;
+    colorsToBeta.resize(0);
+    colorsToBeta.resize(colorsNames.size());
+    std::vector< std::vector< double > > colorsToBetaAngles;
+    colorsToBetaAngles.resize(0);
+    std::vector< gmx::RVec > betaListsRVecs;
+    betaListsRVecsEvaluation(trajectoryFrame, betaLists[frnr], betaListsRVecs);
+    for (size_t i = 0; i < colorsToPeptide.size(); ++i) {
+        if (colorsToPeptide[i]) {
+            searchNearBetaLists(fr, pbc, trajectoryFrame, nb_, betaLists[frnr], colorsNames[i], colorsToBeta[i]);
+        }
+    }
+    for (size_t i = 0; i < colorsToBeta.size(); ++i) {
+        for (size_t j = 0; j < colorsToBeta[i].size(); ++j) {
+            if (colorsToBeta[i][j]) {
+                computeAnglesColorsVsBeta(betaListsRVecs[j], colorFormation[i]);
+            }
+        }
+    }
+    // вывод в файл(ы) информацию для фрейма
+    anglesFileDump(frnr, fnOut, colorsToPeptide, colorFormation);
+}
+
+void
+colorVec::finishAnalysis(int nframes)
+{
+
+}
+
+void
+colorVec::writeOutput()
+{
+    /*
+     *
+     * frame #<current frame number>
+     * 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>]
+     *
+     */
+    std::cout << "\n\t colorAngles finished successfully\n";
+}
+
+/*! \brief
+ * The main function for the analysis template.
+ */
+int
+main(int argc, char *argv[])
+{
+    return gmx::TrajectoryAnalysisCommandLineRunner::runAsMain<colorVec>(argc, argv);
+}
diff --git a/src/domains.cpp b/src/domains.cpp
deleted file mode 100644 (file)
index a03015f..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-/*! \internal \file
- * \brief
- * Implements gmx::analysismodules::Freevolume.
- *
- * \author Titov Anatoly <Wapuk-cobaka@yandex.ru>
- * \ingroup module_trajectoryanalysis
- */
-
-#include "domaintype.h"
-#include "newfit.h"
-
-#include <gromacs/trajectoryanalysis.h>
-#include <gromacs/trajectoryanalysis/topologyinformation.h>
-//#include "/home/titov_ai/Develop/gromacs-original/src/gromacs/trajectoryanalysis/topologyinformation.h"
-
-#include <iostream>
-//#include <chrono>
-#include <cfloat>
-#include <omp.h>
-#include <vector>
-#include <cstdio>
-
-using namespace gmx;
-
-using gmx::RVec;
-
-/*! \brief
- * \ingroup module_trajectoryanalysis
- */
-class Domains : public TrajectoryAnalysisModule
-{
-    public:
-
-        Domains();
-        virtual ~Domains();
-
-        //! Set the options and setting
-        virtual void initOptions(IOptionsContainer          *options,
-                                 TrajectoryAnalysisSettings *settings);
-
-        //! First routine called by the analysis framework
-        // virtual void initAnalysis(const t_trxframe &fr, t_pbc *pbc);
-        virtual void initAnalysis(const TrajectoryAnalysisSettings &settings,
-                                  const TopologyInformation        &top);
-
-        //! Call for each frame of the trajectory
-        // virtual void analyzeFrame(const t_trxframe &fr, t_pbc *pbc);
-        virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
-                                  TrajectoryAnalysisModuleData *pdata);
-
-        //! Last routine called by the analysis framework
-        // virtual void finishAnalysis(t_pbc *pbc);
-        virtual void finishAnalysis(int nframes);
-
-        //! Routine to write output, that is additional over the built-in
-        virtual void writeOutput();
-
-    private:
-
-        std::string                                                 fnNdx_;
-        domainType                                                  testSubject;
-        std::vector< size_t >                                       index;
-        std::vector< RVec >                                         trajectory;
-        std::vector< RVec >                                         reference;
-        Selection                                                   selec;
-        std::vector< std::vector< std::pair< size_t, size_t > > >   fitPairs;
-        unsigned int                                                bone;
-        int                                                         window                      {-1}; // selectable
-        int                                                         domain_min_size             {-1}; // selectable
-        double                                                      delta                       {-1}; // selectable
-        double                                                      epsi                        {-1}; // selectable
-        int                                                         twStep                      {-1}; // selectable
-        int                                                         DomainSearchingAlgorythm    {-1}; // selectable
-        // Copy and assign disallowed by base.
-};
-
-Domains::Domains(): TrajectoryAnalysisModule()
-{
-}
-
-Domains::~Domains()
-{
-}
-
-void
-Domains::initOptions(IOptionsContainer          *options,
-                     TrajectoryAnalysisSettings *settings)
-{
-    static const char *const desc[] = {
-        "[THISMODULE] to be done"
-        "-f trajectory.xtc -s structure.tpr -n index.ndx -sf selectionListFile -on outPutName -dms 4+ -DSA 0/1/2 -eps 0.2 -dlt 0.95 -wSize 1000 -twStep 100"
-    };
-    // Add the descriptive text (program help text) to the options
-    settings->setHelpText(desc);
-    // Add option for selecting a subset of atoms
-    options->addOption(SelectionOption("select")
-                           .store(&selec).required()
-                           .description("Atoms that are considered as part of the excluded volume."));
-    // Add option for output file name
-    options->addOption(FileNameOption("on").filetype(eftIndex).outputFile()
-                            .store(&fnNdx_).defaultBasename("domains")
-                            .description("Index file for the algorithm output."));
-    // Add option for domain min size constant
-    options->addOption(gmx::IntegerOption("dms")
-                            .store(&domain_min_size)
-                            .description("minimum domain size, should be >= 4."));
-    // Add option for Domain's Searching Algorythm
-    options->addOption(gmx::IntegerOption("DSA")
-                            .store(&DomainSearchingAlgorythm)
-                            .description("Domain's Searching Algorythm: 0 == (default) from bigger to smaller | 1 == just the first biggest domain | 2 == from smaller to bigger."));
-    // Add option for epsi constant
-    options->addOption(DoubleOption("eps")
-                            .store(&epsi)
-                            .description("thermal vibrations' constant."));
-    // Add option for delta constant
-    options->addOption(DoubleOption("dlt")
-                            .store(&delta)
-                            .description("domain membership probability."));
-    // Add option for domain min size constant
-    options->addOption(gmx::IntegerOption("wSize")
-                            .store(&window)
-                            .description("flowing window to evaluate domains from."));
-    // Add option for time step between windows' starts
-    options->addOption(gmx::IntegerOption("twStep")
-                            .store(&twStep)
-                            .description("time step between windows' starting positions."));
-    // Control input settings
-    settings->setFlags(TrajectoryAnalysisSettings::efNoUserPBC);
-    settings->setFlag(TrajectoryAnalysisSettings::efUseTopX);
-    //settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
-    settings->setPBC(true);
-}
-
-// -f trajectory.xtc -s structure.tpr -n index.ndx -sf selectionListFile -on outPutName -dms 4+ -DSA 0/1/2 -eps 0.2 -dlt 0.95 -wSize 1000 -twStep 100
-
-void
-Domains::initAnalysis(const TrajectoryAnalysisSettings &settings,
-                      const TopologyInformation        &top)
-{
-    // считывание индекса
-    index.resize(0);
-    for (ArrayRef< const int >::iterator ai {selec.atomIndices().begin()}; (ai < selec.atomIndices().end()); ai++) {
-        index.push_back(static_cast< size_t >(*ai));
-    }
-
-    // считывание референсной структуры
-    reference.resize(0);
-
-    if (top.hasFullTopology()) {
-        for (const auto &i : index) {
-            reference.push_back(top.x().at(i));
-        }
-    }
-
-    // вычисление числа основных (от основание) последовательностей
-    // в идеале нужно брать все сочетания, но ограничиваемся последовательными наборами
-    bone = static_cast< size_t >(index.size() - static_cast< size_t >(domain_min_size) + 1);
-
-    // создание пар для фитирования структур
-    fitPairs.resize(0);
-    fitPairs.resize(bone);
-    for (size_t i {0}; i < bone; i++) {
-        fitPairs[i].resize(0);
-        for (size_t j {0}; j < domain_min_size; j++) {
-            fitPairs[i].push_back(std::make_pair(j + i, j + i));
-        }
-    }
-
-    trajectory.resize(0);
-    trajectory.resize(index.size());
-
-    // задание необходимых параметров для вычисления доменов
-    testSubject.setDefaults(index, reference, window, domain_min_size, DomainSearchingAlgorythm, twStep, bone, epsi, delta, fnNdx_);
-}
-
-void
-Domains::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata)
-{
-    // считывания текущего фрейма траектории
-    for (size_t i {0}; i < index.size(); i++) {
-        trajectory[i] = fr.x[index[i]];
-    }
-
-    // создание копий фрейма для каждой основной последовательности
-    std::vector< std::vector< RVec > > tsTemp;
-    tsTemp.resize(0);
-    tsTemp.resize(bone, trajectory);
-
-    // фитирование каждой копии
-    #pragma omp parallel for ordered schedule(dynamic) firstprivate(reference)
-    for (size_t i = 0; i < bone; i++) {
-        MyFitNew(reference, tsTemp[i], fitPairs[i], 0.000'001);
-    }
-    #pragma omp barrier
-
-    // (обновление/потенциальное выделение) доменов
-    testSubject.update(tsTemp, frnr);
-}
-
-void
-Domains::finishAnalysis(int nframes)
-{
-
-}
-
-void
-Domains::writeOutput()
-{
-    std::cout << "\n END \n";
-}
-
-/*! \brief
- * The main function for the analysis template.
- */
-int
-main(int argc, char *argv[])
-{
-    return gmx::TrajectoryAnalysisCommandLineRunner::runAsMain<Domains>(argc, argv);
-}