cfa09e86a3811889cfe6adbabfe52bd4f235e492
[alexxy/gromacs.git] / src / gromacs / analysisdata / dataframe.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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 /*! \internal \file
36  * \brief
37  * Implements classes in dataframe.h.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_analysisdata
41  */
42 #include "dataframe.h"
43
44 #include "gromacs/utility/gmxassert.h"
45
46 namespace gmx
47 {
48
49 /********************************************************************
50  * AnalysisDataFrameHeader
51  */
52
53 AnalysisDataFrameHeader::AnalysisDataFrameHeader()
54     : index_(-1), x_(0.0), dx_(0.0)
55 {
56 }
57
58
59 AnalysisDataFrameHeader::AnalysisDataFrameHeader(int index, real x, real dx)
60     : index_(index), x_(x), dx_(dx)
61 {
62     GMX_ASSERT(index >= 0, "Invalid frame index");
63 }
64
65
66 /********************************************************************
67  * AnalysisDataPointSetRef
68  */
69
70 AnalysisDataPointSetRef::AnalysisDataPointSetRef(
71         const AnalysisDataFrameHeader  &header,
72         const AnalysisDataPointSetInfo &pointSetInfo,
73         const AnalysisDataValuesRef    &values)
74     : header_(header),
75       dataSetIndex_(pointSetInfo.dataSetIndex()),
76       firstColumn_(pointSetInfo.firstColumn()),
77       values_(constArrayRefFromArray(&*values.begin() + pointSetInfo.valueOffset(),
78                                      pointSetInfo.valueCount()))
79 {
80     GMX_ASSERT(header_.isValid(),
81                "Invalid point set reference should not be constructed");
82 }
83
84
85 AnalysisDataPointSetRef::AnalysisDataPointSetRef(
86         const AnalysisDataFrameHeader        &header,
87         const std::vector<AnalysisDataValue> &values)
88     : header_(header), dataSetIndex_(0), firstColumn_(0),
89       values_(constArrayRefFromVector<AnalysisDataValue>(values.begin(), values.end()))
90 {
91     GMX_ASSERT(header_.isValid(),
92                "Invalid point set reference should not be constructed");
93 }
94
95
96 AnalysisDataPointSetRef::AnalysisDataPointSetRef(
97         const AnalysisDataPointSetRef &points, int firstColumn, int columnCount)
98     : header_(points.header()), dataSetIndex_(points.dataSetIndex()),
99       firstColumn_(0)
100 {
101     GMX_ASSERT(firstColumn >= 0, "Invalid first column");
102     GMX_ASSERT(columnCount >= 0, "Invalid column count");
103     if (points.lastColumn() < firstColumn
104         || points.firstColumn() >= firstColumn + columnCount
105         || columnCount == 0)
106     {
107         return;
108     }
109     AnalysisDataValuesRef::const_iterator begin = points.values().begin();
110     int pointsOffset = firstColumn - points.firstColumn();
111     if (pointsOffset > 0)
112     {
113         // Offset pointer if the first column is not the first in points.
114         begin += pointsOffset;
115     }
116     else
117     {
118         // Take into account if first column is before the first in points.
119         firstColumn_ = -pointsOffset;
120         columnCount -= -pointsOffset;
121     }
122     // Decrease column count if there are not enough columns in points.
123     AnalysisDataValuesRef::const_iterator end = begin + columnCount;
124     if (pointsOffset + columnCount > points.columnCount())
125     {
126         end = points.values().end();
127     }
128     values_ = AnalysisDataValuesRef(begin, end);
129 }
130
131
132 bool AnalysisDataPointSetRef::allPresent() const
133 {
134     AnalysisDataValuesRef::const_iterator i;
135     for (i = values_.begin(); i != values_.end(); ++i)
136     {
137         if (!i->isPresent())
138         {
139             return false;
140         }
141     }
142     return true;
143 }
144
145
146 /********************************************************************
147  * AnalysisDataFrameRef
148  */
149
150 AnalysisDataFrameRef::AnalysisDataFrameRef()
151 {
152 }
153
154
155 AnalysisDataFrameRef::AnalysisDataFrameRef(
156         const AnalysisDataFrameHeader      &header,
157         const AnalysisDataValuesRef        &values,
158         const AnalysisDataPointSetInfosRef &pointSets)
159     : header_(header), values_(values), pointSets_(pointSets)
160 {
161     GMX_ASSERT(!pointSets_.empty(), "There must always be a point set");
162 }
163
164
165 AnalysisDataFrameRef::AnalysisDataFrameRef(
166         const AnalysisDataFrameHeader               &header,
167         const std::vector<AnalysisDataValue>        &values,
168         const std::vector<AnalysisDataPointSetInfo> &pointSets)
169     : header_(header), values_(constArrayRefFromVector<AnalysisDataValue>(values.begin(), values.end())),
170       pointSets_(constArrayRefFromVector<AnalysisDataPointSetInfo>(pointSets.begin(), pointSets.end()))
171 {
172     GMX_ASSERT(!pointSets_.empty(), "There must always be a point set");
173 }
174
175
176 AnalysisDataFrameRef::AnalysisDataFrameRef(
177         const AnalysisDataFrameRef &frame, int firstColumn, int columnCount)
178     : header_(frame.header()),
179       values_(constArrayRefFromArray(&frame.values_[firstColumn], columnCount)),
180       pointSets_(frame.pointSets_)
181 {
182     // FIXME: This doesn't produce a valid internal state, although it does
183     // work in some cases. The point sets cannot be correctly managed here, but
184     // need to be handles by the data proxy class.
185     GMX_ASSERT(firstColumn >= 0, "Invalid first column");
186     GMX_ASSERT(columnCount >= 0, "Invalid column count");
187     GMX_ASSERT(pointSets_.size() == 1U,
188                "Subsets of frames only supported with simple data");
189     GMX_ASSERT(firstColumn + columnCount <= static_cast<int>(values_.size()),
190                "Invalid last column");
191 }
192
193
194 bool AnalysisDataFrameRef::allPresent() const
195 {
196     GMX_ASSERT(isValid(), "Invalid data frame accessed");
197     AnalysisDataValuesRef::const_iterator i;
198     for (i = values_.begin(); i != values_.end(); ++i)
199     {
200         if (!i->isPresent())
201         {
202             return false;
203         }
204     }
205     return true;
206 }
207
208 } // namespace gmx