Merge remote-tracking branch 'gerrit/release-4-6'
[alexxy/gromacs.git] / src / gromacs / analysisdata / dataframe.h
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 /*! \file
32  * \brief
33  * Declares classes for accessing data frame information.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_analysisdata
38  */
39 #ifndef GMX_ANALYSISDATA_DATAFRAME_H
40 #define GMX_ANALYSISDATA_DATAFRAME_H
41
42 #include <vector>
43
44 #include "../legacyheaders/types/simple.h"
45
46 #include "../fatalerror/gmxassert.h"
47 #include "../utility/arrayref.h"
48 #include "../utility/flags.h"
49
50 namespace gmx
51 {
52
53 /*! \brief
54  * Value type for representing a single value in analysis data objects.
55  *
56  * Default copy constructor and assignment operator are used and work as
57  * intended.
58  *
59  * Methods in this class do not throw.
60  *
61  * \inpublicapi
62  * \ingroup module_analysisdata
63  */
64 class AnalysisDataValue
65 {
66     public:
67         /*! \brief
68          * Constructs an unset value.
69          */
70         AnalysisDataValue() : value_(0.0), error_(0.0) {}
71         /*! \brief
72          * Constructs a value object with the given value.
73          *
74          * The constructed object is marked as set and present.
75          */
76         explicit AnalysisDataValue(real value)
77             : value_(value), error_(0.0)
78         {
79             flags_.set(efSet);
80             flags_.set(efPresent);
81         }
82
83         /*! \brief
84          * Direct access to the value.
85          *
86          * Assigning a value to this does not mark the value as set; setValue()
87          * must be used for this.
88          */
89         real &value() { return value_; }
90         /*! \brief
91          * Direct access to the error estimate.
92          *
93          * Assigning a value to this does not mark the error estimate as set;
94          * setValue() must be used for this.
95          */
96         real &error() { return error_; }
97         //! Returns the value for this value.
98         real value() const { return value_; }
99         //! Returns the error estimate for this value, or zero if not set.
100         real error() const { return error_; }
101         /*! \brief
102          * Returns whether this value has been set.
103          *
104          * If this method returns false, the return value of value() and
105          * error() are undefined.
106          */
107         bool isSet() const { return flags_.test(efSet); }
108         /*! \brief
109          * Returns whether the error estimate for this value has been set.
110          *
111          * If this method returns false, but isSet() returns true, error()
112          * returns zero.
113          */
114         bool hasError() const { return flags_.test(efErrorSet); }
115         /*! \brief
116          * Returns whether this value has been marked as present.
117          *
118          * If this method returns false, it is up to the source data to define
119          * whether isSet() may return true.
120          */
121         bool isPresent() const { return flags_.test(efPresent); }
122
123         //! Clears and unsets this value.
124         void clear()
125         {
126             *this = AnalysisDataValue();
127         }
128         //! Sets this value.
129         void setValue(real value, bool bPresent = true)
130         {
131             value_ = value;
132             flags_.set(efSet);
133             flags_.set(efPresent, bPresent);
134         }
135         //! Sets this value and its error estimate.
136         void setValue(real value, real error, bool bPresent = true)
137         {
138             value_ = value;
139             error_ = error;
140             flags_.set(efSet);
141             flags_.set(efErrorSet);
142             flags_.set(efPresent, bPresent);
143         }
144         //! Set only error estimate for this value.
145         void setError(real error)
146         {
147             error_ = error;
148             flags_.set(efErrorSet);
149         }
150
151     private:
152         //! Possible flags for \a flags_.
153         enum Flag
154         {
155             efSet       = 1<<0, //!< Value has been set.
156             efErrorSet  = 1<<1, //!< Error estimate has been set.
157             efPresent   = 1<<2  //!< Value is set as present.
158         };
159
160         //! Value for this value.
161         real                    value_;
162         //! Error estimate for this value, zero if not set.
163         real                    error_;
164         //! Status flags for thise value.
165         FlagsTemplate<Flag>     flags_;
166 };
167
168 //! Shorthand for reference to an array of data values.
169 typedef ConstArrayRef<AnalysisDataValue> AnalysisDataValuesRef;
170
171
172 /*! \brief
173  * Value type for storing frame-level information for analysis data.
174  *
175  * Default copy constructor and assignment operator are used and work as
176  * intended.
177  * Typically new objects of this type are only constructed internally by the
178  * library and in classes that are derived from AbstractAnalysisData.
179  *
180  * Methods in this class do not throw, but may contain asserts for incorrect
181  * usage.
182  *
183  * \inpublicapi
184  * \ingroup module_analysisdata
185  */
186 class AnalysisDataFrameHeader
187 {
188     public:
189         /*! \brief
190          * Constructs an invalid frame header.
191          *
192          * Return values of other methods than isValid() are unspecified for
193          * the constructed object.
194          */
195         AnalysisDataFrameHeader();
196         /*! \brief
197          * Constructs a frame header from given values.
198          *
199          * \param[in] index  Index of the frame. Must be >= 0.
200          * \param[in] x      x coordinate for the frame.
201          * \param[in] dx     Error estimate for x.
202          */
203         AnalysisDataFrameHeader(int index, real x, real dx);
204
205         /*! \brief
206          * Returns whether the frame header corresponds to a valid frame.
207          *
208          * If returns false, return values of other methods are not specified.
209          */
210         bool isValid() const
211         {
212             return index_ >= 0;
213         }
214         /*! \brief
215          * Returns zero-based index of the frame.
216          *
217          * The return value is >= 0 for valid frames.
218          * Should not be called for invalid frames.
219          */
220         int index() const
221         {
222             GMX_ASSERT(isValid(), "Tried to access invalid frame header");
223             return index_;
224         }
225         /*! \brief
226          * Returns the x coordinate for the frame.
227          *
228          * Should not be called for invalid frames.
229          */
230         real x() const
231         {
232             GMX_ASSERT(isValid(), "Tried to access invalid frame header");
233             return x_;
234         }
235         /*! \brief
236          * Returns error in the x coordinate for the frame (if applicable).
237          *
238          * All data do not provide error estimates.
239          * Typically returns zero in those cases.
240          *
241          * Should not be called for invalid frames.
242          */
243         real dx() const
244         {
245             GMX_ASSERT(isValid(), "Tried to access invalid frame header");
246             return dx_;
247         }
248
249     private:
250         int                     index_;
251         real                    x_;
252         real                    dx_;
253 };
254
255
256 /*! \brief
257  * Value type wrapper for non-mutable access to a set of data column values.
258  *
259  * Default copy constructor and assignment operator are used and work as
260  * intended.
261  * Typically new objects of this type are only constructed internally by the
262  * library and in classes that are derived from AbstractAnalysisData.
263  *
264  * Methods in this class do not throw, but may contain asserts for incorrect
265  * usage.
266  *
267  * The design of the interfaces is such that all objects of this type should be
268  * valid, i.e., header().isValid() should always return true.
269  *
270  * \inpublicapi
271  * \ingroup module_analysisdata
272  */
273 class AnalysisDataPointSetRef
274 {
275     public:
276         /*! \brief
277          * Constructs a point set reference from given values.
278          *
279          * \param[in] header      Header for the frame.
280          * \param[in] firstColumn Zero-based index of the first column.
281          *     Must be >= 0.
282          * \param[in] values      Values for each column.
283          *
284          * The first element in \p values should correspond to \p firstColumn.
285          */
286         AnalysisDataPointSetRef(const AnalysisDataFrameHeader &header,
287                                 int firstColumn,
288                                 const AnalysisDataValuesRef &values);
289         /*! \brief
290          * Constructs a point set reference from given values.
291          *
292          * \param[in] header      Header for the frame.
293          * \param[in] values      Values for each column.
294          *
295          * The first element in \p values should correspond to the first
296          * column.
297          */
298         AnalysisDataPointSetRef(const AnalysisDataFrameHeader &header,
299                                 const std::vector<AnalysisDataValue> &values);
300         /*! \brief
301          * Constructs a point set reference to a subset of columns.
302          *
303          * \param[in] points      Point set to use as source.
304          * \param[in] firstColumn First column index to include.
305          * \param[in] columnCount Number of columns to include.
306          *
307          * Creates a point set that contains \p columnCount columns starting
308          * from \p firstColumn from \p points, or a subset if all requested
309          * columns are not present in \p points.  If the requested column range
310          * and the range in \p points do not intersect, the result has
311          * columnCount() == 0.
312          *
313          * \p firstColumn is relative to the whole data set, i.e., not relative
314          * to points.firstColumn().
315          *
316          * Mainly intended for internal use.
317          */
318         AnalysisDataPointSetRef(const AnalysisDataPointSetRef &points,
319                                 int firstColumn, int columnCount);
320
321         /*! \brief
322          * Returns the frame header for the frame of this point set.
323          */
324         const AnalysisDataFrameHeader &header() const
325         {
326             return header_;
327         }
328         //! \copydoc AnalysisDataFrameHeader::index()
329         int frameIndex() const
330         {
331             return header_.index();
332         }
333         //! \copydoc AnalysisDataFrameHeader::x()
334         real x() const
335         {
336             return header_.x();
337         }
338         //! \copydoc AnalysisDataFrameHeader::dx()
339         real dx() const
340         {
341             return header_.dx();
342         }
343         //! Returns zero-based index of the first column included in this set.
344         int firstColumn() const
345         {
346             return firstColumn_;
347         }
348         //! Returns the number of columns included in this set.
349         int columnCount() const
350         {
351             return values().size();
352         }
353         //! Returns zero-based index of the last column included in this set (inclusive).
354         int lastColumn() const
355         {
356             return firstColumn_ + columnCount() - 1;
357         }
358         /*! \brief
359          * Returns reference container for all values.
360          *
361          * First value in the returned container corresponds to firstColumn().
362          */
363         const AnalysisDataValuesRef &values() const
364         {
365             return values_;
366         }
367         /*! \brief
368          * Returns data value for a column in this set.
369          *
370          * \param[in] i  Zero-based column index relative to firstColumn().
371          *     Should be >= 0 and < columnCount().
372          */
373         real y(int i) const
374         {
375             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
376             return values()[i].value();
377         }
378         /*! \brief
379          * Returns error estimate for a column in this set if applicable.
380          *
381          * \param[in] i  Zero-based column index relative to firstColumn().
382          *     Should be >= 0 and < columnCount().
383          *
384          * Currently, this method returns zero if the source data does not
385          * specify errors.
386          */
387         real dy(int i) const
388         {
389             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
390             return values()[i].error();
391         }
392         /*! \brief
393          * Returns whether a column is present in this set.
394          *
395          * \param[in] i  Zero-based column index relative to firstColumn().
396          *     Should be >= 0 and < columnCount().
397          *
398          * If present(i) returns false, it is depends on the source data
399          * whether y(i) and/or dy(i) are defined.
400          */
401         bool present(int i) const
402         {
403             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
404             return values()[i].isPresent();
405         }
406         /*! \brief
407          * Returns true if all points in this point set are present.
408          *
409          * That is, if present() would return true for all points.
410          */
411         bool allPresent() const;
412
413     private:
414         AnalysisDataFrameHeader header_;
415         int                     firstColumn_;
416         AnalysisDataValuesRef   values_;
417 };
418
419
420 /*! \brief
421  * Value type wrapper for non-mutable access to a data frame.
422  *
423  * Default copy constructor and assignment operator are used and work as
424  * intended.
425  * Typically new objects of this type are only constructed internally by the
426  * library and in classes that are derived from AbstractAnalysisData.
427  *
428  * Methods in this class do not throw, but may contain asserts for incorrect
429  * usage.
430  *
431  * \todo
432  * Support for multipoint data.
433  *
434  * \inpublicapi
435  * \ingroup module_analysisdata
436  */
437 class AnalysisDataFrameRef
438 {
439     public:
440         /*! \brief
441          * Constructs an invalid frame reference.
442          *
443          * Return values of other methods than isValid() are unspecified for
444          * the constructed object.
445          */
446         AnalysisDataFrameRef();
447         /*! \brief
448          * Constructs a frame reference from given values.
449          *
450          * \param[in] header      Header for the frame.
451          * \param[in] values      Values for each column.
452          */
453         AnalysisDataFrameRef(const AnalysisDataFrameHeader &header,
454                              const AnalysisDataValuesRef &values);
455         /*! \brief
456          * Constructs a frame reference from given values.
457          *
458          * \param[in] header      Header for the frame.
459          * \param[in] values      Values for each column.
460          */
461         AnalysisDataFrameRef(const AnalysisDataFrameHeader &header,
462                              const std::vector<AnalysisDataValue> &values);
463         /*! \brief
464          * Constructs a frame reference to a subset of columns.
465          *
466          * \param[in] frame       Frame to use as source.
467          * \param[in] firstColumn First column index to include.
468          * \param[in] columnCount Number of columns to include.
469          *
470          * Creates a frame reference that contains \p columnCount columns
471          * starting from \p firstColumn from \p frame, or a subset if all
472          * requested columns are not present in \p frame.
473          *
474          * Mainly intended for internal use.
475          */
476         AnalysisDataFrameRef(const AnalysisDataFrameRef &frame,
477                              int firstColumn, int columnCount);
478
479         /*! \brief
480          * Returns whether the object refers to a valid frame.
481          *
482          * If returns false, return values of other methods are not specified.
483          */
484         bool isValid() const
485         {
486             return header().isValid();
487         }
488         //! Returns the header for this frame.
489         const AnalysisDataFrameHeader &header() const
490         {
491             return header_;
492         }
493         //! \copydoc AnalysisDataFrameHeader::index()
494         int frameIndex() const
495         {
496             return header().index();
497         }
498         //! \copydoc AnalysisDataFrameHeader::x()
499         real x() const
500         {
501             return header().x();
502         }
503         //! \copydoc AnalysisDataFrameHeader::dx()
504         real dx() const
505         {
506             return header().dx();
507         }
508         /*! \brief
509          * Returns point set reference to the column values of this frame.
510          *
511          * Should not be called for invalid frames.
512          */
513         AnalysisDataPointSetRef points() const
514         {
515             GMX_ASSERT(isValid(), "Invalid data frame accessed");
516             return AnalysisDataPointSetRef(header_, 0, values_);
517         }
518         /*! \brief
519          * Returns number of columns in this frame.
520          *
521          * Returns zero for an invalid frame.
522          */
523         int columnCount() const
524         {
525             return values_.size();
526         }
527         /*! \brief
528          * Returns reference container for all column values.
529          */
530         const AnalysisDataValuesRef &values() const
531         {
532             return values_;
533         }
534         /*! \brief
535          * Convenience method for accessing a column value.
536          *
537          * \copydetails AnalysisDataPointSetRef::y()
538          */
539         real y(int i) const
540         {
541             GMX_ASSERT(isValid(), "Invalid data frame accessed");
542             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
543             return values_[i].value();
544         }
545         /*! \brief
546          * Convenience method for accessing error for a column value.
547          *
548          * \copydetails AnalysisDataPointSetRef::dy()
549          */
550         real dy(int i) const
551         {
552             GMX_ASSERT(isValid(), "Invalid data frame accessed");
553             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
554             return values_[i].error();
555         }
556         /*! \brief
557          * Convenience method for accessing present status for a column.
558          *
559          * \copydetails AnalysisDataPointSetRef::present()
560          */
561         bool present(int i) const
562         {
563             GMX_ASSERT(isValid(), "Invalid data frame accessed");
564             GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
565             return values_[i].isPresent();
566         }
567         /*! \brief
568          * Returns true if all points in this frame are present.
569          */
570         bool allPresent() const;
571
572     private:
573         AnalysisDataFrameHeader header_;
574         AnalysisDataValuesRef   values_;
575 };
576
577 } // namespace gmx
578
579 #endif