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 #include "analysismodule-impl.h"
48
49 namespace gmx
50 {
51
52 /********************************************************************
53  * TrajectoryAnalysisModuleData::Impl
54  */
55
56 TrajectoryAnalysisModuleData::Impl::Impl(
57         TrajectoryAnalysisModule *module,
58         const AnalysisDataParallelOptions &opt,
59         const SelectionCollection &selections)
60     : _selections(selections)
61 {
62     TrajectoryAnalysisModule::Impl::AnalysisDatasetContainer::const_iterator i;
63     for (i = module->_impl->_analysisDatasets.begin();
64          i != module->_impl->_analysisDatasets.end(); ++i)
65     {
66         _handles.insert(std::make_pair(i->second, i->second->startData(opt)));
67     }
68 }
69
70 TrajectoryAnalysisModuleData::Impl::~Impl()
71 {
72 }
73
74
75 /********************************************************************
76  * TrajectoryAnalysisModuleData
77  */
78
79 TrajectoryAnalysisModuleData::TrajectoryAnalysisModuleData(
80         TrajectoryAnalysisModule *module,
81         const AnalysisDataParallelOptions &opt,
82         const SelectionCollection &selections)
83     : _impl(new Impl(module, opt, selections))
84 {
85 }
86
87
88 TrajectoryAnalysisModuleData::~TrajectoryAnalysisModuleData()
89 {
90 }
91
92
93 void TrajectoryAnalysisModuleData::finishDataHandles()
94 {
95     // FIXME: Call finishData() for all handles even if one throws
96     Impl::HandleContainer::iterator i;
97     for (i = _impl->_handles.begin(); i != _impl->_handles.end(); ++i)
98     {
99         i->second.finishData();
100     }
101     _impl->_handles.clear();
102 }
103
104
105 AnalysisDataHandle
106 TrajectoryAnalysisModuleData::dataHandle(const AnalysisData &data)
107 {
108     Impl::HandleContainer::const_iterator i = _impl->_handles.find(&data);
109     GMX_RELEASE_ASSERT(i != _impl->_handles.end(),
110                        "Data handle requested on unknown dataset");
111     return i->second;
112 }
113
114
115 Selection TrajectoryAnalysisModuleData::parallelSelection(const Selection &selection)
116 {
117     // TODO: Implement properly.
118     return selection;
119 }
120
121
122 SelectionList
123 TrajectoryAnalysisModuleData::parallelSelections(const SelectionList &selections)
124 {
125     // TODO: Consider an implementation that does not allocate memory every time.
126     SelectionList newSelections;
127     newSelections.reserve(selections.size());
128     SelectionList::const_iterator i = selections.begin();
129     for ( ; i != selections.end(); ++i)
130     {
131         newSelections.push_back(parallelSelection(*i));
132     }
133     return newSelections;
134 }
135
136
137 /********************************************************************
138  * TrajectoryAnalysisModuleDataBasic
139  */
140 TrajectoryAnalysisModuleDataBasic::TrajectoryAnalysisModuleDataBasic(
141         TrajectoryAnalysisModule *module,
142         const AnalysisDataParallelOptions &opt,
143         const SelectionCollection &selections)
144     : TrajectoryAnalysisModuleData(module, opt, selections)
145 {
146 }
147
148
149 void
150 TrajectoryAnalysisModuleDataBasic::finish()
151 {
152     finishDataHandles();
153 }
154
155
156 /********************************************************************
157  * TrajectoryAnalysisModule
158  */
159
160 TrajectoryAnalysisModule::TrajectoryAnalysisModule()
161     : _impl(new Impl)
162 {
163 }
164
165
166 TrajectoryAnalysisModule::~TrajectoryAnalysisModule()
167 {
168 }
169
170
171 void TrajectoryAnalysisModule::initOptionsDone(TrajectoryAnalysisSettings * /*settings*/)
172 {
173 }
174
175
176 void TrajectoryAnalysisModule::initAfterFirstFrame(const t_trxframe &/*fr*/)
177 {
178 }
179
180
181 TrajectoryAnalysisModuleDataPointer
182 TrajectoryAnalysisModule::startFrames(const AnalysisDataParallelOptions &opt,
183                                       const SelectionCollection &selections)
184 {
185     return TrajectoryAnalysisModuleDataPointer(
186             new TrajectoryAnalysisModuleDataBasic(this, opt, selections));
187 }
188
189
190 void TrajectoryAnalysisModule::finishFrames(TrajectoryAnalysisModuleData * /*pdata*/)
191 {
192 }
193
194
195 int TrajectoryAnalysisModule::datasetCount() const
196 {
197     return _impl->_datasetNames.size();
198 }
199
200
201 const std::vector<std::string> &TrajectoryAnalysisModule::datasetNames() const
202 {
203     return _impl->_datasetNames;
204 }
205
206
207 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromIndex(int index) const
208 {
209     if (index < 0 || index >= datasetCount())
210     {
211         GMX_THROW(APIError("Out of range data set index"));
212     }
213     Impl::DatasetContainer::const_iterator item
214         = _impl->_datasets.find(_impl->_datasetNames[index]);
215     GMX_RELEASE_ASSERT(item != _impl->_datasets.end(),
216                        "Inconsistent data set names");
217     return *item->second;
218 }
219
220
221 AbstractAnalysisData &TrajectoryAnalysisModule::datasetFromName(const char *name) const
222 {
223     Impl::DatasetContainer::const_iterator item = _impl->_datasets.find(name);
224     if (item == _impl->_datasets.end())
225     {
226         GMX_THROW(APIError("Unknown data set name"));
227     }
228     return *item->second;
229 }
230
231
232 void TrajectoryAnalysisModule::registerBasicDataset(AbstractAnalysisData *data,
233                                                     const char *name)
234 {
235     // TODO: Strong exception safety should be possible to implement.
236     GMX_RELEASE_ASSERT(_impl->_datasets.find(name) == _impl->_datasets.end(),
237                        "Duplicate data set name registered");
238     _impl->_datasets[name] = data;
239     _impl->_datasetNames.push_back(name);
240 }
241
242
243 void TrajectoryAnalysisModule::registerAnalysisDataset(AnalysisData *data,
244                                                        const char *name)
245 {
246     // TODO: Strong exception safety should be possible to implement.
247     registerBasicDataset(data, name);
248     _impl->_analysisDatasets[name] = data;
249 }
250
251 } // namespace gmx