2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019, 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::ExtractCluster.
39 * \author Paul Bauer <paul.bauer.q@gmail.com>
40 * \ingroup module_trajectoryanalysis
45 #include "extract_cluster.h"
49 #include "gromacs/coordinateio/coordinatefile.h"
50 #include "gromacs/coordinateio/requirements.h"
51 #include "gromacs/options/filenameoption.h"
52 #include "gromacs/options/ioptionscontainer.h"
53 #include "gromacs/selection/selectionoption.h"
54 #include "gromacs/topology/index.h"
55 #include "gromacs/trajectoryanalysis/analysissettings.h"
56 #include "gromacs/trajectoryanalysis/topologyinformation.h"
57 #include "gromacs/utility/path.h"
58 #include "gromacs/utility/stringutil.h"
63 namespace analysismodules
73 class ExtractCluster : public TrajectoryAnalysisModule
78 ~ExtractCluster() override;
80 void initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings* settings) override;
81 void optionsFinished(TrajectoryAnalysisSettings* settings) override;
82 void initAnalysis(const TrajectoryAnalysisSettings& settings, const TopologyInformation& top) override;
83 void analyzeFrame(int frameNumber, const t_trxframe& fr, t_pbc* pbc, TrajectoryAnalysisModuleData* pdata) override;
85 void finishAnalysis(int nframes) override;
86 void writeOutput() override;
89 //! Storage of objects that handle output files.
90 std::vector<TrajectoryFrameWriterPointer> writers_;
91 //! Selection used for output.
93 //! Name for output file.
94 std::string outputNamePrefix_;
95 //! Name for index file.
96 std::string indexFileName_;
97 //! Storage of requirements for creating output files.
98 OutputRequirementOptionDirector requirementsBuilder_;
99 //! Stores the index information for the clusters. TODO refactor this!
100 t_cluster_ndx* clusterIndex_ = nullptr;
103 ExtractCluster::ExtractCluster() {}
105 ExtractCluster::~ExtractCluster()
107 if (clusterIndex_ != nullptr)
109 if (clusterIndex_->grpname != nullptr)
111 for (int i = 0; i < clusterIndex_->clust->nr; i++)
113 sfree(clusterIndex_->grpname[i]);
115 sfree(clusterIndex_->grpname);
117 if (clusterIndex_->clust != nullptr)
119 sfree(clusterIndex_->inv_clust);
120 done_blocka(clusterIndex_->clust);
121 sfree(clusterIndex_->clust);
123 sfree(clusterIndex_);
128 void ExtractCluster::initOptions(IOptionsContainer* options, TrajectoryAnalysisSettings* settings)
130 static const char* const desc[] = {
131 "[THISMODULE] can be used to extract trajectory frames that correspond to clusters ",
132 "obtained from running gmx cluster with the -clndx option.",
133 "The module supports writing all GROMACS supported trajectory file formats.",
135 "Included is also a selection of possible options to change additional information.",
137 "It is possible to write only a selection of atoms to the output trajectory",
138 "files for each cluster.",
141 options->addOption(FileNameOption("clusters")
145 .store(&indexFileName_)
146 .defaultBasename("cluster")
147 .description("Name of index file containing frame indices for each "
148 "cluster, obtained from gmx cluster -clndx."));
150 options->addOption(SelectionOption("select").store(&sel_).onlyAtoms().description(
151 "Selection of atoms to write to the file"));
153 options->addOption(FileNameOption("o")
154 .filetype(eftTrajectory)
156 .store(&outputNamePrefix_)
157 .defaultBasename("trajout")
159 .description("Prefix for the name of the trajectory file written "
160 "for each cluster."));
162 requirementsBuilder_.initOptions(options);
164 settings->setHelpText(desc);
167 void ExtractCluster::optionsFinished(TrajectoryAnalysisSettings* settings)
169 int frameFlags = TRX_NEED_X;
171 frameFlags |= TRX_READ_V | TRX_READ_F;
173 settings->setFrameFlags(frameFlags);
175 clusterIndex_ = cluster_index(nullptr, indexFileName_.c_str());
179 void ExtractCluster::initAnalysis(const TrajectoryAnalysisSettings& /*settings*/,
180 const TopologyInformation& top)
182 int numberOfClusters = clusterIndex_->clust->nr;
183 for (int i = 0; i < numberOfClusters; i++)
185 std::string outputName = Path::concatenateBeforeExtension(
186 outputNamePrefix_, formatString("_%s", clusterIndex_->grpname[i]));
187 writers_.emplace_back(createTrajectoryFrameWriter(top.mtop(), sel_, outputName,
188 top.hasTopology() ? top.copyAtoms() : nullptr,
189 requirementsBuilder_.process()));
193 void ExtractCluster::analyzeFrame(int frameNumber,
194 const t_trxframe& frame,
196 TrajectoryAnalysisModuleData* /*pdata*/)
198 // modify frame to write out correct number of coords
199 // and actually write out
200 int clusterToWriteTo = clusterIndex_->inv_clust[frameNumber];
201 // Check for valid entry in cluster list, otherwise skip frame.
202 if (clusterToWriteTo != -1 && clusterToWriteTo < clusterIndex_->clust->nr)
204 writers_[clusterToWriteTo]->prepareAndWriteFrame(frameNumber, frame);
208 printf("Frame %d was not found in any cluster!", frameNumber);
212 void ExtractCluster::finishAnalysis(int /*nframes*/) {}
215 void ExtractCluster::writeOutput() {}
219 const char ExtractClusterInfo::name[] = "extract-cluster";
220 const char ExtractClusterInfo::shortDescription[] =
221 "Allows extracting frames corresponding to clusters from trajectory";
223 TrajectoryAnalysisModulePointer ExtractClusterInfo::create()
225 return TrajectoryAnalysisModulePointer(new ExtractCluster);
228 } // namespace analysismodules