Merge release-4-6 into master
[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         //! Initializes analysis module data with given name and description.
68         Impl(const char *name, const char *description)
69             : name_(name), description_(description)
70         {
71         }
72
73         //! Name of the module.
74         std::string                     name_;
75         //! Description of the module.
76         std::string                     description_;
77         //! List of registered data set names.
78         std::vector<std::string>        datasetNames_;
79         /*! \brief
80          * Keeps all registered data sets.
81          *
82          * This container also includes datasets from \a analysisDatasets_.
83          */
84         DatasetContainer                datasets_;
85         //! Keeps registered AnalysisData objects.
86         AnalysisDatasetContainer        analysisDatasets_;
87 };
88
89 /********************************************************************
90  * TrajectoryAnalysisModuleData::Impl
91  */
92
93 /*! \internal \brief
94  * Private implementation class for TrajectoryAnalysisModuleData.
95  *
96  * \ingroup module_trajectoryanalysis
97  */
98 class TrajectoryAnalysisModuleData::Impl
99 {
100     public:
101         //! Container that associates a data handle to its AnalysisData object.
102         typedef std::map<const AnalysisData *, AnalysisDataHandle>
103             HandleContainer;
104
105         //! \copydoc TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData()
106         Impl(TrajectoryAnalysisModule          *module,
107              const AnalysisDataParallelOptions &opt,
108              const SelectionCollection         &selections);
109
110         //! Keeps a data handle for each AnalysisData object.
111         HandleContainer            handles_;
112         //! Stores thread-local selections.
113         const SelectionCollection &selections_;
114 };
115
116 TrajectoryAnalysisModuleData::Impl::Impl(
117         TrajectoryAnalysisModule          *module,
118         const AnalysisDataParallelOptions &opt,
119         const SelectionCollection         &selections)
120     : selections_(selections)
121 {
122     TrajectoryAnalysisModule::Impl::AnalysisDatasetContainer::const_iterator i;
123     for (i = module->impl_->analysisDatasets_.begin();
124          i != module->impl_->analysisDatasets_.end(); ++i)
125     {
126         handles_.insert(std::make_pair(i->second, i->second->startData(opt)));
127     }
128 }
129
130
131 /********************************************************************
132  * TrajectoryAnalysisModuleData
133  */
134
135 TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData(
136         TrajectoryAnalysisModule          *module,
137         const AnalysisDataParallelOptions &opt,
138         const SelectionCollection         &selections)
139     : impl_(new Impl(module, opt, selections))
140 {
141 }
142
143
144 TrajectoryAnalysisModuleData::~TrajectoryAnalysisModuleData()
145 {
146 }
147
148
149 void TrajectoryAnalysisModuleData::finishDataHandles()
150 {
151     // FIXME: Call finishData() for all handles even if one throws
152     Impl::HandleContainer::iterator i;
153     for (i = impl_->handles_.begin(); i != impl_->handles_.end(); ++i)
154     {
155         i->second.finishData();
156     }
157     impl_->handles_.clear();
158 }
159
160
161 AnalysisDataHandle
162 TrajectoryAnalysisModuleData::dataHandle(const AnalysisData &data)
163 {
164     Impl::HandleContainer::const_iterator i = impl_->handles_.find(&data);
165     GMX_RELEASE_ASSERT(i != impl_->handles_.end(),
166                        "Data handle requested on unknown dataset");
167     return i->second;
168 }
169
170
171 Selection TrajectoryAnalysisModuleData::parallelSelection(const Selection &selection)
172 {
173     // TODO: Implement properly.
174     return selection;
175 }
176
177
178 SelectionList
179 TrajectoryAnalysisModuleData::parallelSelections(const SelectionList &selections)
180 {
181     // TODO: Consider an implementation that does not allocate memory every time.
182     SelectionList                 newSelections;
183     newSelections.reserve(selections.size());
184     SelectionList::const_iterator i = selections.begin();
185     for (; i != selections.end(); ++i)
186     {
187         newSelections.push_back(parallelSelection(*i));
188     }
189     return newSelections;
190 }
191
192
193 /********************************************************************
194  * TrajectoryAnalysisModuleDataBasic
195  */
196
197 namespace
198 {
199
200 /*! \internal \brief
201  * Basic thread-local trajectory analysis data storage class.
202  *
203  * Most simple tools should only require data handles and selections to be
204  * thread-local, so this class implements just that.
205  *
206  * \ingroup module_trajectoryanalysis
207  */
208 class TrajectoryAnalysisModuleDataBasic : public TrajectoryAnalysisModuleData
209 {
210     public:
211         /*! \brief
212          * Initializes thread-local storage for data handles and selections.
213          *
214          * \param[in] module     Analysis module to use for data objects.
215          * \param[in] opt        Data parallelization options.
216          * \param[in] selections Thread-local selection collection.
217          */
218         TrajectoryAnalysisModuleDataBasic(TrajectoryAnalysisModule          *module,
219                                           const AnalysisDataParallelOptions &opt,
220                                           const SelectionCollection         &selections);
221
222         virtual void finish();
223 };
224
225 TrajectoryAnalysisModuleDataBasic::TrajectoryAnalysisModuleDataBasic(
226         TrajectoryAnalysisModule          *module,
227         const AnalysisDataParallelOptions &opt,
228         const SelectionCollection         &selections)
229     : TrajectoryAnalysisModuleData(module, opt, selections)
230 {
231 }
232
233
234 void
235 TrajectoryAnalysisModuleDataBasic::finish()
236 {
237     finishDataHandles();
238 }
239
240 }   // namespace
241
242
243 /********************************************************************
244  * TrajectoryAnalysisModule
245  */
246
247 TrajectoryAnalysisModule::TrajectoryAnalysisModule(const char *name,
248                                                    const char *description)
249     : impl_(new Impl(name, description))
250 {
251 }
252
253
254 TrajectoryAnalysisModule::~TrajectoryAnalysisModule()
255 {
256 }
257
258
259 void TrajectoryAnalysisModule::optionsFinished(
260         Options                    * /*options*/,
261         TrajectoryAnalysisSettings * /*settings*/)
262 {
263 }
264
265
266 void TrajectoryAnalysisModule::initAfterFirstFrame(const t_trxframe & /*fr*/)
267 {
268 }
269
270
271 TrajectoryAnalysisModuleDataPointer
272 TrajectoryAnalysisModule::startFrames(const AnalysisDataParallelOptions &opt,
273                                       const SelectionCollection         &selections)
274 {
275     return TrajectoryAnalysisModuleDataPointer(
276             new TrajectoryAnalysisModuleDataBasic(this, opt, selections));
277 }
278
279
280 void TrajectoryAnalysisModule::finishFrames(TrajectoryAnalysisModuleData * /*pdata*/)
281 {
282 }
283
284
285 const char *TrajectoryAnalysisModule::name() const
286 {
287     return impl_->name_.c_str();
288 }
289
290
291 const char *TrajectoryAnalysisModule::description() const
292 {
293     return impl_->description_.c_str();
294 }
295
296
297 int TrajectoryAnalysisModule::datasetCount() const
298 {
299     return impl_->datasetNames_.size();
300 }
301
302
303 const std::vector<std::string> &TrajectoryAnalysisModule::datasetNames() const
304 {
305     return impl_->datasetNames_;
306 }
307
308
309 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromIndex(int index) const
310 {
311     if (index < 0 || index >= datasetCount())
312     {
313         GMX_THROW(APIError("Out of range data set index"));
314     }
315     Impl::DatasetContainer::const_iterator item
316         = impl_->datasets_.find(impl_->datasetNames_[index]);
317     GMX_RELEASE_ASSERT(item != impl_->datasets_.end(),
318                        "Inconsistent data set names");
319     return *item->second;
320 }
321
322
323 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromName(const char *name) const
324 {
325     Impl::DatasetContainer::const_iterator item = impl_->datasets_.find(name);
326     if (item == impl_->datasets_.end())
327     {
328         GMX_THROW(APIError("Unknown data set name"));
329     }
330     return *item->second;
331 }
332
333
334 void TrajectoryAnalysisModule::registerBasicDataset(AbstractAnalysisData *data,
335                                                     const char           *name)
336 {
337     // TODO: Strong exception safety should be possible to implement.
338     GMX_RELEASE_ASSERT(impl_->datasets_.find(name) == impl_->datasets_.end(),
339                        "Duplicate data set name registered");
340     impl_->datasets_[name] = data;
341     impl_->datasetNames_.push_back(name);
342 }
343
344
345 void TrajectoryAnalysisModule::registerAnalysisDataset(AnalysisData *data,
346                                                        const char   *name)
347 {
348     // TODO: Strong exception safety should be possible to implement.
349     registerBasicDataset(data, name);
350     impl_->analysisDatasets_[name] = data;
351 }
352
353 } // namespace gmx