Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / analysisdata / abstractdata.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements gmx::AbstractAnalysisData.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_analysisdata
41  */
42 #include "gromacs/analysisdata/abstractdata.h"
43
44 #include <vector>
45
46 #include "gromacs/analysisdata/dataframe.h"
47 #include "gromacs/analysisdata/datamodule.h"
48 #include "gromacs/analysisdata/datamodulemanager.h"
49 #include "gromacs/utility/exceptions.h"
50 #include "gromacs/utility/gmxassert.h"
51 #include "gromacs/utility/uniqueptr.h"
52
53 #include "dataproxy.h"
54
55 namespace gmx
56 {
57
58 /********************************************************************
59  * AbstractAnalysisData::Impl
60  */
61
62 /*! \internal \brief
63  * Private implementation class for AbstractAnalysisData.
64  *
65  * \ingroup module_analysisdata
66  */
67 class AbstractAnalysisData::Impl
68 {
69     public:
70         Impl();
71
72         //! Column counts for each data set in the data.
73         std::vector<int>           columnCounts_;
74         //! Whether the data is multipoint.
75         bool                       bMultipoint_;
76         //! Manager for the added modules.
77         AnalysisDataModuleManager  modules_;
78 };
79
80 AbstractAnalysisData::Impl::Impl()
81     : bMultipoint_(false)
82 {
83     columnCounts_.push_back(0);
84 }
85
86
87 /********************************************************************
88  * AbstractAnalysisData
89  */
90 /*! \cond libapi */
91 AbstractAnalysisData::AbstractAnalysisData()
92     : impl_(new Impl())
93 {
94 }
95 //! \endcond
96
97 AbstractAnalysisData::~AbstractAnalysisData()
98 {
99 }
100
101 bool
102 AbstractAnalysisData::isMultipoint() const
103 {
104     return impl_->bMultipoint_;
105 }
106
107 int
108 AbstractAnalysisData::dataSetCount() const
109 {
110     return impl_->columnCounts_.size();
111 }
112
113 int
114 AbstractAnalysisData::columnCount(int dataSet) const
115 {
116     GMX_ASSERT(dataSet >= 0 && dataSet < dataSetCount(),
117                "Out of range data set index");
118     return impl_->columnCounts_[dataSet];
119 }
120
121 int
122 AbstractAnalysisData::columnCount() const
123 {
124     GMX_ASSERT(dataSetCount() == 1,
125                "Convenience method not available for multiple data sets");
126     return columnCount(0);
127 }
128
129
130 AnalysisDataFrameRef
131 AbstractAnalysisData::tryGetDataFrame(int index) const
132 {
133     if (index < 0 || index >= frameCount())
134     {
135         return AnalysisDataFrameRef();
136     }
137     return tryGetDataFrameInternal(index);
138 }
139
140
141 AnalysisDataFrameRef
142 AbstractAnalysisData::getDataFrame(int index) const
143 {
144     AnalysisDataFrameRef frame = tryGetDataFrame(index);
145     if (!frame.isValid())
146     {
147         GMX_THROW(APIError("Invalid frame accessed"));
148     }
149     return frame;
150 }
151
152
153 bool
154 AbstractAnalysisData::requestStorage(int nframes)
155 {
156     GMX_RELEASE_ASSERT(nframes >= -1, "Invalid number of frames requested");
157     if (nframes == 0)
158     {
159         return true;
160     }
161     return requestStorageInternal(nframes);
162 }
163
164
165 void
166 AbstractAnalysisData::addModule(AnalysisDataModulePointer module)
167 {
168     impl_->modules_.addModule(this, module);
169 }
170
171
172 void
173 AbstractAnalysisData::addColumnModule(int col, int span,
174                                       AnalysisDataModulePointer module)
175 {
176     GMX_RELEASE_ASSERT(col >= 0 && span >= 1,
177                        "Invalid columns specified for a column module");
178     boost::shared_ptr<AnalysisDataProxy> proxy(
179             new AnalysisDataProxy(col, span, this));
180     proxy->addModule(module);
181     addModule(proxy);
182 }
183
184
185 void
186 AbstractAnalysisData::applyModule(AnalysisDataModuleInterface *module)
187 {
188     impl_->modules_.applyModule(this, module);
189 }
190
191 /*! \cond libapi */
192 void
193 AbstractAnalysisData::setDataSetCount(int dataSetCount)
194 {
195     GMX_RELEASE_ASSERT(dataSetCount > 0, "Invalid data column count");
196     impl_->modules_.dataPropertyAboutToChange(
197             AnalysisDataModuleManager::eMultipleDataSets, dataSetCount > 1);
198     impl_->columnCounts_.resize(dataSetCount);
199 }
200
201 void
202 AbstractAnalysisData::setColumnCount(int dataSet, int columnCount)
203 {
204     GMX_RELEASE_ASSERT(dataSet >= 0 && dataSet < dataSetCount(),
205                        "Out of range data set index");
206     GMX_RELEASE_ASSERT(columnCount > 0, "Invalid data column count");
207
208     bool bMultipleColumns = columnCount > 1;
209     for (int i = 0; i < dataSetCount() && !bMultipleColumns; ++i)
210     {
211         if (i != dataSet && this->columnCount(i) > 1)
212         {
213             bMultipleColumns = true;
214         }
215     }
216     impl_->modules_.dataPropertyAboutToChange(
217             AnalysisDataModuleManager::eMultipleColumns, bMultipleColumns);
218     impl_->columnCounts_[dataSet] = columnCount;
219 }
220
221 void
222 AbstractAnalysisData::setMultipoint(bool bMultipoint)
223 {
224     impl_->modules_.dataPropertyAboutToChange(
225             AnalysisDataModuleManager::eMultipoint, bMultipoint);
226     impl_->bMultipoint_ = bMultipoint;
227 }
228
229 AnalysisDataModuleManager &AbstractAnalysisData::moduleManager()
230 {
231     return impl_->modules_;
232 }
233
234 const AnalysisDataModuleManager &AbstractAnalysisData::moduleManager() const
235 {
236     return impl_->modules_;
237 }
238 //! \endcond
239
240 } // namespace gmx