/* * This file is part of the GROMACS molecular simulation package. * * Copyright (c) 2012,2013,2014,2017,2019, by the GROMACS development team, led by * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, * and including many others, as listed in the AUTHORS file in the * top-level source directory and at http://www.gromacs.org. * * GROMACS is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * GROMACS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GROMACS; if not, see * http://www.gnu.org/licenses, or write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * If you want to redistribute modifications to GROMACS, please * consider that scientific software is very special. Version * control is crucial - bugs must be traceable. We will be happy to * consider code for inclusion in the official distribution, but * derived work must not be called official GROMACS. Details are found * in the README & COPYING files - if they are missing, get the * official version at http://www.gromacs.org. * * To help us fund GROMACS development, we humbly ask that you cite * the research papers on the package. Check out http://www.gromacs.org. */ /*! \internal \file * \brief * Implements classes in dataframe.h. * * \author Teemu Murtola * \ingroup module_analysisdata */ #include "gmxpre.h" #include "dataframe.h" #include "gromacs/utility/gmxassert.h" namespace gmx { /******************************************************************** * AnalysisDataFrameHeader */ AnalysisDataFrameHeader::AnalysisDataFrameHeader() : index_(-1), x_(0.0), dx_(0.0) {} AnalysisDataFrameHeader::AnalysisDataFrameHeader(int index, real x, real dx) : index_(index), x_(x), dx_(dx) { GMX_ASSERT(index >= 0, "Invalid frame index"); } /******************************************************************** * AnalysisDataPointSetRef */ AnalysisDataPointSetRef::AnalysisDataPointSetRef(const AnalysisDataFrameHeader& header, const AnalysisDataPointSetInfo& pointSetInfo, const AnalysisDataValuesRef& values) : header_(header), dataSetIndex_(pointSetInfo.dataSetIndex()), firstColumn_(pointSetInfo.firstColumn()), values_(constArrayRefFromArray(&*values.begin() + pointSetInfo.valueOffset(), pointSetInfo.valueCount())) { GMX_ASSERT(header_.isValid(), "Invalid point set reference should not be constructed"); } AnalysisDataPointSetRef::AnalysisDataPointSetRef(const AnalysisDataFrameHeader& header, const std::vector& values) : header_(header), dataSetIndex_(0), firstColumn_(0), values_(values) { GMX_ASSERT(header_.isValid(), "Invalid point set reference should not be constructed"); } AnalysisDataPointSetRef::AnalysisDataPointSetRef(const AnalysisDataPointSetRef& points, int firstColumn, int columnCount) : header_(points.header()), dataSetIndex_(points.dataSetIndex()), firstColumn_(0) { GMX_ASSERT(firstColumn >= 0, "Invalid first column"); GMX_ASSERT(columnCount >= 0, "Invalid column count"); if (points.lastColumn() < firstColumn || points.firstColumn() >= firstColumn + columnCount || columnCount == 0) { return; } AnalysisDataValuesRef::const_iterator begin = points.values().begin(); int pointsOffset = firstColumn - points.firstColumn(); if (pointsOffset > 0) { // Offset pointer if the first column is not the first in points. begin += pointsOffset; } else { // Take into account if first column is before the first in points. firstColumn_ = -pointsOffset; columnCount -= -pointsOffset; } // Decrease column count if there are not enough columns in points. AnalysisDataValuesRef::const_iterator end = begin + columnCount; if (pointsOffset + columnCount > points.columnCount()) { end = points.values().end(); } values_ = AnalysisDataValuesRef(begin, end); } bool AnalysisDataPointSetRef::allPresent() const { AnalysisDataValuesRef::const_iterator i; for (i = values_.begin(); i != values_.end(); ++i) { if (!i->isPresent()) { return false; } } return true; } /******************************************************************** * AnalysisDataFrameRef */ AnalysisDataFrameRef::AnalysisDataFrameRef() {} AnalysisDataFrameRef::AnalysisDataFrameRef(const AnalysisDataFrameHeader& header, const AnalysisDataValuesRef& values, const AnalysisDataPointSetInfosRef& pointSets) : header_(header), values_(values), pointSets_(pointSets) { GMX_ASSERT(!pointSets_.empty(), "There must always be a point set"); } AnalysisDataFrameRef::AnalysisDataFrameRef(const AnalysisDataFrameHeader& header, const std::vector& values, const std::vector& pointSets) : header_(header), values_(values), pointSets_(pointSets) { GMX_ASSERT(!pointSets_.empty(), "There must always be a point set"); } AnalysisDataFrameRef::AnalysisDataFrameRef(const AnalysisDataFrameRef& frame, int firstColumn, int columnCount) : header_(frame.header()), values_(constArrayRefFromArray(&frame.values_[firstColumn], columnCount)), pointSets_(frame.pointSets_) { // FIXME: This doesn't produce a valid internal state, although it does // work in some cases. The point sets cannot be correctly managed here, but // need to be handles by the data proxy class. GMX_ASSERT(firstColumn >= 0, "Invalid first column"); GMX_ASSERT(columnCount >= 0, "Invalid column count"); GMX_ASSERT(pointSets_.size() == 1U, "Subsets of frames only supported with simple data"); GMX_ASSERT(firstColumn + columnCount <= ssize(values_), "Invalid last column"); } bool AnalysisDataFrameRef::allPresent() const { GMX_ASSERT(isValid(), "Invalid data frame accessed"); AnalysisDataValuesRef::const_iterator i; for (i = values_.begin(); i != values_.end(); ++i) { if (!i->isPresent()) { return false; } } return true; } } // namespace gmx