3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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.
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.
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.
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.
29 * For more info, check our website at http://www.gromacs.org
33 * Declares gmx::AnalysisData and gmx::AnalysisDataHandle.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
37 * \ingroup module_analysisdata
39 #ifndef GMX_ANALYSISDATA_ANALYSISDATA_H
40 #define GMX_ANALYSISDATA_ANALYSISDATA_H
42 #include "abstractdata.h"
47 class AnalysisDataHandle;
48 class AnalysisDataParallelOptions;
51 * Parallelizable data container for raw data.
53 * This is the main class used to implement parallelizable data processing in
54 * analysis tools. It is used by first creating an object and setting its
55 * properties using setColumnCount() and setMultipoint(), and attaching
56 * necessary modules using addModule() etc. Then one or more
57 * AnalysisDataHandle objects can be created using startData(). Each data
58 * handle can then be independently used to provide data frames (each frame
59 * must be provided by a single handle, but different frames can be freely
60 * mixed between the handles). When all data has been provided, the handles
61 * are destroyed using finishData() (or AnalysisDataHandle::finishData()).
62 * The AnalysisData object takes care of internally sorting the frames and
63 * passing them to the attached modules in the order in which the modules
67 * Currently, multiple handles with multipoint data are not implemented.
70 * Parallel implementation is not complete.
73 * Special note for MPI implementation: assuming that the initialization of
74 * data objects is identical in all processes, associating the data objects
75 * in different MPI processes should be possible without changes in the
77 * Alternative, more robust implementation could get a unique ID as parameter
78 * to the constructor or a separate function, but would require all tools to
79 * provide it. With the current registration mechanism in
80 * TrajectoryAnalysisModule, this should be straightforward.
84 * \ingroup module_analysisdata
86 class AnalysisData : public AbstractAnalysisData
90 * Creates an empty analysis data object.
92 * \throws std::bad_alloc if out of memory.
95 virtual ~AnalysisData();
98 * Sets the number of columns in the data.
100 * \param[in] ncol Number of columns in the data (must be > 0).
102 * Must be called before startData(), and can be called multiple times
103 * before modules are added.
104 * Must not be called after startData() has been called.
106 * Does not currently throw, but this may change for the case that
107 * modules have already been added.
109 void setColumnCount(int ncol);
111 * Sets whether the data contains multiple points per column per frame.
113 * \param[in] bMultipoint Whether the data will allow multiple points
114 * per column within a single frame.
116 * If this method is not called, the data is not multipoint.
118 * Must not be called after modules have been added or startData() has
121 * Does not currently throw, but this may change for the case that
122 * modules have already been added.
124 * \see isMultipoint()
126 void setMultipoint(bool bMultipoint);
129 * Create a handle for adding data.
131 * \param[in] opt Options for setting how this handle will be
133 * \returns The created handle.
134 * \throws std::bad_alloc if out of memory.
135 * \throws APIError if any attached data module is not compatible.
136 * \throws unspecified Any exception thrown by attached data modules
137 * in AnalysisDataModuleInterface::dataStarted().
139 * The caller should retain the returned handle (or a copy of it), and
140 * pass it to finishData() after successfully adding all data.
141 * The caller should discard the returned handle if an error occurs;
142 * memory allocated for the handle will be freed when the AnalysisData
143 * object is destroyed.
145 * The \p opt options should be the same for all calls to this method,
146 * and the number of calls should match the parallelization factor
149 AnalysisDataHandle startData(const AnalysisDataParallelOptions &opt);
151 * Destroy a handle after all data has been added.
153 * \param[in] handle Handle to destroy.
154 * \throws unspecified Any exception thrown by attached data modules
155 * in AnalysisDataModuleInterface::dataFinished().
157 * \p handle must have been obtained from startData() of this object.
158 * The order of the calls with respect to the corresponding startData()
159 * calls is not important.
161 * The \p handle (and any copies) are invalid after the call.
163 void finishData(AnalysisDataHandle handle);
166 virtual AnalysisDataFrameRef tryGetDataFrameInternal(int index) const;
167 virtual bool requestStorageInternal(int nframes);
171 PrivateImplPointer<Impl> impl_;
173 friend class AnalysisDataHandle;
178 class AnalysisDataHandleImpl;
179 } // namespace internal
182 * Handle for inserting data into AnalysisData.
184 * This class provides an interface for adding data frames into an AnalysisData
185 * object. After a handle is obtained from AnalysisData::startData(), new
186 * frames can be added using startFrame(). Then values for that frame are set
187 * using provided methods (see below), and finishFrame() is called. After all
188 * frames have been added, finishData() (or AnalysisData::finishData()) must be
191 * For simple (non-multipoint) data, within a frame values can be set using
192 * setPoint() and setPoints(). Setting the same column multiple times
193 * overrides previously set values. When the frame is finished, attached
194 * modules are notified.
196 * Multipoint data works otherwise similarly, but requires finishPointSet() to
197 * be called for each set of points for which the modules need to be notified.
198 * Each point set starts empty (after startFrame() or finishPointSet()), and
199 * values can be set using setPoint()/setPoints(). finishPointSet() must also
200 * be called for the last point set just before finishFrame().
202 * This class works like a pointer type: copying and assignment is lightweight,
203 * and all copies work interchangeably, accessing the same internal handle.
204 * However, normally you should only keep one copy of a handle, i.e., treat
205 * this type as movable.
206 * Several handles created from the same AnalysisData object can exist
207 * concurrently, but must currently operate on separate frames.
210 * \ingroup module_analysisdata
212 class AnalysisDataHandle
216 * Constructs an invalid data handle.
218 * This constructor is provided for convenience in cases where it is
219 * easiest to declare an AnalysisDataHandle without immediately
220 * assigning a value to it. Any attempt to call methods without first
221 * assigning a value from AnalysisData::startData() to the handle
226 AnalysisDataHandle();
229 * Start data for a new frame.
231 * \param[in] index Zero-based index for the frame to start.
232 * \param[in] x x value for the frame.
233 * \param[in] dx Error in x for the frame if applicable.
235 * \throws unspecified Any exception thrown by attached data
236 * modules in AnalysisDataModuleInterface::frameStarted().
238 * Each \p index value 0, 1, ..., N (where N is the total number of
239 * frames) should be started exactly once by exactly one handle of an
240 * AnalysisData object. The frames may be started out of order, but
241 * currently the implementation places some limitations on how far
242 * the index can be in the future (as counted from the first frame that
245 void startFrame(int index, real x, real dx = 0.0);
247 * Set a value for a single column for the current frame.
249 * \param[in] column Zero-based column index.
250 * \param[in] value Value to set for the column.
251 * \param[in] bPresent Present flag to set for the column.
253 * If called multiple times for a column (within one point set for
254 * multipoint data), old values are overwritten.
258 void setPoint(int column, real value, bool bPresent = true);
260 * Set a value and its error estimate for a single column for the
263 * \param[in] column Zero-based column index.
264 * \param[in] value Value to set for the column.
265 * \param[in] error Error estimate to set for the column.
266 * \param[in] bPresent Present flag to set for the column.
268 * If called multiple times for a column (within one point set for
269 * multipoint data), old values are overwritten.
273 void setPoint(int column, real value, real error, bool bPresent = true);
275 * Set values for consecutive columns for the current frame.
277 * \param[in] firstColumn Zero-based column index.
278 * \param[in] count Number of columns to set.
279 * \param[in] values Value array of \p column items.
281 * Equivalent to calling setPoint(firstColumn + i, values[i]) for
286 void setPoints(int firstColumn, int count, const real *values);
288 * Finish data for the current point set.
290 * \throws APIError if any attached data module is not compatible.
291 * \throws unspecified Any exception thrown by attached data
292 * modules in AnalysisDataModuleInterface::pointsAdded().
294 * Must be called after each point set for multipoint data, including
295 * the last (i.e., no values must be set between the last call to this
296 * method and AnalysisDataStorage::finishFrame()).
297 * Must not be called for non-multipoint data.
299 void finishPointSet();
301 * Finish data for the current frame.
303 * \throws APIError if any attached data module is not compatible.
304 * \throws unspecified Any exception thrown by attached data
305 * modules in frame notification methods.
308 //! Calls AnalysisData::finishData() for this handle.
313 * Creates a new data handle associated with \p data.
315 * \param data Data to associate the handle with.
317 * The constructor is private because data handles should only be
318 * constructed through AnalysisData::startData().
322 explicit AnalysisDataHandle(internal::AnalysisDataHandleImpl *impl);
325 * Pointer to the internal implementation class.
327 * The memory for this object is managed by the AnalysisData object,
328 * and AnalysisDataHandle simply provides a public interface for
329 * accessing the implementation.
331 internal::AnalysisDataHandleImpl *impl_;
334 * Needed to access the non-public implementation.
336 friend class AnalysisData;