2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013, 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.
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.
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.
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.
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.
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.
37 * Declares classes for accessing data frame information.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_analysisdata
43 #ifndef GMX_ANALYSISDATA_DATAFRAME_H
44 #define GMX_ANALYSISDATA_DATAFRAME_H
48 #include "../legacyheaders/types/simple.h"
50 #include "../utility/arrayref.h"
51 #include "../utility/flags.h"
52 #include "../utility/gmxassert.h"
58 * Value type for representing a single value in analysis data objects.
60 * Default copy constructor and assignment operator are used and work as
63 * Methods in this class do not throw.
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
70 * \ingroup module_analysisdata
72 class AnalysisDataValue
76 * Constructs an unset value.
78 AnalysisDataValue() : value_(0.0), error_(0.0) {}
80 * Constructs a value object with the given value.
82 * The constructed object is marked as set and present.
84 explicit AnalysisDataValue(real value)
85 : value_(value), error_(0.0)
88 flags_.set(efPresent);
92 * Direct access to the value.
94 * Assigning a value to this does not mark the value as set; setValue()
95 * must be used for this.
97 real &value() { return value_; }
99 * Direct access to the error estimate.
101 * Assigning a value to this does not mark the error estimate as set;
102 * setValue() must be used for this.
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_; }
110 * Returns whether this value has been set.
112 * If this method returns false, the return value of value() and
113 * error() are undefined.
115 bool isSet() const { return flags_.test(efSet); }
117 * Returns whether the error estimate for this value has been set.
119 * If this method returns false, but isSet() returns true, error()
122 bool hasError() const { return flags_.test(efErrorSet); }
124 * Returns whether this value has been marked as present.
126 * If this method returns false, it is up to the source data to define
127 * whether isSet() may return true.
129 bool isPresent() const { return flags_.test(efPresent); }
131 //! Clears and unsets this value.
134 *this = AnalysisDataValue();
137 void setValue(real value, bool bPresent = true)
141 flags_.set(efPresent, bPresent);
143 //! Sets this value and its error estimate.
144 void setValue(real value, real error, bool bPresent = true)
149 flags_.set(efErrorSet);
150 flags_.set(efPresent, bPresent);
152 //! Set only error estimate for this value.
153 void setError(real error)
156 flags_.set(efErrorSet);
160 //! Possible flags for \a flags_.
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.
168 //! Value for this value.
170 //! Error estimate for this value, zero if not set.
172 //! Status flags for thise value.
173 FlagsTemplate<Flag> flags_;
176 //! Shorthand for reference to an array of data values.
177 typedef ConstArrayRef<AnalysisDataValue> AnalysisDataValuesRef;
181 * Value type for storing frame-level information for analysis data.
183 * Default copy constructor and assignment operator are used and work as
185 * Typically new objects of this type are only constructed internally by the
186 * library and in classes that are derived from AbstractAnalysisData.
188 * Methods in this class do not throw, but may contain asserts for incorrect
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.
195 * \ingroup module_analysisdata
197 class AnalysisDataFrameHeader
201 * Constructs an invalid frame header.
203 * Return values of other methods than isValid() are unspecified for
204 * the constructed object.
206 AnalysisDataFrameHeader();
208 * Constructs a frame header from given values.
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.
214 AnalysisDataFrameHeader(int index, real x, real dx);
217 * Returns whether the frame header corresponds to a valid frame.
219 * If returns false, return values of other methods are not specified.
226 * Returns zero-based index of the frame.
228 * The return value is >= 0 for valid frames.
229 * Should not be called for invalid frames.
233 GMX_ASSERT(isValid(), "Tried to access invalid frame header");
237 * Returns the x coordinate for the frame.
239 * Should not be called for invalid frames.
243 GMX_ASSERT(isValid(), "Tried to access invalid frame header");
247 * Returns error in the x coordinate for the frame (if applicable).
249 * All data do not provide error estimates.
250 * Typically returns zero in those cases.
252 * Should not be called for invalid frames.
256 GMX_ASSERT(isValid(), "Tried to access invalid frame header");
267 /*! \cond libinternal */
268 /*! \libinternal \brief
269 * Value type for internal indexing of point sets.
271 * This class contains the necessary data to split an array of
272 * AnalysisDataValue objects into point sets. It is always specified in the
273 * context of an array of AnalysisDataValues: the point set specified by this
274 * class contains valueCount() values, starting from the array index
276 * The value at location valueOffset() corresponds to column firstColumn().
277 * It is not necessary for code using the analysis data framework to know of
278 * this class, but it is declared in a public header to allow using it in other
281 * Default copy constructor and assignment operator are used and work as
283 * Typically new objects of this type are only constructed internally by the
284 * library and in classes that are derived from AbstractAnalysisData.
286 * Methods in this class do not throw, but may contain asserts for incorrect
289 * Note that it is not possible to change the contents of an initialized
290 * object, except by assigning a new object to replace it completely.
293 * \ingroup module_analysisdata
295 class AnalysisDataPointSetInfo
298 //! Construct point set data object with the given values.
299 AnalysisDataPointSetInfo(int valueOffset, int valueCount,
300 int dataSetIndex, int firstColumn)
301 : valueOffset_(valueOffset), valueCount_(valueCount),
302 dataSetIndex_(dataSetIndex), firstColumn_(firstColumn)
304 GMX_ASSERT(valueOffset >= 0, "Negative value offsets are invalid");
305 GMX_ASSERT(valueCount >= 0, "Negative value counts are invalid");
306 GMX_ASSERT(dataSetIndex >= 0, "Negative data set indices are invalid");
307 GMX_ASSERT(firstColumn >= 0, "Negative column indices are invalid");
310 //! Returns the offset of the first value in the referenced value array.
311 int valueOffset() const { return valueOffset_; }
312 //! Returns the number of values in this point set.
313 int valueCount() const { return valueCount_; }
314 //! Returns the data set index for this point set.
315 int dataSetIndex() const { return dataSetIndex_; }
316 //! Returns the index of the first column in this point set.
317 int firstColumn() const { return firstColumn_; }
326 //! Shorthand for reference to an array of point set data objects.
327 typedef ConstArrayRef<AnalysisDataPointSetInfo> AnalysisDataPointSetInfosRef;
333 * Value type wrapper for non-mutable access to a set of data column values.
335 * Default copy constructor and assignment operator are used and work as
337 * Typically new objects of this type are only constructed internally by the
338 * library and in classes that are derived from AbstractAnalysisData.
340 * Methods in this class do not throw, but may contain asserts for incorrect
343 * The design of the interfaces is such that all objects of this type should be
344 * valid, i.e., header().isValid() should always return true.
346 * Note that it is not possible to change the contents of an initialized
347 * object, except by assigning a new object to replace it completely.
350 * \ingroup module_analysisdata
352 class AnalysisDataPointSetRef
356 * Constructs a point set reference from given values.
358 * \param[in] header Header for the frame.
359 * \param[in] pointSetInfo Information about the point set.
360 * \param[in] values Values for each column.
362 * The first element of the point set should be found from \p values
363 * using the offset in \p pointSetInfo.
365 AnalysisDataPointSetRef(const AnalysisDataFrameHeader &header,
366 const AnalysisDataPointSetInfo &pointSetInfo,
367 const AnalysisDataValuesRef &values);
369 * Constructs a point set reference from given values.
371 * \param[in] header Header for the frame.
372 * \param[in] values Values for each column.
374 * The first element in \p values should correspond to the first
377 AnalysisDataPointSetRef(const AnalysisDataFrameHeader &header,
378 const std::vector<AnalysisDataValue> &values);
380 * Constructs a point set reference to a subset of columns.
382 * \param[in] points Point set to use as source.
383 * \param[in] firstColumn First column index to include.
384 * \param[in] columnCount Number of columns to include.
386 * Creates a point set that contains \p columnCount columns starting
387 * from \p firstColumn from \p points, or a subset if all requested
388 * columns are not present in \p points. If the requested column range
389 * and the range in \p points do not intersect, the result has
390 * columnCount() == 0.
392 * \p firstColumn is relative to the whole data set, i.e., not relative
393 * to points.firstColumn().
395 * Mainly intended for internal use.
397 AnalysisDataPointSetRef(const AnalysisDataPointSetRef &points,
398 int firstColumn, int columnCount);
401 * Returns the frame header for the frame of this point set.
403 const AnalysisDataFrameHeader &header() const
407 //! \copydoc AnalysisDataFrameHeader::index()
408 int frameIndex() const
410 return header_.index();
412 //! \copydoc AnalysisDataFrameHeader::x()
417 //! \copydoc AnalysisDataFrameHeader::dx()
422 //! Returns zero-based index of the dataset that this set is part of.
423 int dataSetIndex() const
425 return dataSetIndex_;
427 //! Returns zero-based index of the first column included in this set.
428 int firstColumn() const
432 //! Returns the number of columns included in this set.
433 int columnCount() const
435 return values().size();
437 //! Returns zero-based index of the last column included in this set (inclusive).
438 int lastColumn() const
440 return firstColumn_ + columnCount() - 1;
443 * Returns reference container for all values.
445 * First value in the returned container corresponds to firstColumn().
447 const AnalysisDataValuesRef &values() const
452 * Returns data value for a column in this set.
454 * \param[in] i Zero-based column index relative to firstColumn().
455 * Should be >= 0 and < columnCount().
459 GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
460 return values()[i].value();
463 * Returns error estimate for a column in this set if applicable.
465 * \param[in] i Zero-based column index relative to firstColumn().
466 * Should be >= 0 and < columnCount().
468 * Currently, this method returns zero if the source data does not
473 GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
474 return values()[i].error();
477 * Returns whether a column is present in this set.
479 * \param[in] i Zero-based column index relative to firstColumn().
480 * Should be >= 0 and < columnCount().
482 * If present(i) returns false, it is depends on the source data
483 * whether y(i) and/or dy(i) are defined.
485 bool present(int i) const
487 GMX_ASSERT(i >= 0 && i < columnCount(), "Out of range data access");
488 return values()[i].isPresent();
491 * Returns true if all points in this point set are present.
493 * That is, if present() would return true for all points.
495 bool allPresent() const;
498 AnalysisDataFrameHeader header_;
501 AnalysisDataValuesRef values_;
506 * Value type wrapper for non-mutable access to a data frame.
508 * Default copy constructor and assignment operator are used and work as
510 * Typically new objects of this type are only constructed internally by the
511 * library and in classes that are derived from AbstractAnalysisData.
513 * Methods in this class do not throw, but may contain asserts for incorrect
516 * Note that it is not possible to change the contents of an initialized
517 * object, except by assigning a new object to replace it completely.
520 * \ingroup module_analysisdata
522 class AnalysisDataFrameRef
526 * Constructs an invalid frame reference.
528 * Return values of other methods than isValid() are unspecified for
529 * the constructed object.
531 AnalysisDataFrameRef();
533 * Constructs a frame reference from given values.
535 * \param[in] header Header for the frame.
536 * \param[in] values Values for each column.
537 * \param[in] pointSets Point set data.
539 AnalysisDataFrameRef(const AnalysisDataFrameHeader &header,
540 const AnalysisDataValuesRef &values,
541 const AnalysisDataPointSetInfosRef &pointSets);
543 * Constructs a frame reference from given values.
545 * \param[in] header Header for the frame.
546 * \param[in] values Values for each column.
547 * \param[in] pointSets Point set data.
549 AnalysisDataFrameRef(const AnalysisDataFrameHeader &header,
550 const std::vector<AnalysisDataValue> &values,
551 const std::vector<AnalysisDataPointSetInfo> &pointSets);
553 * Constructs a frame reference to a subset of columns.
555 * \param[in] frame Frame to use as source.
556 * \param[in] firstColumn First column index to include.
557 * \param[in] columnCount Number of columns to include.
559 * Creates a frame reference that contains \p columnCount columns
560 * starting from \p firstColumn from \p frame, or a subset if all
561 * requested columns are not present in \p frame.
563 * Mainly intended for internal use.
565 AnalysisDataFrameRef(const AnalysisDataFrameRef &frame,
566 int firstColumn, int columnCount);
569 * Returns whether the object refers to a valid frame.
571 * If returns false, return values of other methods are not specified.
575 return header().isValid();
577 //! Returns the header for this frame.
578 const AnalysisDataFrameHeader &header() const
582 //! \copydoc AnalysisDataFrameHeader::index()
583 int frameIndex() const
585 return header().index();
587 //! \copydoc AnalysisDataFrameHeader::x()
592 //! \copydoc AnalysisDataFrameHeader::dx()
595 return header().dx();
598 * Returns the number of point sets for this frame.
600 * Returns zero for an invalid frame.
602 int pointSetCount() const
604 return pointSets_.size();
607 * Returns point set reference for a given point set.
609 * Should not be called for invalid frames.
611 AnalysisDataPointSetRef pointSet(int index) const
613 GMX_ASSERT(isValid(), "Invalid data frame accessed");
614 GMX_ASSERT(index >= 0 && index < pointSetCount(),
615 "Out of range data access");
616 return AnalysisDataPointSetRef(header_, pointSets_[index], values_);
619 * Convenience method for accessing a column value in simple data.
621 * \copydetails AnalysisDataPointSetRef::y()
625 return singleColumnValue(i).value();
628 * Convenience method for accessing error for a column value in simple
631 * \copydetails AnalysisDataPointSetRef::dy()
635 return singleColumnValue(i).error();
638 * Convenience method for accessing present status for a column in
641 * \copydetails AnalysisDataPointSetRef::present()
643 bool present(int i) const
645 return singleColumnValue(i).isPresent();
648 * Returns true if all points in this frame are present.
650 bool allPresent() const;
653 //! Helper method for accessing single columns in simple data.
654 const AnalysisDataValue &singleColumnValue(int i) const
656 GMX_ASSERT(isValid(), "Invalid data frame accessed");
657 GMX_ASSERT(pointSets_.size() == 1U && pointSets_[0].firstColumn() == 0,
658 "Convenience method not available for multiple point sets");
659 GMX_ASSERT(i >= 0 && i < static_cast<int>(values_.size()),
660 "Out of range data access");
664 AnalysisDataFrameHeader header_;
665 AnalysisDataValuesRef values_;
666 AnalysisDataPointSetInfosRef pointSets_;