Remove more underscore-prefixed C++ symbols.
[alexxy/gromacs.git] / src / gromacs / trajectoryanalysis / analysismodule.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Implements classes in analysismodule.h.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_trajectoryanalysis
37  */
38 #include "gromacs/trajectoryanalysis/analysismodule.h"
39
40 #include <utility>
41
42 #include "gromacs/analysisdata/analysisdata.h"
43 #include "gromacs/selection/selection.h"
44 #include "gromacs/utility/exceptions.h"
45 #include "gromacs/utility/gmxassert.h"
46
47 namespace gmx
48 {
49
50 /********************************************************************
51  * TrajectoryAnalysisModule::Impl
52  */
53
54 /*! \internal \brief
55  * Private implementation class for TrajectoryAnalysisModule.
56  *
57  * \ingroup module_trajectoryanalysis
58  */
59 class TrajectoryAnalysisModule::Impl
60 {
61     public:
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;
66
67         //! List of registered data set names.
68         std::vector<std::string>        datasetNames_;
69         /*! \brief
70          * Keeps all registered data sets.
71          *
72          * This container also includes datasets from \a analysisDatasets_.
73          */
74         DatasetContainer                datasets_;
75         //! Keeps registered AnalysisData objects.
76         AnalysisDatasetContainer        analysisDatasets_;
77 };
78
79 /********************************************************************
80  * TrajectoryAnalysisModuleData::Impl
81  */
82
83 /*! \internal \brief
84  * Private implementation class for TrajectoryAnalysisModuleData.
85  *
86  * \ingroup module_trajectoryanalysis
87  */
88 class TrajectoryAnalysisModuleData::Impl
89 {
90     public:
91         //! Container that associates a data handle to its AnalysisData object.
92         typedef std::map<const AnalysisData *, AnalysisDataHandle>
93                 HandleContainer;
94
95         //! \copydoc TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData()
96         Impl(TrajectoryAnalysisModule *module,
97              const AnalysisDataParallelOptions &opt,
98              const SelectionCollection &selections);
99
100         //! Keeps a data handle for each AnalysisData object.
101         HandleContainer         handles_;
102         //! Stores thread-local selections.
103         const SelectionCollection &selections_;
104 };
105
106 TrajectoryAnalysisModuleData::Impl::Impl(
107         TrajectoryAnalysisModule *module,
108         const AnalysisDataParallelOptions &opt,
109         const SelectionCollection &selections)
110     : selections_(selections)
111 {
112     TrajectoryAnalysisModule::Impl::AnalysisDatasetContainer::const_iterator i;
113     for (i = module->impl_->analysisDatasets_.begin();
114          i != module->impl_->analysisDatasets_.end(); ++i)
115     {
116         handles_.insert(std::make_pair(i->second, i->second->startData(opt)));
117     }
118 }
119
120
121 /********************************************************************
122  * TrajectoryAnalysisModuleData
123  */
124
125 TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData(
126         TrajectoryAnalysisModule *module,
127         const AnalysisDataParallelOptions &opt,
128         const SelectionCollection &selections)
129     : impl_(new Impl(module, opt, selections))
130 {
131 }
132
133
134 TrajectoryAnalysisModuleData::~TrajectoryAnalysisModuleData()
135 {
136 }
137
138
139 void TrajectoryAnalysisModuleData::finishDataHandles()
140 {
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)
144     {
145         i->second.finishData();
146     }
147     impl_->handles_.clear();
148 }
149
150
151 AnalysisDataHandle
152 TrajectoryAnalysisModuleData::dataHandle(const AnalysisData &data)
153 {
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");
157     return i->second;
158 }
159
160
161 Selection TrajectoryAnalysisModuleData::parallelSelection(const Selection &selection)
162 {
163     // TODO: Implement properly.
164     return selection;
165 }
166
167
168 SelectionList
169 TrajectoryAnalysisModuleData::parallelSelections(const SelectionList &selections)
170 {
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)
176     {
177         newSelections.push_back(parallelSelection(*i));
178     }
179     return newSelections;
180 }
181
182
183 /********************************************************************
184  * TrajectoryAnalysisModuleDataBasic
185  */
186
187 namespace
188 {
189
190 /*! \internal \brief
191  * Basic thread-local trajectory analysis data storage class.
192  *
193  * Most simple tools should only require data handles and selections to be
194  * thread-local, so this class implements just that.
195  *
196  * \ingroup module_trajectoryanalysis
197  */
198 class TrajectoryAnalysisModuleDataBasic : public TrajectoryAnalysisModuleData
199 {
200     public:
201         /*! \brief
202          * Initializes thread-local storage for data handles and selections.
203          *
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.
207          */
208         TrajectoryAnalysisModuleDataBasic(TrajectoryAnalysisModule *module,
209                                           const AnalysisDataParallelOptions &opt,
210                                           const SelectionCollection &selections);
211
212         virtual void finish();
213 };
214
215 TrajectoryAnalysisModuleDataBasic::TrajectoryAnalysisModuleDataBasic(
216         TrajectoryAnalysisModule *module,
217         const AnalysisDataParallelOptions &opt,
218         const SelectionCollection &selections)
219     : TrajectoryAnalysisModuleData(module, opt, selections)
220 {
221 }
222
223
224 void
225 TrajectoryAnalysisModuleDataBasic::finish()
226 {
227     finishDataHandles();
228 }
229
230 } // namespace
231
232
233 /********************************************************************
234  * TrajectoryAnalysisModule
235  */
236
237 TrajectoryAnalysisModule::TrajectoryAnalysisModule()
238     : impl_(new Impl)
239 {
240 }
241
242
243 TrajectoryAnalysisModule::~TrajectoryAnalysisModule()
244 {
245 }
246
247
248 void TrajectoryAnalysisModule::initOptionsDone(TrajectoryAnalysisSettings * /*settings*/)
249 {
250 }
251
252
253 void TrajectoryAnalysisModule::initAfterFirstFrame(const t_trxframe &/*fr*/)
254 {
255 }
256
257
258 TrajectoryAnalysisModuleDataPointer
259 TrajectoryAnalysisModule::startFrames(const AnalysisDataParallelOptions &opt,
260                                       const SelectionCollection &selections)
261 {
262     return TrajectoryAnalysisModuleDataPointer(
263             new TrajectoryAnalysisModuleDataBasic(this, opt, selections));
264 }
265
266
267 void TrajectoryAnalysisModule::finishFrames(TrajectoryAnalysisModuleData * /*pdata*/)
268 {
269 }
270
271
272 int TrajectoryAnalysisModule::datasetCount() const
273 {
274     return impl_->datasetNames_.size();
275 }
276
277
278 const std::vector<std::string> &TrajectoryAnalysisModule::datasetNames() const
279 {
280     return impl_->datasetNames_;
281 }
282
283
284 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromIndex(int index) const
285 {
286     if (index < 0 || index >= datasetCount())
287     {
288         GMX_THROW(APIError("Out of range data set index"));
289     }
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;
295 }
296
297
298 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromName(const char *name) const
299 {
300     Impl::DatasetContainer::const_iterator item = impl_->datasets_.find(name);
301     if (item == impl_->datasets_.end())
302     {
303         GMX_THROW(APIError("Unknown data set name"));
304     }
305     return *item->second;
306 }
307
308
309 void TrajectoryAnalysisModule::registerBasicDataset(AbstractAnalysisData *data,
310                                                     const char *name)
311 {
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);
317 }
318
319
320 void TrajectoryAnalysisModule::registerAnalysisDataset(AnalysisData *data,
321                                                        const char *name)
322 {
323     // TODO: Strong exception safety should be possible to implement.
324     registerBasicDataset(data, name);
325     impl_->analysisDatasets_[name] = data;
326 }
327
328 } // namespace gmx