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