Merge branch release-5-1
[alexxy/gromacs.git] / src / gromacs / analysisdata / datamodule.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source 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 /*! \file
36  * \brief
37  * Declares gmx::IAnalysisDataModule and related convenience classes.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inlibraryapi
41  * \ingroup module_analysisdata
42  */
43 #ifndef GMX_ANALYSISDATA_DATAMODULE_H
44 #define GMX_ANALYSISDATA_DATAMODULE_H
45
46 namespace gmx
47 {
48
49 class AbstractAnalysisData;
50 class AnalysisDataFrameHeader;
51 class AnalysisDataParallelOptions;
52 class AnalysisDataPointSetRef;
53
54 /*! \brief
55  * Interface for a module that gets notified whenever data is added.
56  *
57  * The interface provides one method (flags()) that describes features of
58  * data objects the module supports.  Only most common features are included
59  * in the flags; custom checks can be implemented in the dataStarted() and/or
60  * parallelDataStarted() methods (see below).
61  * All other methods in the interface are callbacks that are called by the
62  * data object to which the module is attached to describe the data.
63  * See \ref module_analysisdata for an overview of the notifications the
64  * modules receive, and \ref page_analysisdata for overview of the terminology.
65  *
66  * Concrete modules typically do not directly derive from this interface, but
67  * from either AnalysisDataModuleSerial or AnalysisDataModuleParallel.
68  * Both these classes implement one of dataStarted()/parallelDataStarted() by
69  * forwarding the calls to the other method of this pair.  This allows the
70  * module to only implement the initialization once, without needing to worry
71  * how to correctly handle both cases.
72  *
73  * Currently, if the module throws an exception, it requires the analysis tool
74  * to terminate, since AbstractAnalysisData will be left in a state where it
75  * is not possible to continue processing.  See a related todo item in
76  * AbstractAnalysisData.
77  *
78  * \inlibraryapi
79  * \ingroup module_analysisdata
80  */
81 class IAnalysisDataModule
82 {
83     public:
84         /*! \brief
85          * Possible flags for flags().
86          */
87         enum Flag
88         {
89             //! The module can process multipoint data.
90             efAllowMultipoint           = 1<<0,
91             //! The module does not make sense for non-multipoint data.
92             efOnlyMultipoint            = 1<<1,
93             //! The module can process data with more than one column.
94             efAllowMulticolumn          = 1<<2,
95             //! The module can process data with missing points.
96             efAllowMissing              = 1<<3,
97             //! The module can process data with multiple data sets.
98             efAllowMultipleDataSets     = 1<<4
99         };
100
101         virtual ~IAnalysisDataModule() {};
102
103         /*! \brief
104          * Returns properties supported by the module.
105          *
106          * The return value of this method should not change after the module
107          * has been added to a data (this responsibility can, and in most cases
108          * must, be delegated to the user of the module).
109          *
110          * The purpose of this method is to remove the need for common checks
111          * for data compatibility in the classes that implement the interface.
112          * Instead, AbstractAnalysisData performs these checks based on the
113          * flags provided.
114          *
115          * Does not throw.
116          */
117         virtual int flags() const = 0;
118
119         /*! \brief
120          * Called (once) when the data has been set up properly.
121          *
122          * \param[in] data  Data object to which the module is added.
123          * \throws    APIError if the provided data is not compatible.
124          * \throws    unspecified  Can throw any exception required by the
125          *      implementing class to report errors.
126          *
127          * When the data is ready, either this method or parallelDataStarted()
128          * is called, depending on the nature of the input data.  If this
129          * method is called, the input data will always present the frames in
130          * sequential order.
131          *
132          * The data to which the module is attached is passed as an argument
133          * to provide access to properties of the data for initialization
134          * and/or validation.  The module can also call
135          * AbstractAnalysisData::requestStorage() if needed.
136          *
137          * This is the only place where the module gets access to the data;
138          * if properties of the data are required later, the module should
139          * store them internally.  It is guaranteed that the data properties
140          * (column count, whether it's multipoint) do not change once this
141          * method has been called.
142          *
143          * Notice that \p data will be a proxy object if the module is added as
144          * a column module, not the data object for which
145          * AbstractAnalysisData::addColumnModule() was called.
146          */
147         virtual void dataStarted(AbstractAnalysisData *data) = 0;
148         /*! \brief
149          * Called (once) for parallel data when the data has been set up.
150          *
151          * \param[in] data     Data object to which the module is added.
152          * \param[in] options  Parallelization properties of the input data.
153          * \returns   true if the module can process the input in
154          *      non-sequential order.
155          * \throws    APIError if the provided data is not compatible.
156          * \throws    unspecified  Can throw any exception required by the
157          *      implementing class to report errors.
158          *
159          * This method is called instead of dataStarted() if the input data has
160          * the capability to present data in non-sequential order.
161          * If the method returns true, then the module accepts this and frame
162          * notification methods may be called in that non-sequential order.
163          * If the method returns false, then the frame notification methods are
164          * called in sequential order, as if dataStarted() had been called.
165          *
166          * See dataStarted() for general information on initializing the data.
167          * That applies to this method as well, with the exception that calling
168          * AbstractAnalysisData::requestStorage() is currently not very well
169          * supported (or rather, accessing the requested storage doesn't work).
170          */
171         virtual bool parallelDataStarted(
172             AbstractAnalysisData              *data,
173             const AnalysisDataParallelOptions &options) = 0;
174         /*! \brief
175          * Called at the start of each data frame.
176          *
177          * \param[in] frame  Header information for the frame that is starting.
178          * \throws    unspecified  Can throw any exception required by the
179          *      implementing class to report errors.
180          */
181         virtual void frameStarted(const AnalysisDataFrameHeader &frame) = 0;
182         /*! \brief
183          * Called one or more times during each data frame.
184          *
185          * \param[in] points  Set of points added (also provides access to
186          *      frame-level data).
187          * \throws    APIError if the provided data is not compatible.
188          * \throws    unspecified  Can throw any exception required by the
189          *      implementing class to report errors.
190          *
191          * Can be called once or multiple times for a frame.  For all data
192          * objects currently implemented in the library (and all objects that
193          * will use AnalysisDataStorage for internal implementation), it is
194          * called exactly once for each frame if the data is not multipoint,
195          * but currently this restriction is not enforced.
196          */
197         virtual void pointsAdded(const AnalysisDataPointSetRef &points) = 0;
198         /*! \brief
199          * Called when a data frame is finished.
200          *
201          * \param[in] header  Header information for the frame that is ending.
202          * \throws    unspecified  Can throw any exception required by the
203          *      implementing class to report errors.
204          */
205         virtual void frameFinished(const AnalysisDataFrameHeader &header) = 0;
206         /*! \brief
207          * Called in sequential order for each frame after they are finished.
208          *
209          * \param[in] frameIndex   Index of the next finished frame.
210          * \throws    unspecified  Can throw any exception required by the
211          *      implementing class to report errors.
212          *
213          * This method is called after frameFinished(), but with an additional
214          * constraint that it is always called in serial and with an increasing
215          * \p frameIndex.  Parallel data modules need this to serialize their
216          * data for downsteam serial modules; AnalysisDataModuleSerial provides
217          * an empty implementation, as there frameFinished() can be used for
218          * the same purpose.
219          */
220         virtual void frameFinishedSerial(int frameIndex) = 0;
221         /*! \brief
222          * Called (once) when no more data is available.
223          *
224          * \throws    unspecified  Can throw any exception required by the
225          *      implementing class to report errors.
226          */
227         virtual void dataFinished() = 0;
228 };
229
230 /*! \brief
231  * Convenience base class for serial analysis data modules.
232  *
233  * Implements the parallelDataStarted() method such that initialization is
234  * always forwarded to dataStarted(), and the module always behaves as serial
235  * (parallelDataStarted() returns false).
236  *
237  * \inlibraryapi
238  * \ingroup module_analysisdata
239  */
240 class AnalysisDataModuleSerial : public IAnalysisDataModule
241 {
242     public:
243         virtual ~AnalysisDataModuleSerial() {}
244
245         virtual int flags() const = 0;
246
247         virtual void dataStarted(AbstractAnalysisData *data)              = 0;
248         virtual void frameStarted(const AnalysisDataFrameHeader &frame)   = 0;
249         virtual void pointsAdded(const AnalysisDataPointSetRef &points)   = 0;
250         virtual void frameFinished(const AnalysisDataFrameHeader &header) = 0;
251         virtual void dataFinished() = 0;
252
253     private:
254         virtual bool parallelDataStarted(
255             AbstractAnalysisData              *data,
256             const AnalysisDataParallelOptions &options);
257         virtual void frameFinishedSerial(int /*frameIndex*/) {}
258 };
259
260 /*! \brief
261  * Convenience base class for parallel analysis data modules.
262  *
263  * Implements the dataStarted() method such that initialization is always done
264  * in parallelDataStarted().  dataStarted() calls are forwarded to
265  * parallelDataStarted() using a dummy serial AnalysisDataParallelOptions.
266  *
267  * \inlibraryapi
268  * \ingroup module_analysisdata
269  */
270 class AnalysisDataModuleParallel : public IAnalysisDataModule
271 {
272     public:
273         virtual ~AnalysisDataModuleParallel() {}
274
275         virtual int flags() const = 0;
276
277         virtual bool parallelDataStarted(
278             AbstractAnalysisData              *data,
279             const AnalysisDataParallelOptions &options)                   = 0;
280         virtual void frameStarted(const AnalysisDataFrameHeader &frame)   = 0;
281         virtual void pointsAdded(const AnalysisDataPointSetRef &points)   = 0;
282         virtual void frameFinished(const AnalysisDataFrameHeader &header) = 0;
283         virtual void frameFinishedSerial(int index) = 0;
284         virtual void dataFinished()                 = 0;
285
286     private:
287         virtual void dataStarted(AbstractAnalysisData *data);
288 };
289
290 } // namespace gmx
291
292 #endif