3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements classes in analysismodule.h.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_trajectoryanalysis
38 #include "gromacs/trajectoryanalysis/analysismodule.h"
42 #include "gromacs/analysisdata/analysisdata.h"
43 #include "gromacs/selection/selection.h"
44 #include "gromacs/utility/exceptions.h"
45 #include "gromacs/utility/gmxassert.h"
50 /********************************************************************
51 * TrajectoryAnalysisModule::Impl
55 * Private implementation class for TrajectoryAnalysisModule.
57 * \ingroup module_trajectoryanalysis
59 class TrajectoryAnalysisModule::Impl
62 //! Container that associates a data set with its name.
63 typedef std::map<std::string, AbstractAnalysisData *> DatasetContainer;
64 //! Container that associates a AnalysisData object with its name.
65 typedef std::map<std::string, AnalysisData *> AnalysisDatasetContainer;
67 //! List of registered data set names.
68 std::vector<std::string> datasetNames_;
70 * Keeps all registered data sets.
72 * This container also includes datasets from \a analysisDatasets_.
74 DatasetContainer datasets_;
75 //! Keeps registered AnalysisData objects.
76 AnalysisDatasetContainer analysisDatasets_;
79 /********************************************************************
80 * TrajectoryAnalysisModuleData::Impl
84 * Private implementation class for TrajectoryAnalysisModuleData.
86 * \ingroup module_trajectoryanalysis
88 class TrajectoryAnalysisModuleData::Impl
91 //! Container that associates a data handle to its AnalysisData object.
92 typedef std::map<const AnalysisData *, AnalysisDataHandle>
95 //! \copydoc TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData()
96 Impl(TrajectoryAnalysisModule *module,
97 const AnalysisDataParallelOptions &opt,
98 const SelectionCollection &selections);
100 //! Keeps a data handle for each AnalysisData object.
101 HandleContainer handles_;
102 //! Stores thread-local selections.
103 const SelectionCollection &selections_;
106 TrajectoryAnalysisModuleData::Impl::Impl(
107 TrajectoryAnalysisModule *module,
108 const AnalysisDataParallelOptions &opt,
109 const SelectionCollection &selections)
110 : selections_(selections)
112 TrajectoryAnalysisModule::Impl::AnalysisDatasetContainer::const_iterator i;
113 for (i = module->impl_->analysisDatasets_.begin();
114 i != module->impl_->analysisDatasets_.end(); ++i)
116 handles_.insert(std::make_pair(i->second, i->second->startData(opt)));
121 /********************************************************************
122 * TrajectoryAnalysisModuleData
125 TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData(
126 TrajectoryAnalysisModule *module,
127 const AnalysisDataParallelOptions &opt,
128 const SelectionCollection &selections)
129 : impl_(new Impl(module, opt, selections))
134 TrajectoryAnalysisModuleData::~TrajectoryAnalysisModuleData()
139 void TrajectoryAnalysisModuleData::finishDataHandles()
141 // FIXME: Call finishData() for all handles even if one throws
142 Impl::HandleContainer::iterator i;
143 for (i = impl_->handles_.begin(); i != impl_->handles_.end(); ++i)
145 i->second.finishData();
147 impl_->handles_.clear();
152 TrajectoryAnalysisModuleData::dataHandle(const AnalysisData &data)
154 Impl::HandleContainer::const_iterator i = impl_->handles_.find(&data);
155 GMX_RELEASE_ASSERT(i != impl_->handles_.end(),
156 "Data handle requested on unknown dataset");
161 Selection TrajectoryAnalysisModuleData::parallelSelection(const Selection &selection)
163 // TODO: Implement properly.
169 TrajectoryAnalysisModuleData::parallelSelections(const SelectionList &selections)
171 // TODO: Consider an implementation that does not allocate memory every time.
172 SelectionList newSelections;
173 newSelections.reserve(selections.size());
174 SelectionList::const_iterator i = selections.begin();
175 for ( ; i != selections.end(); ++i)
177 newSelections.push_back(parallelSelection(*i));
179 return newSelections;
183 /********************************************************************
184 * TrajectoryAnalysisModuleDataBasic
191 * Basic thread-local trajectory analysis data storage class.
193 * Most simple tools should only require data handles and selections to be
194 * thread-local, so this class implements just that.
196 * \ingroup module_trajectoryanalysis
198 class TrajectoryAnalysisModuleDataBasic : public TrajectoryAnalysisModuleData
202 * Initializes thread-local storage for data handles and selections.
204 * \param[in] module Analysis module to use for data objects.
205 * \param[in] opt Data parallelization options.
206 * \param[in] selections Thread-local selection collection.
208 TrajectoryAnalysisModuleDataBasic(TrajectoryAnalysisModule *module,
209 const AnalysisDataParallelOptions &opt,
210 const SelectionCollection &selections);
212 virtual void finish();
215 TrajectoryAnalysisModuleDataBasic::TrajectoryAnalysisModuleDataBasic(
216 TrajectoryAnalysisModule *module,
217 const AnalysisDataParallelOptions &opt,
218 const SelectionCollection &selections)
219 : TrajectoryAnalysisModuleData(module, opt, selections)
225 TrajectoryAnalysisModuleDataBasic::finish()
233 /********************************************************************
234 * TrajectoryAnalysisModule
237 TrajectoryAnalysisModule::TrajectoryAnalysisModule()
243 TrajectoryAnalysisModule::~TrajectoryAnalysisModule()
248 void TrajectoryAnalysisModule::initOptionsDone(TrajectoryAnalysisSettings * /*settings*/)
253 void TrajectoryAnalysisModule::initAfterFirstFrame(const t_trxframe &/*fr*/)
258 TrajectoryAnalysisModuleDataPointer
259 TrajectoryAnalysisModule::startFrames(const AnalysisDataParallelOptions &opt,
260 const SelectionCollection &selections)
262 return TrajectoryAnalysisModuleDataPointer(
263 new TrajectoryAnalysisModuleDataBasic(this, opt, selections));
267 void TrajectoryAnalysisModule::finishFrames(TrajectoryAnalysisModuleData * /*pdata*/)
272 int TrajectoryAnalysisModule::datasetCount() const
274 return impl_->datasetNames_.size();
278 const std::vector<std::string> &TrajectoryAnalysisModule::datasetNames() const
280 return impl_->datasetNames_;
284 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromIndex(int index) const
286 if (index < 0 || index >= datasetCount())
288 GMX_THROW(APIError("Out of range data set index"));
290 Impl::DatasetContainer::const_iterator item
291 = impl_->datasets_.find(impl_->datasetNames_[index]);
292 GMX_RELEASE_ASSERT(item != impl_->datasets_.end(),
293 "Inconsistent data set names");
294 return *item->second;
298 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromName(const char *name) const
300 Impl::DatasetContainer::const_iterator item = impl_->datasets_.find(name);
301 if (item == impl_->datasets_.end())
303 GMX_THROW(APIError("Unknown data set name"));
305 return *item->second;
309 void TrajectoryAnalysisModule::registerBasicDataset(AbstractAnalysisData *data,
312 // TODO: Strong exception safety should be possible to implement.
313 GMX_RELEASE_ASSERT(impl_->datasets_.find(name) == impl_->datasets_.end(),
314 "Duplicate data set name registered");
315 impl_->datasets_[name] = data;
316 impl_->datasetNames_.push_back(name);
320 void TrajectoryAnalysisModule::registerAnalysisDataset(AnalysisData *data,
323 // TODO: Strong exception safety should be possible to implement.
324 registerBasicDataset(data, name);
325 impl_->analysisDatasets_[name] = data;