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