<NME> TimeSeriesTable.h
<BEF> /* -------------------------------------------------------------------------- *
 *                            OpenSim:  TimeSeriesTable.h                     *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2017 Stanford University and the Authors                *
 * Authors:                                                                   *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

#ifndef OPENSIM_TIME_SERIES_DATA_TABLE_H_
#define OPENSIM_TIME_SERIES_DATA_TABLE_H_

/** \file
This file defines the TimeSeriesTable_ class, which is used by OpenSim to 
provide an in-memory container for data access and manipulation.              */

#include "OpenSim/Common/DataTable.h"
#include <SimTKsimbody.h>
#include "Logger.h"

namespace OpenSim {

class InvalidTable : public Exception {
public:
    using Exception::Exception;
};

class TimeColumnNotIncreasing : public InvalidTable {
public:
    TimeColumnNotIncreasing(const std::string& file, 
                            size_t line,
                            const std::string& func) :
        InvalidTable(file, line, func) {
        std::string msg = "Time column is not strictly increasing";

        addMessage(msg);
    } 
};

class InvalidTimestamp : public InvalidRow {
public:
#ifndef SWIG
    using InvalidRow::InvalidRow;
#endif
};

class TimestampLessThanEqualToPrevious : public InvalidTimestamp {
public:
    TimestampLessThanEqualToPrevious(const std::string& file,
                                     size_t line,
                                     const std::string& func,
                                     size_t rowIndex,
                                     double new_timestamp,
                                     double prev_timestamp) :
        InvalidTimestamp(file, line, func) {
        std::string msg = "Timestamp at row " + std::to_string(rowIndex);
        msg += " with value " + std::to_string(new_timestamp);
        msg += " is less-than/equal to timestamp at row ";
        msg += std::to_string(rowIndex - 1) + " with value ";
        msg += std::to_string(prev_timestamp);

        addMessage(msg);
    }
};

class TimestampGreaterThanEqualToNext : public InvalidTimestamp {
public:
    TimestampGreaterThanEqualToNext(const std::string& file,
                                    size_t line,
                                    const std::string& func,
                                    size_t rowIndex,
                                    double new_timestamp,
                                    double next_timestamp) :
        InvalidTimestamp(file, line, func) {
        std::string msg = "Timestamp at row " + std::to_string(rowIndex);
        msg += " with value " + std::to_string(new_timestamp);
        msg += " is greater-than/equal to timestamp at row "; 
        msg += std::to_string(rowIndex + 1) + " with value "; 
        msg += std::to_string(next_timestamp);

        addMessage(msg);
    }
};
template<typename ETY = SimTK::Real>
class TimeSeriesTable_ : public DataTable_<double, ETY> {
public:
    using RowVector = SimTK::RowVector_<ETY>;

    TimeSeriesTable_()                                   = default;
    TimeSeriesTable_(const TimeSeriesTable_&)            = default;
                   const double min,
                   const double max) :
        Exception(file, line, func) {
        std::string msg = "Time " + std::to_string(time) + 
            " is out of time range [" + std::to_string(min) +
            ", " + std::to_string(max) + "]";

        addMessage(msg);
    }
};

class InvalidTimeRange : public Exception {
public:
    InvalidTimeRange(const std::string& file,
                     size_t line,
                     const std::string& func,
                     const double begTime,
                     const double endTime) :
        Exception(file, line, func) {
        std::string msg = " Invalid time range: initial time " + 
            std::to_string(begTime)  + " >= final time = " +
            std::to_string(endTime);

        addMessage(msg);
    }
};

/** TimeSeriesTable_ is a DataTable_ where the independent column is time of 
type double. The time column is enforced to be strictly increasing.           */
template<typename ETY = SimTK::Real>
class TimeSeriesTable_ : public DataTable_<double, ETY> {
public:
    typedef SimTK::RowVector_<ETY>     RowVector;
    typedef SimTK::RowVectorView_<ETY> RowVectorView;

    TimeSeriesTable_()                                   = default;
    TimeSeriesTable_(const TimeSeriesTable_&)            = default;
    TimeSeriesTable_(TimeSeriesTable_&&)                 = default;
    TimeSeriesTable_& operator=(const TimeSeriesTable_&) = default;
    TimeSeriesTable_& operator=(TimeSeriesTable_&&)      = default;
    ~TimeSeriesTable_()                                  = default;

    /** Convenience constructor to efficiently populate a time series table
    from available data. This is primarily useful for constructing with large
    data read in from file without having to reallocate and copy memory.*/
    TimeSeriesTable_(const std::vector<double>& indVec,
}; // TimeSeriesTable_

/** See TimeSeriesTable_ for details on the interface.                        */
using TimeSeriesTable = TimeSeriesTable_<SimTK::Real>;

} // namespace OpenSim

            // because base classes cannot properly invoke virtual functions.
            this->validateDependentsMetaData();
            for (size_t i = 0; i < indVec.size(); ++i) {
                this->validateRow(i, indVec[i], depData.row(int(i)));
            }
        }
        catch (std::exception&) {
            // wipe out the data loaded if any
            this->_indData.clear();
            this->_depData.clear();
            this->removeDependentsMetaDataForKey("labels");
            throw;
        }
    }

    /** Construct a table with only the independent (time) column and 0
    dependent columns. This constructor is useful if you want to populate the
    table by appending columns rather than by appending rows.                 */
    TimeSeriesTable_(const std::vector<double>& indVec) :
            DataTable_<double, ETY>(indVec) {
        try {
            // Perform the validation of the data of this TimeSeriesTable.
            // validateDependentsMetaData() invoked by the DataTable_
            // constructor via setColumnLabels(), but we invoke it again
            // because base classes cannot properly invoke virtual functions.
            this->validateDependentsMetaData();
            for (size_t i = 0; i < indVec.size(); ++i) {
                this->validateRow(i, indVec[i], this->_depData.row(int(i)));
            }
        }
        catch (std::exception&) {
            // wipe out the data loaded if any
            this->_indData.clear();
            this->_depData.clear(); // should be empty
            this->removeDependentsMetaDataForKey("labels"); // should be empty
            throw;
        }

    }

#ifndef SWIG
    using DataTable_<double, ETY>::DataTable_;
    using DataTable_<double, ETY>::operator=;
    /** Flatten the columns of this table to create a TimeSeriesTable_<double>.
    See documentation of DataTable_::flatten() for details.                   */
    using DataTable_<double, ETY>::flatten;
    /** Pack the columns of this table (which should be TimeSeriesTable_<double>
    ) to create a TimeSeriesTable_<SimTK::Vec3>, TimeSeriesTable_<SimTK::Vec6>,
    TimeSeriesTable_<SimTK::UnitVec3> and so on. See documentation for 
    DataTable_::pack().                                                       */
    using DataTable_<double, ETY>::pack;
#endif    
    
    /** Construct a TimeSeriesTable_ from a DataTable_.                       

    \throws InvalidTable If the input table's independent column is not strictly
                         increasing.                                          */
    TimeSeriesTable_(const DataTable_<double, ETY>& datatable) : 
        DataTable_<double, ETY>(datatable) {
        using DT = DataTable_<double, ETY>;

        OPENSIM_THROW_IF(!std::is_sorted(DT::_indData.cbegin(), 
                                         DT::_indData.cend()) ||
                         std::adjacent_find(DT::_indData.cbegin(), 
                                            DT::_indData.cend()) != 
                         DT::_indData.cend(),
                         TimeColumnNotIncreasing);
    }

    /** Construct TimeSeriesTable_ from a file.

    \param filename Name of the file.

    \throws InvalidArgument If the input file contains more than one table.
    \throws InvalidArgument If the input file contains a table that is not of
                            this TimeSeriesTable_ type.                       */
    TimeSeriesTable_(const std::string& filename) : 
        TimeSeriesTable_{filename, ""} {}

    /** Construct TimeSeriesTable_ from a file.

    \param filename Name of the file.
    \param tablename Name of the table in the file to construct this 
                     TimeSeriesTable_ from. For example, a c3d file contains 
                     tables named 'markers' and 'forces'.

    \throws InvalidArgument If the input file contains more than one table and 
                            tablename was not specified.
    \throws InvalidArgument If the input file contains a table that is not of
                            this TimeSeriesTable_ type.                       */
    TimeSeriesTable_(const std::string& filename, 
                     const std::string& tablename) {
        auto absTables = FileAdapter::createAdapterFromExtension(filename)->read(filename);

        OPENSIM_THROW_IF(absTables.size() > 1 && tablename.empty(),
                         InvalidArgument,
                         "File '" + filename + 
                         "' contains more than one table and tablename not "
                         "specified.");

        AbstractDataTable* absTable{};
        if(tablename.empty()) {
            absTable = (absTables.cbegin()->second).get();
        } else {
            try {
                absTable = absTables.at(tablename).get();
            } catch (const std::out_of_range&) {
                OPENSIM_THROW(InvalidArgument,
                              "File '" + filename + "' contains no table named "
                              "'"+ tablename + "'.");
            }
        }
        auto table = dynamic_cast<TimeSeriesTable_*>(absTable);
        OPENSIM_THROW_IF(table == nullptr,
                         InvalidArgument,
                         "DataTable cannot be created from file '" + filename +
                         "'. Type mismatch.");

        *this = std::move(*table);
    }

    /** Get index of row whose time is nearest/closest to the given value.

    \param time Value to search for.
    \param restrictToTimeRange  When true -- Exception is thrown if the given
                                value is out-of-range of the time column. A value
                                within SimTK::SignifcantReal of a time column
                                bound is considered to be equal to the bound.
                                When false -- If the given value is less than or
                                equal to the first value in the time column, the
                                index returned is of the first row. If the given
                                value is greater than or equal to the last value
                                in the time column, the index of the last row is
                                returned. Defaults to 'true'.

    \throws TimeOutOfRange If the given value is out-of-range of time column.
    \throws EmptyTable If the table is empty.                                 */
    size_t getNearestRowIndexForTime(const double time,
                                     const bool restrictToTimeRange = true) const {
        using DT = DataTable_<double, ETY>;
        const auto& timeCol = DT::getIndependentColumn();
        OPENSIM_THROW_IF(timeCol.size() == 0,
            EmptyTable);
        const SimTK::Real eps = SimTK::SignificantReal;
        OPENSIM_THROW_IF(restrictToTimeRange &&
            ((time < timeCol.front() - eps) ||
            (time > timeCol.back() + eps)),
            TimeOutOfRange,
            time, timeCol.front(), timeCol.back());

        auto iter = std::lower_bound(timeCol.begin(), timeCol.end(), time);
        if (iter == timeCol.end())
            return timeCol.size() - 1;
        if (iter == timeCol.begin())
            return 0;
        if ((*iter - time) <= (time - *std::prev(iter)))
            return std::distance(timeCol.begin(), iter);
        else
            return std::distance(timeCol.begin(), std::prev(iter));
    }
    /** Get index of row whose time is first to be higher than the given value.

     \param time Value to search for.
     */
    size_t getRowIndexAfterTime(
            const double& time) const {
        size_t candidate = getNearestRowIndexForTime(time, false);
        using DT = DataTable_<double, ETY>;
        const auto& timeCol = DT::getIndependentColumn();
        const SimTK::Real eps = SimTK::SignificantReal;
        // increment if less than time passed in
        if (timeCol[candidate] < time-eps) 
            candidate++;
        OPENSIM_THROW_IF(candidate > timeCol.size() - 1,
                    TimeOutOfRange, time, timeCol.front(), timeCol.back());
        return candidate;
    }
    /** Get index of row whose time is the largest time less than the given value.

     \param time Value to search for.
     */
    size_t getRowIndexBeforeTime(const double& time) const {
        size_t candidate = getNearestRowIndexForTime(time, false);
        using DT = DataTable_<double, ETY>;
        const auto& timeCol = DT::getIndependentColumn();
        const SimTK::Real eps = SimTK::SignificantReal;
        // increment if less than time passed in
        if (timeCol[candidate] > time+eps) candidate--;
        OPENSIM_THROW_IF(candidate < 0, TimeOutOfRange, time,
                timeCol.front(), timeCol.back());
        return candidate;
    }

    /** Get row whose time column is nearest/closest to the given value. 

    \param time Value to search for. 
    \param restrictToTimeRange When true -- Exception is thrown if the given 
                               value is out-of-range of the time column. 
                               When false -- If the given value is less than or 
                               equal to the first value in the time column, the
                               row returned is the first row. If the given value
                               is greater than or equal to the last value in the
                               time column, the row returned is the last row. 
                               This operation only returns existing rows and 
                               does not perform any interpolation. Defaults to
                               'true'.

    \throws TimeOutOfRange If the given value is out-of-range of time column.
    \throws EmptyTable If the table is empty.                                 */
    RowVectorView
    getNearestRow(const double& time,
                  const bool restrictToTimeRange = true) const {
        using DT = DataTable_<double, ETY>;
        return DT::getRowAtIndex( 
            getNearestRowIndexForTime(time, restrictToTimeRange) );
    }

    /** Get writable reference to row whose time column is nearest/closest to 
    the given value. 

    \param time Value to search for. 
    \param restrictToTimeRange When true -- Exception is thrown if the given 
                               value is out-of-range of the time column. 
                               When false -- If the given value is less than or 
                               equal to the first value in the time column, the
                               row returned is the first row. If the given value
                               is greater than or equal to the last value in the
                               time column, the row returned is the last row. 
                               This operation only returns existing rows and 
                               does not perform any interpolation. Defaults to
                               'true'.

    \throws TimeOutOfRange If the given value is out-of-range of time column.
    \throws EmptyTable If the table is empty.                                 */
    RowVectorView
    updNearestRow(const double& time,
                  const bool restrictToTimeRange = true) {
        using DT = DataTable_<double, ETY>;
        return DT::updRowAtIndex(
            getNearestRowIndexForTime(time, restrictToTimeRange));
    }

    /** Compute the average row in the time range (inclusive) given. This
    operation does not modify the table. It just computes and returns an average
    row. 

    \throws InvalidTimeRange If beginTime is greater than or equal to endTime.
    \throws TimeOutOfRange If beginTime or endTime is out of range of time 
                           column.                                            */
    RowVector averageRow(const double& beginTime, const double& endTime) const {
        using DT = DataTable_<double, ETY>;
        OPENSIM_THROW_IF(endTime <= beginTime,
                         InvalidTimeRange,
                         beginTime, endTime);
        const auto& timeCol = DT::getIndependentColumn();
        OPENSIM_THROW_IF(beginTime < timeCol.front() ||
                         beginTime > timeCol.back(),
                         TimeOutOfRange,
                         beginTime, timeCol.front(), timeCol.back(),);
        OPENSIM_THROW_IF(endTime < timeCol.front() ||
                         endTime > timeCol.back(),
                         TimeOutOfRange,
                         endTime, timeCol.front(), timeCol.back());

        std::vector<double> comps(DT::numComponentsPerElement(), 0);
        RowVector row{static_cast<int>(DT::getNumColumns()),
                      DT::makeElement(comps.begin(), comps.end())};
        unsigned numRowsInRange{};
        for(unsigned r = 0; r < DT::getNumRows(); ++r) {
            if(timeCol[r] >= beginTime && timeCol[r] <= endTime) {
                row += DT::getRowAtIndex(r);
                ++numRowsInRange;
            }
        }
        row /= numRowsInRange;

        return row;
    }
    /**
     * Trim TimeSeriesTable to rows that have times that lies between 
     * newStartTime, newFinalTime. The trimming is done in place, no copy is made. 
     * Uses getRowIndexAfterTime to locate first row and
     * getNearestRowIndexForTime method to locate last row.
     */
    void trim(const double& newStartTime, const double& newFinalTime) {
        OPENSIM_THROW_IF(newFinalTime < newStartTime, EmptyTable);
        const auto& timeCol = this->getIndependentColumn();
        size_t start_index = 0;
        size_t last_index = this->getNumRows() - 1;
        // Avoid throwing exception if newStartTime is less than first time
        // or newFinalTime is greater than last value in table
        start_index = this->getRowIndexAfterTime(newStartTime);
        last_index = this->getRowIndexBeforeTime(newFinalTime);
        // Make sure last_index >= start_index before attempting to trim
        OPENSIM_THROW_IF(last_index < start_index, EmptyTable);
        // do the actual trimming based on index instead of time.
        trimToIndices(start_index, last_index);
        // If resulting table is empty, throw
        if (this->getNumRows()==0)
            log_warn("Trimming resulted in an empty table.");
    }
    /**
     * trim TimeSeriesTable, keeping rows at newStartTime to the end.
     */
    void trimFrom(const double& newStartTime) { 
        this->trim(newStartTime, this->getIndependentColumn().back());
    }
    /**
     * trim TimeSeriesTable, keeping rows up to newFinalTime
     */
    void trimTo(const double& newFinalTime) {
        this->trim(this->getIndependentColumn().front(), newFinalTime);
    }
protected:
    /** Validate the given row. 

    \throws InvalidRow If the timestamp for the row breaks strictly increasing
                       property of the independent column.                    */
    void validateRow(size_t rowIndex,
                     const double& time, 
                     const RowVector& row) const override {
        using DT = DataTable_<double, ETY>;

        if(DT::_indData.empty())
            return;

        if(rowIndex > 0) {
            OPENSIM_THROW_IF(DT::_indData[rowIndex - 1] >= time,
                             TimestampLessThanEqualToPrevious, rowIndex, time, 
                             DT::_indData[rowIndex - 1]);
        }

        if(rowIndex < DT::_indData.size() - 1) {
            OPENSIM_THROW_IF(DT::_indData[rowIndex + 1] <= time,
                             TimestampGreaterThanEqualToNext, rowIndex, time, 
                             DT::_indData[rowIndex + 1]);
        }
    }
    /** trim table to rows between start_index and last_index inclusively
     */
    void trimToIndices(const size_t& start_index, const size_t& last_index) {
        // This uses the rather invasive but efficient mechanism to copy a
        // block of the underlying Matrix.
        // Side effect may include that headers/metaData may be left stale.
        // Alternatively we can create a new TimeSeriesTable and copy contents
        // one row at a time but that's rather overkill
        SimTK::Matrix_<ETY> matrixBlock = this->updMatrix()((int)start_index, 0,
                (int)(last_index - start_index + 1),
                (int)this->getNumColumns());
        this->updMatrix() = matrixBlock;
        std::vector<double> newIndependentVector = std::vector<double>(
                this->getIndependentColumn().begin() + start_index,
                this->getIndependentColumn().begin() + last_index + 1);
        this->_indData = newIndependentVector;
    }

    friend class TableUtilities;

}; // TimeSeriesTable_

/** See TimeSeriesTable_ for details on the interface.                        */
typedef TimeSeriesTable_<SimTK::Real> TimeSeriesTable;

/** See TimeSeriesTable_ for details on the interface.                        */
typedef TimeSeriesTable_<SimTK::Vec3> TimeSeriesTableVec3;

/** See TimeSeriesTable_ for details on the interface.                        */
typedef TimeSeriesTable_<SimTK::Quaternion> TimeSeriesTableQuaternion;

/** See TimeSeriesTable_ for details on the interface.                        */
typedef TimeSeriesTable_<SimTK::Rotation> TimeSeriesTableRotation;

} // namespace OpenSim

#endif // OPENSIM_TIME_SERIES_DATA_TABLE_H_

<MSG> Wrap all necessary classes to make wrapping of DataTable and TimeSeriesTable work.
* Wrap RowVectorBase, RowVectorView, VectorBase, VectorView
* Wrap DataTable, TimeSeriesTable.

<DFF> @@ -98,7 +98,7 @@ type double. The time column is enforced to be strictly increasing.           */
 template<typename ETY = SimTK::Real>
 class TimeSeriesTable_ : public DataTable_<double, ETY> {
 public:
-    using RowVector = SimTK::RowVector_<ETY>;
+    typedef SimTK::RowVector_<ETY> RowVector;
 
     TimeSeriesTable_()                                   = default;
     TimeSeriesTable_(const TimeSeriesTable_&)            = default;
@@ -151,7 +151,7 @@ protected:
 }; // TimeSeriesTable_
 
 /** See TimeSeriesTable_ for details on the interface.                        */
-using TimeSeriesTable = TimeSeriesTable_<SimTK::Real>;
+typedef TimeSeriesTable_<SimTK::Real> TimeSeriesTable;
 
 } // namespace OpenSim
 

{'commit': 'diff --git a/Bindings/SWIGSimTK/BigMatrix.h b/Bindings/SWIGSimTK/BigMatrix.h\nindex d71183ebe..ae5cc86df 100644\n--- a/Bindings/SWIGSimTK/BigMatrix.h\n+++ b/Bindings/SWIGSimTK/BigMatrix.h\n@@ -1495,14 +1495,13 @@ private:\n #endif\n };\n \n-\n-#ifndef SWIG\n //  ------------------------------- RowVectorBase ------------------------------\n /// This is a dataless rehash of the MatrixBase class to specialize it for RowVectors.\n /// This mostly entails overriding a few of the methods. Note that all the MatrixBase\n /// operations remain available if you static_cast<> this up to a MatrixBase.\n //  ----------------------------------------------------------------------------\n template <class ELT> class RowVectorBase : public MatrixBase<ELT> {\n+#ifndef SWIG\n     typedef MatrixBase<ELT>                             Base;\n     typedef typename CNT<ELT>::Scalar                   Scalar;\n     typedef typename CNT<ELT>::Number                   Number;\n@@ -1511,6 +1510,7 @@ template <class ELT> class RowVectorBase : public MatrixBase<ELT> {\n     typedef RowVectorBase<typename CNT<ELT>::TAbs>      TAbs;\n     typedef RowVectorBase<typename CNT<ELT>::TNeg>      TNeg;\n     typedef VectorView_<typename CNT<ELT>::THerm>       THerm;\n+#endif\n public: \n     //  ------------------------------------------------------------------------\n     /// @name       RowVectorBase "owner" construction\n@@ -1532,8 +1532,10 @@ public:\n     /// initialized from the source object.    \n     RowVectorBase(const RowVectorBase& source) : Base(source) {}\n \n+#ifndef SWIG\n     /// Implicit conversion from compatible row vector with negated elements.\n     RowVectorBase(const TNeg& source) : Base(source) {}\n+#endif\n \n     /// Construct an owner row vector of length n, with each element initialized to\n     /// the given value.\n@@ -1558,6 +1560,7 @@ public:\n     /// both read-only and writable external data.\n     /// @{\n \n+#ifndef SWIG\n     /// Construct a read-only view of existing data.\n     RowVectorBase(int n, int stride, const Scalar* s)\n     :   Base(MatrixCommitment::RowVector(n), MatrixCharacter::RowVector(n),stride,s) { }\n@@ -1565,6 +1568,7 @@ public:\n     RowVectorBase(int n, int stride, Scalar* s)\n     :   Base(MatrixCommitment::RowVector(n), MatrixCharacter::RowVector(n),stride,s) { }\n     /// @}\n+#endif\n \n     //  ------------------------------------------------------------------------\n     /// @name       RowVectorBase construction from an existing Helper.\n@@ -1574,6 +1578,7 @@ public:\n     /// view of the original data and one providing a writable view into the original data.\n     /// @{\n \n+#ifndef SWIG\n     /// Construct a writable view into the source data.\n     RowVectorBase(MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::ShallowCopy& s) \n     :   Base(MatrixCommitment::RowVector(), h,s) { }\n@@ -1593,6 +1598,7 @@ public:\n         typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Add> Add;\n         typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Sub> Sub;\n     };\n+#endif\n \n     /// Copy assignment is deep copy but behavior depends on type of lhs: if view, rhs\n     /// must match. If owner, we reallocate and copy rhs.\n@@ -1644,6 +1650,8 @@ public:\n     // elementwise multiply from left\n     template <class EE> RowVectorBase& elementwiseMultiplyFromLeftInPlace(const RowVectorBase<EE>& r)\n     { Base::template elementwiseMultiplyFromLeftInPlace<EE>(r); return *this; }\n+\n+#ifndef SWIG\n     template <class EE> inline void \n     elementwiseMultiplyFromLeft(\n         const RowVectorBase<EE>& v, \n@@ -1651,6 +1659,7 @@ public:\n     { \n         Base::template elementwiseMultiplyFromLeft<EE>(v,out);\n     }\n+\n     template <class EE> inline \n     typename RowVectorBase<EE>::template EltResult<ELT>::Mul \n     elementwiseMultiplyFromLeft(const RowVectorBase<EE>& v) const {\n@@ -1658,6 +1667,7 @@ public:\n         Base::template elementwiseMultiplyFromLeft<EE>(v,out); \n         return out;\n     }\n+#endif\n \n     // elementwise divide\n     template <class EE> RowVectorBase& elementwiseDivideInPlace(const RowVectorBase<EE>& r)\n@@ -1670,6 +1680,8 @@ public:\n     // elementwise divide from left\n     template <class EE> RowVectorBase& elementwiseDivideFromLeftInPlace(const RowVectorBase<EE>& r)\n     { Base::template elementwiseDivideFromLeftInPlace<EE>(r); return *this; }\n+\n+#ifndef SWIG\n     template <class EE> inline void \n     elementwiseDivideFromLeft\n        (const RowVectorBase<EE>& v, \n@@ -1683,6 +1695,7 @@ public:\n         Base::template elementwiseDivideFromLeft<EE>(v,out); \n         return out;\n     }\n+#endif\n \n     // Implicit conversions are allowed to RowVector or Matrix, but not to Vector.   \n     operator const RowVector_<ELT>&()     const {return *reinterpret_cast<const RowVector_<ELT>*>(this);}\n@@ -1706,10 +1719,12 @@ public:\n     int       ncol() const {assert(Base::nrow()==1); return Base::ncol();}\n     ptrdiff_t nelt() const {assert(Base::nrow()==1); return Base::nelt();}\n \n+#ifndef SWIG\n     // Override MatrixBase operators to return the right shape\n     TAbs abs() const {\n         TAbs result; Base::abs(result); return result;\n     }\n+#endif\n \n     // Override MatrixBase indexing operators          \n     const ELT& operator[](int j) const {return *reinterpret_cast<const ELT*>(Base::getHelper().getElt(j));}\n@@ -1734,22 +1749,25 @@ public:\n     RowVectorView_<ELT> operator()(const Array_<int>& indices) const {return index(indices);}\n     RowVectorView_<ELT> operator()(const Array_<int>& indices)       {return updIndex(indices);}\n  \n+#ifndef SWIG\n     // Hermitian transpose.\n     THerm transpose() const {return Base::transpose().getAsVectorView();}\n     THerm updTranspose()    {return Base::updTranspose().updAsVectorView();}\n \n     THerm operator~() const {return transpose();}\n     THerm operator~()       {return updTranspose();}\n+#endif\n \n     const RowVectorBase& operator+() const {return *this; }\n \n+#ifndef SWIG\n     // Negation\n-\n     const TNeg& negate()    const {return *reinterpret_cast<const TNeg*>(this); }\n     TNeg&       updNegate()       {return *reinterpret_cast<TNeg*>(this); }\n \n     const TNeg& operator-() const {return negate();}\n     TNeg&       operator-()       {return updNegate();}\n+#endif\n \n     RowVectorBase& resize(int n)     {Base::resize(1,n); return *this;}\n     RowVectorBase& resizeKeep(int n) {Base::resizeKeep(1,n); return *this;}\n@@ -1773,6 +1791,7 @@ private:\n     // NO DATA MEMBERS ALLOWED\n };\n \n+#ifndef SWIG\n \n \n //  ------------------------------- MatrixView_ --------------------------------\n@@ -2003,7 +2022,6 @@ private:\n     // NO DATA MEMBERS ALLOWED\n };\n \n-#ifndef SWIG\n //  -------------------------------- VectorView_ -------------------------------\n /// This class is identical to a Vector_; it is used only to manage the C++ rules\n /// for when copy constructors are called by introducing a separate type to\n@@ -2012,6 +2030,7 @@ private:\n /// However, there are no owner constructors for VectorView_. \n //  ----------------------------------------------------------------------------\n template <class ELT> class VectorView_ : public VectorBase<ELT> {\n+#ifndef SWIG\n     typedef VectorBase<ELT>                             Base;\n     typedef typename CNT<ELT>::Scalar                   S;\n     typedef typename CNT<ELT>::Number                   Number;\n@@ -2019,12 +2038,15 @@ template <class ELT> class VectorView_ : public VectorBase<ELT> {\n     typedef VectorView_<ELT>                            T;\n     typedef VectorView_< typename CNT<ELT>::TNeg >      TNeg;\n     typedef RowVectorView_< typename CNT<ELT>::THerm >  THerm;\n+#endif\n public:\n     // Default construction is suppressed.\n     // Uses default destructor.\n \n+#ifndef SWIG\n     // Create a VectorView_ handle using a given helper rep. \n     explicit VectorView_(MatrixHelperRep<S>* hrep) : Base(hrep) {}\n+#endif\n \n     // Copy constructor is shallow. CAUTION: despite const argument, this preserves writability\n     // if it was present in the source. This is necessary to allow temporary views to be\n@@ -2037,9 +2059,11 @@ public:\n         Base::operator=(v); return *this;\n     }\n \n+#ifndef SWIG\n     // Ask for shallow copy    \n     explicit VectorView_(const MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { }\n     explicit VectorView_(MatrixHelper<S>&       h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { }\n+#endif\n     \n     VectorView_& operator=(const Base& b) { Base::operator=(b); return *this; }\n \n@@ -2062,7 +2086,6 @@ private:\n     VectorView_(); // default construction suppressed (what\'s it a View of?)\n };\n \n-#endif\n \n //  ---------------------------------- Vector_ ---------------------------------\n /// This is the Vector class intended to appear in user code. It can be a \n@@ -2158,7 +2181,6 @@ private:\n \n };\n \n-#ifndef SWIG\n \n //  ------------------------------ RowVectorView_ ------------------------------\n /// This class is identical to a RowVector_; it is used only to manage the C++ \n@@ -2168,6 +2190,7 @@ private:\n /// RowVectorView_. However, there are no owner constructors for RowVectorView_. \n //  ----------------------------------------------------------------------------\n template <class ELT> class RowVectorView_ : public RowVectorBase<ELT> {\n+#ifndef SWIG\n     typedef RowVectorBase<ELT>                              Base;\n     typedef typename CNT<ELT>::Scalar                       S;\n     typedef typename CNT<ELT>::Number                       Number;\n@@ -2175,12 +2198,15 @@ template <class ELT> class RowVectorView_ : public RowVectorBase<ELT> {\n     typedef RowVectorView_<ELT>                             T;\n     typedef RowVectorView_< typename CNT<ELT>::TNeg >       TNeg;\n     typedef VectorView_< typename CNT<ELT>::THerm >         THerm;\n+#endif\n public:\n     // Default construction is suppressed.\n     // Uses default destructor.\n \n+#ifndef SWIG\n     // Create a RowVectorView_ handle using a given helper rep. \n     explicit RowVectorView_(MatrixHelperRep<S>* hrep) : Base(hrep) {}\n+#endif\n \n     // Copy constructor is shallow. CAUTION: despite const argument, this preserves writability\n     // if it was present in the source. This is necessary to allow temporary views to be\n@@ -2193,9 +2219,11 @@ public:\n         Base::operator=(r); return *this;\n     }\n \n+#ifndef SWIG\n     // Ask for shallow copy    \n     explicit RowVectorView_(const MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { }\n     explicit RowVectorView_(MatrixHelper<S>&       h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { }\n+#endif\n     \n     RowVectorView_& operator=(const Base& b) { Base::operator=(b); return *this; }\n \n@@ -2227,6 +2255,7 @@ private:\n /// itself, although of course it will always have just one row.\n //  ----------------------------------------------------------------------------\n template <class ELT> class RowVector_ : public RowVectorBase<ELT> {\n+#ifndef SWIG\n     typedef typename CNT<ELT>::Scalar       S;\n     typedef typename CNT<ELT>::Number       Number;\n     typedef typename CNT<ELT>::StdNumber    StdNumber;\n@@ -2234,6 +2263,7 @@ template <class ELT> class RowVector_ : public RowVectorBase<ELT> {\n \n     typedef RowVectorBase<ELT>              Base;\n     typedef RowVectorBase<ENeg>             BaseNeg;\n+#endif\n public:\n     RowVector_() : Base() {}   // 1x0 reallocatable\n     // Uses default destructor.\n@@ -2241,9 +2271,11 @@ public:\n     // Copy constructor is deep.\n     RowVector_(const RowVector_& src) : Base(src) {}\n \n+#ifndef SWIG\n     // Implicit conversions.\n     RowVector_(const Base& src) : Base(src) {}    // e.g., RowVectorView\n     RowVector_(const BaseNeg& src) : Base(src) {}  \n+#endif\n \n     // Copy assignment is deep and can be reallocating if this RowVector\n     // has no View.\n@@ -2256,6 +2288,7 @@ public:\n     RowVector_(int n, const ELT* cppInitialValues) : Base(n, cppInitialValues) {}\n     RowVector_(int n, const ELT& initialValue)     : Base(n, initialValue) {}\n \n+#ifndef SWIG\n     /// Construct a Vector which uses borrowed space with assumed\n     /// element-to-element stride equal to the C++ element spacing.\n     /// Last parameter is a dummy to avoid overload conflicts when ELT=S;\n@@ -2268,6 +2301,7 @@ public:\n     /// dummy to avoid overload conflicts; pass it as "true".\n     RowVector_(int n, int stride, const S* data, bool) : Base(n, stride, data) {}\n     RowVector_(int n, int stride,       S* data, bool) : Base(n, stride, data) {}\n+#endif\n     \n     /// Convert a Row to a RowVector_.\n     template <int M>\n@@ -2294,6 +2328,7 @@ private:\n     // NO DATA MEMBERS ALLOWED\n };\n \n+#ifndef SWIG\n \n \n //  ------------------------ MatrixBase definitions ----------------------------\ndiff --git a/Bindings/common.i b/Bindings/common.i\nindex a43801965..1ffcfedca 100644\n--- a/Bindings/common.i\n+++ b/Bindings/common.i\n@@ -74,8 +74,11 @@\n %include <OpenSim/Common/ScaleSet.h>\n %include <OpenSim/Common/MarkerFrame.h>\n %include <OpenSim/Common/MarkerData.h>\n-%include <OpenSim/Common/TimeSeriesTable.h>\n \n+%include <OpenSim/Common/DataTable.h>\n+%include <OpenSim/Common/TimeSeriesTable.h>\n+%template(DataTableDouble)       OpenSim::DataTable_<double>;\n+%template(TimeSeriesTableDouble) OpenSim::TimeSeriesTable_<double>;\n \n \n \ndiff --git a/Bindings/simbody.i b/Bindings/simbody.i\nindex 4901f71c4..8f7e87c93 100644\n--- a/Bindings/simbody.i\n+++ b/Bindings/simbody.i\n@@ -27,10 +27,14 @@ namespace SimTK {\n // Vector and Matrix\n %include <SWIGSimTK/BigMatrix.h>\n namespace SimTK {\n-%template(MatrixBaseDouble) SimTK::MatrixBase<double>;\n-%template(VectorBaseDouble) SimTK::VectorBase<double>;\n-%template(Vector) SimTK::Vector_<double>;\n-%template(Matrix) SimTK::Matrix_<double>;\n+%template(MatrixBaseDouble)    SimTK::MatrixBase<double>;\n+%template(Matrix)              SimTK::Matrix_<double>;\n+%template(VectorBaseDouble)    SimTK::VectorBase<double>;\n+%template(VectorViewDouble)    SimTK::VectorView_<double>;\n+%template(Vector)              SimTK::Vector_<double>;\n+%template(RowVectorBaseDouble) SimTK::RowVectorBase<double>;\n+%template(RowVectorView)       SimTK::RowVectorView_<double>;\n+%template(RowVectorDouble)     SimTK::RowVector_<double>;\n }\n \n %include <SWIGSimTK/SpatialAlgebra.h>\ndiff --git a/OpenSim/Common/DataTable.h b/OpenSim/Common/DataTable.h\nindex 2e50418df..5feeb1646 100644\n--- a/OpenSim/Common/DataTable.h\n+++ b/OpenSim/Common/DataTable.h\n@@ -38,6 +38,10 @@ namespace OpenSim {\n class InvalidRow : public Exception {\n public:\n     using Exception::Exception;\n+    // InvalidRow(const std::string& file,\n+    //            size_t line,\n+    //            const std::string& func) :\n+    //     Exception(file, line, func) {}\n };\n \n class IncorrectNumColumns : public InvalidRow {\n@@ -123,16 +127,16 @@ This class is abstract and cannot be used directly. Create instances of\n DataTable_ instead. See DataTable_ for details on usage.                     */\n class AbstractDataTable {\n public:\n-    using TableMetaData       = ValueArrayDictionary;\n-    using DependentsMetaData  = ValueArrayDictionary;\n-    using IndependentMetaData = ValueArrayDictionary;\n+    typedef ValueArrayDictionary TableMetaData;\n+    typedef ValueArrayDictionary DependentsMetaData;\n+    typedef ValueArrayDictionary IndependentMetaData;\n \n     AbstractDataTable()                                      = default;\n     AbstractDataTable(const AbstractDataTable&)              = default;\n     AbstractDataTable(AbstractDataTable&&)                   = default;\n     AbstractDataTable& operator=(const AbstractDataTable&)   = default;\n     AbstractDataTable& operator=(AbstractDataTable&&)        = default;\n-    virtual std::unique_ptr<AbstractDataTable> clone() const = 0;\n+    virtual std::shared_ptr<AbstractDataTable> clone() const = 0;\n     virtual ~AbstractDataTable()                             = default;\n \n     /** Get metadata associated with the table.                               */\n@@ -210,9 +214,9 @@ whole can contain metadata.                                                   */\n template<typename ETX = double, typename ETY = SimTK::Real>\n class DataTable_ : public AbstractDataTable {\n public:\n-    using RowVector     = SimTK::RowVector_<ETY>;\n-    using RowVectorView = SimTK::RowVectorView_<ETY>;\n-    using VectorView    = SimTK::VectorView_<ETY>;\n+    typedef SimTK::RowVector_<ETY>     RowVector;\n+    typedef SimTK::RowVectorView_<ETY> RowVectorView;\n+    typedef SimTK::VectorView_<ETY>    VectorView;\n \n     DataTable_()                             = default;\n     DataTable_(const DataTable_&)            = default;\n@@ -221,8 +225,8 @@ public:\n     DataTable_& operator=(DataTable_&&)      = default;\n     ~DataTable_()                            = default;\n \n-    std::unique_ptr<AbstractDataTable> clone() const override {\n-        return std::unique_ptr<AbstractDataTable>{new DataTable_{*this}};\n+    std::shared_ptr<AbstractDataTable> clone() const override {\n+        return std::shared_ptr<AbstractDataTable>{new DataTable_{*this}};\n     }\n \n     /** Append row to the DataTable_.                                         \n@@ -404,7 +408,7 @@ protected:\n };  // DataTable_\n \n /** See DataTable_ for details on the interface.                              */\n-using DataTable = DataTable_<SimTK::Real>;\n+typedef DataTable_<SimTK::Real> DataTable;\n \n } // namespace OpenSim\n \ndiff --git a/OpenSim/Common/TimeSeriesTable.h b/OpenSim/Common/TimeSeriesTable.h\nindex d40212c75..142ce4b65 100644\n--- a/OpenSim/Common/TimeSeriesTable.h\n+++ b/OpenSim/Common/TimeSeriesTable.h\n@@ -98,7 +98,7 @@ type double. The time column is enforced to be strictly increasing.           */\n template<typename ETY = SimTK::Real>\n class TimeSeriesTable_ : public DataTable_<double, ETY> {\n public:\n-    using RowVector = SimTK::RowVector_<ETY>;\n+    typedef SimTK::RowVector_<ETY> RowVector;\n \n     TimeSeriesTable_()                                   = default;\n     TimeSeriesTable_(const TimeSeriesTable_&)            = default;\n@@ -151,7 +151,7 @@ protected:\n }; // TimeSeriesTable_\n \n /** See TimeSeriesTable_ for details on the interface.                        */\n-using TimeSeriesTable = TimeSeriesTable_<SimTK::Real>;\n+typedef TimeSeriesTable_<SimTK::Real> TimeSeriesTable;\n \n } // namespace OpenSim\n \n', 'commit_subject': 'Wrap all necessary classes to make wrapping of DataTable and TimeSeriesTable work. * Wrap RowVectorBase, RowVectorView, VectorBase, VectorView * Wrap DataTable, TimeSeriesTable.', 'repo_name': 'opensim-org/opensim-core', 'committer': {'name': 'Shrinidhi KL', 'email': 'd95ab70d9f94fe9e94415764048b7c0104d27b27@gmail.com', 'time_sec': '1456884954', 'tz_offset': '-480', 'date': {'seconds': '1456884954'}}, 'commit_tree': '5229c70f5e123dc3428152bf5c4713497fee2799', 'commit_message': 'Wrap all necessary classes to make wrapping of DataTable and TimeSeriesTable work.\n* Wrap RowVectorBase, RowVectorView, VectorBase, VectorView\n* Wrap DataTable, TimeSeriesTable.\n', 'language_name': 'Shell', 'license': 'apache-2.0', 'hunks': '@@ -98,7 +98,7 @@ type double. The time column is enforced to be strictly increasing.           */\n template<typename ETY = SimTK::Real>\n class TimeSeriesTable_ : public DataTable_<double, ETY> {\n public:\n-    using RowVector = SimTK::RowVector_<ETY>;\n+    typedef SimTK::RowVector_<ETY> RowVector;\n \n     TimeSeriesTable_()                                   = default;\n     TimeSeriesTable_(const TimeSeriesTable_&)            = default;\n@@ -151,7 +151,7 @@ protected:\n }; // TimeSeriesTable_\n \n /** See TimeSeriesTable_ for details on the interface.                        */\n-using TimeSeriesTable = TimeSeriesTable_<SimTK::Real>;\n+typedef TimeSeriesTable_<SimTK::Real> TimeSeriesTable;\n \n } // namespace OpenSim\n \n', 'addition_count': 2, 'deletion_count': 2, 'src_file': 'a/OpenSim/Common/TimeSeriesTable.h', 'tgt_file': 'b/OpenSim/Common/TimeSeriesTable.h', 'file_extension': '.h', 'before_file': '/* -------------------------------------------------------------------------- *\n *                            OpenSim:  TimeSeriesTable.h                     *\n * -------------------------------------------------------------------------- *\n * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *\n * See http://opensim.stanford.edu and the NOTICE file for more information.  *\n * OpenSim is developed at Stanford University and supported by the US        *\n * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *\n * through the Warrior Web program.                                           *\n *                                                                            *\n * Copyright (c) 2005-2017 Stanford University and the Authors                *\n * Authors:                                                                   *\n *                                                                            *\n * Licensed under the Apache License, Version 2.0 (the "License"); you may    *\n * not use this file except in compliance with the License. You may obtain a  *\n * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *\n *                                                                            *\n * Unless required by applicable law or agreed to in writing, software        *\n * distributed under the License is distributed on an "AS IS" BASIS,          *\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *\n * See the License for the specific language governing permissions and        *\n * limitations under the License.                                             *\n * -------------------------------------------------------------------------- */\n\n#ifndef OPENSIM_TIME_SERIES_DATA_TABLE_H_\n#define OPENSIM_TIME_SERIES_DATA_TABLE_H_\n\n/** \\file\nThis file defines the TimeSeriesTable_ class, which is used by OpenSim to \nprovide an in-memory container for data access and manipulation.              */\n\n#include "OpenSim/Common/DataTable.h"\n#include <SimTKsimbody.h>\n#include "Logger.h"\n\nnamespace OpenSim {\n\nclass InvalidTable : public Exception {\npublic:\n    using Exception::Exception;\n};\n\nclass TimeColumnNotIncreasing : public InvalidTable {\npublic:\n    TimeColumnNotIncreasing(const std::string& file, \n                            size_t line,\n                            const std::string& func) :\n        InvalidTable(file, line, func) {\n        std::string msg = "Time column is not strictly increasing";\n\n        addMessage(msg);\n    } \n};\n\nclass InvalidTimestamp : public InvalidRow {\npublic:\n#ifndef SWIG\n    using InvalidRow::InvalidRow;\n#endif\n};\n\nclass TimestampLessThanEqualToPrevious : public InvalidTimestamp {\npublic:\n    TimestampLessThanEqualToPrevious(const std::string& file,\n                                     size_t line,\n                                     const std::string& func,\n                                     size_t rowIndex,\n                                     double new_timestamp,\n                                     double prev_timestamp) :\n        InvalidTimestamp(file, line, func) {\n        std::string msg = "Timestamp at row " + std::to_string(rowIndex);\n        msg += " with value " + std::to_string(new_timestamp);\n        msg += " is less-than/equal to timestamp at row ";\n        msg += std::to_string(rowIndex - 1) + " with value ";\n        msg += std::to_string(prev_timestamp);\n\n        addMessage(msg);\n    }\n};\n\nclass TimestampGreaterThanEqualToNext : public InvalidTimestamp {\npublic:\n    TimestampGreaterThanEqualToNext(const std::string& file,\n                                    size_t line,\n                                    const std::string& func,\n                                    size_t rowIndex,\n                                    double new_timestamp,\n                                    double next_timestamp) :\n        InvalidTimestamp(file, line, func) {\n        std::string msg = "Timestamp at row " + std::to_string(rowIndex);\n        msg += " with value " + std::to_string(new_timestamp);\n        msg += " is greater-than/equal to timestamp at row "; \n        msg += std::to_string(rowIndex + 1) + " with value "; \n        msg += std::to_string(next_timestamp);\n\n        addMessage(msg);\n    }\n};\ntemplate<typename ETY = SimTK::Real>\nclass TimeSeriesTable_ : public DataTable_<double, ETY> {\npublic:\n    using RowVector = SimTK::RowVector_<ETY>;\n\n    TimeSeriesTable_()                                   = default;\n    TimeSeriesTable_(const TimeSeriesTable_&)            = default;\n                   const double min,\n                   const double max) :\n        Exception(file, line, func) {\n        std::string msg = "Time " + std::to_string(time) + \n            " is out of time range [" + std::to_string(min) +\n            ", " + std::to_string(max) + "]";\n\n        addMessage(msg);\n    }\n};\n\nclass InvalidTimeRange : public Exception {\npublic:\n    InvalidTimeRange(const std::string& file,\n                     size_t line,\n                     const std::string& func,\n                     const double begTime,\n                     const double endTime) :\n        Exception(file, line, func) {\n        std::string msg = " Invalid time range: initial time " + \n            std::to_string(begTime)  + " >= final time = " +\n            std::to_string(endTime);\n\n        addMessage(msg);\n    }\n};\n\n/** TimeSeriesTable_ is a DataTable_ where the independent column is time of \ntype double. The time column is enforced to be strictly increasing.           */\ntemplate<typename ETY = SimTK::Real>\nclass TimeSeriesTable_ : public DataTable_<double, ETY> {\npublic:\n    typedef SimTK::RowVector_<ETY>     RowVector;\n    typedef SimTK::RowVectorView_<ETY> RowVectorView;\n\n    TimeSeriesTable_()                                   = default;\n    TimeSeriesTable_(const TimeSeriesTable_&)            = default;\n    TimeSeriesTable_(TimeSeriesTable_&&)                 = default;\n    TimeSeriesTable_& operator=(const TimeSeriesTable_&) = default;\n    TimeSeriesTable_& operator=(TimeSeriesTable_&&)      = default;\n    ~TimeSeriesTable_()                                  = default;\n\n    /** Convenience constructor to efficiently populate a time series table\n    from available data. This is primarily useful for constructing with large\n    data read in from file without having to reallocate and copy memory.*/\n    TimeSeriesTable_(const std::vector<double>& indVec,\n}; // TimeSeriesTable_\n\n/** See TimeSeriesTable_ for details on the interface.                        */\nusing TimeSeriesTable = TimeSeriesTable_<SimTK::Real>;\n\n} // namespace OpenSim\n\n            // because base classes cannot properly invoke virtual functions.\n            this->validateDependentsMetaData();\n            for (size_t i = 0; i < indVec.size(); ++i) {\n                this->validateRow(i, indVec[i], depData.row(int(i)));\n            }\n        }\n        catch (std::exception&) {\n            // wipe out the data loaded if any\n            this->_indData.clear();\n            this->_depData.clear();\n            this->removeDependentsMetaDataForKey("labels");\n            throw;\n        }\n    }\n\n    /** Construct a table with only the independent (time) column and 0\n    dependent columns. This constructor is useful if you want to populate the\n    table by appending columns rather than by appending rows.                 */\n    TimeSeriesTable_(const std::vector<double>& indVec) :\n            DataTable_<double, ETY>(indVec) {\n        try {\n            // Perform the validation of the data of this TimeSeriesTable.\n            // validateDependentsMetaData() invoked by the DataTable_\n            // constructor via setColumnLabels(), but we invoke it again\n            // because base classes cannot properly invoke virtual functions.\n            this->validateDependentsMetaData();\n            for (size_t i = 0; i < indVec.size(); ++i) {\n                this->validateRow(i, indVec[i], this->_depData.row(int(i)));\n            }\n        }\n        catch (std::exception&) {\n            // wipe out the data loaded if any\n            this->_indData.clear();\n            this->_depData.clear(); // should be empty\n            this->removeDependentsMetaDataForKey("labels"); // should be empty\n            throw;\n        }\n\n    }\n\n#ifndef SWIG\n    using DataTable_<double, ETY>::DataTable_;\n    using DataTable_<double, ETY>::operator=;\n    /** Flatten the columns of this table to create a TimeSeriesTable_<double>.\n    See documentation of DataTable_::flatten() for details.                   */\n    using DataTable_<double, ETY>::flatten;\n    /** Pack the columns of this table (which should be TimeSeriesTable_<double>\n    ) to create a TimeSeriesTable_<SimTK::Vec3>, TimeSeriesTable_<SimTK::Vec6>,\n    TimeSeriesTable_<SimTK::UnitVec3> and so on. See documentation for \n    DataTable_::pack().                                                       */\n    using DataTable_<double, ETY>::pack;\n#endif    \n    \n    /** Construct a TimeSeriesTable_ from a DataTable_.                       \n\n    \\throws InvalidTable If the input table\'s independent column is not strictly\n                         increasing.                                          */\n    TimeSeriesTable_(const DataTable_<double, ETY>& datatable) : \n        DataTable_<double, ETY>(datatable) {\n        using DT = DataTable_<double, ETY>;\n\n        OPENSIM_THROW_IF(!std::is_sorted(DT::_indData.cbegin(), \n                                         DT::_indData.cend()) ||\n                         std::adjacent_find(DT::_indData.cbegin(), \n                                            DT::_indData.cend()) != \n                         DT::_indData.cend(),\n                         TimeColumnNotIncreasing);\n    }\n\n    /** Construct TimeSeriesTable_ from a file.\n\n    \\param filename Name of the file.\n\n    \\throws InvalidArgument If the input file contains more than one table.\n    \\throws InvalidArgument If the input file contains a table that is not of\n                            this TimeSeriesTable_ type.                       */\n    TimeSeriesTable_(const std::string& filename) : \n        TimeSeriesTable_{filename, ""} {}\n\n    /** Construct TimeSeriesTable_ from a file.\n\n    \\param filename Name of the file.\n    \\param tablename Name of the table in the file to construct this \n                     TimeSeriesTable_ from. For example, a c3d file contains \n                     tables named \'markers\' and \'forces\'.\n\n    \\throws InvalidArgument If the input file contains more than one table and \n                            tablename was not specified.\n    \\throws InvalidArgument If the input file contains a table that is not of\n                            this TimeSeriesTable_ type.                       */\n    TimeSeriesTable_(const std::string& filename, \n                     const std::string& tablename) {\n        auto absTables = FileAdapter::createAdapterFromExtension(filename)->read(filename);\n\n        OPENSIM_THROW_IF(absTables.size() > 1 && tablename.empty(),\n                         InvalidArgument,\n                         "File \'" + filename + \n                         "\' contains more than one table and tablename not "\n                         "specified.");\n\n        AbstractDataTable* absTable{};\n        if(tablename.empty()) {\n            absTable = (absTables.cbegin()->second).get();\n        } else {\n            try {\n                absTable = absTables.at(tablename).get();\n            } catch (const std::out_of_range&) {\n                OPENSIM_THROW(InvalidArgument,\n                              "File \'" + filename + "\' contains no table named "\n                              "\'"+ tablename + "\'.");\n            }\n        }\n        auto table = dynamic_cast<TimeSeriesTable_*>(absTable);\n        OPENSIM_THROW_IF(table == nullptr,\n                         InvalidArgument,\n                         "DataTable cannot be created from file \'" + filename +\n                         "\'. Type mismatch.");\n\n        *this = std::move(*table);\n    }\n\n    /** Get index of row whose time is nearest/closest to the given value.\n\n    \\param time Value to search for.\n    \\param restrictToTimeRange  When true -- Exception is thrown if the given\n                                value is out-of-range of the time column. A value\n                                within SimTK::SignifcantReal of a time column\n                                bound is considered to be equal to the bound.\n                                When false -- If the given value is less than or\n                                equal to the first value in the time column, the\n                                index returned is of the first row. If the given\n                                value is greater than or equal to the last value\n                                in the time column, the index of the last row is\n                                returned. Defaults to \'true\'.\n\n    \\throws TimeOutOfRange If the given value is out-of-range of time column.\n    \\throws EmptyTable If the table is empty.                                 */\n    size_t getNearestRowIndexForTime(const double time,\n                                     const bool restrictToTimeRange = true) const {\n        using DT = DataTable_<double, ETY>;\n        const auto& timeCol = DT::getIndependentColumn();\n        OPENSIM_THROW_IF(timeCol.size() == 0,\n            EmptyTable);\n        const SimTK::Real eps = SimTK::SignificantReal;\n        OPENSIM_THROW_IF(restrictToTimeRange &&\n            ((time < timeCol.front() - eps) ||\n            (time > timeCol.back() + eps)),\n            TimeOutOfRange,\n            time, timeCol.front(), timeCol.back());\n\n        auto iter = std::lower_bound(timeCol.begin(), timeCol.end(), time);\n        if (iter == timeCol.end())\n            return timeCol.size() - 1;\n        if (iter == timeCol.begin())\n            return 0;\n        if ((*iter - time) <= (time - *std::prev(iter)))\n            return std::distance(timeCol.begin(), iter);\n        else\n            return std::distance(timeCol.begin(), std::prev(iter));\n    }\n    /** Get index of row whose time is first to be higher than the given value.\n\n     \\param time Value to search for.\n     */\n    size_t getRowIndexAfterTime(\n            const double& time) const {\n        size_t candidate = getNearestRowIndexForTime(time, false);\n        using DT = DataTable_<double, ETY>;\n        const auto& timeCol = DT::getIndependentColumn();\n        const SimTK::Real eps = SimTK::SignificantReal;\n        // increment if less than time passed in\n        if (timeCol[candidate] < time-eps) \n            candidate++;\n        OPENSIM_THROW_IF(candidate > timeCol.size() - 1,\n                    TimeOutOfRange, time, timeCol.front(), timeCol.back());\n        return candidate;\n    }\n    /** Get index of row whose time is the largest time less than the given value.\n\n     \\param time Value to search for.\n     */\n    size_t getRowIndexBeforeTime(const double& time) const {\n        size_t candidate = getNearestRowIndexForTime(time, false);\n        using DT = DataTable_<double, ETY>;\n        const auto& timeCol = DT::getIndependentColumn();\n        const SimTK::Real eps = SimTK::SignificantReal;\n        // increment if less than time passed in\n        if (timeCol[candidate] > time+eps) candidate--;\n        OPENSIM_THROW_IF(candidate < 0, TimeOutOfRange, time,\n                timeCol.front(), timeCol.back());\n        return candidate;\n    }\n\n    /** Get row whose time column is nearest/closest to the given value. \n\n    \\param time Value to search for. \n    \\param restrictToTimeRange When true -- Exception is thrown if the given \n                               value is out-of-range of the time column. \n                               When false -- If the given value is less than or \n                               equal to the first value in the time column, the\n                               row returned is the first row. If the given value\n                               is greater than or equal to the last value in the\n                               time column, the row returned is the last row. \n                               This operation only returns existing rows and \n                               does not perform any interpolation. Defaults to\n                               \'true\'.\n\n    \\throws TimeOutOfRange If the given value is out-of-range of time column.\n    \\throws EmptyTable If the table is empty.                                 */\n    RowVectorView\n    getNearestRow(const double& time,\n                  const bool restrictToTimeRange = true) const {\n        using DT = DataTable_<double, ETY>;\n        return DT::getRowAtIndex( \n            getNearestRowIndexForTime(time, restrictToTimeRange) );\n    }\n\n    /** Get writable reference to row whose time column is nearest/closest to \n    the given value. \n\n    \\param time Value to search for. \n    \\param restrictToTimeRange When true -- Exception is thrown if the given \n                               value is out-of-range of the time column. \n                               When false -- If the given value is less than or \n                               equal to the first value in the time column, the\n                               row returned is the first row. If the given value\n                               is greater than or equal to the last value in the\n                               time column, the row returned is the last row. \n                               This operation only returns existing rows and \n                               does not perform any interpolation. Defaults to\n                               \'true\'.\n\n    \\throws TimeOutOfRange If the given value is out-of-range of time column.\n    \\throws EmptyTable If the table is empty.                                 */\n    RowVectorView\n    updNearestRow(const double& time,\n                  const bool restrictToTimeRange = true) {\n        using DT = DataTable_<double, ETY>;\n        return DT::updRowAtIndex(\n            getNearestRowIndexForTime(time, restrictToTimeRange));\n    }\n\n    /** Compute the average row in the time range (inclusive) given. This\n    operation does not modify the table. It just computes and returns an average\n    row. \n\n    \\throws InvalidTimeRange If beginTime is greater than or equal to endTime.\n    \\throws TimeOutOfRange If beginTime or endTime is out of range of time \n                           column.                                            */\n    RowVector averageRow(const double& beginTime, const double& endTime) const {\n        using DT = DataTable_<double, ETY>;\n        OPENSIM_THROW_IF(endTime <= beginTime,\n                         InvalidTimeRange,\n                         beginTime, endTime);\n        const auto& timeCol = DT::getIndependentColumn();\n        OPENSIM_THROW_IF(beginTime < timeCol.front() ||\n                         beginTime > timeCol.back(),\n                         TimeOutOfRange,\n                         beginTime, timeCol.front(), timeCol.back(),);\n        OPENSIM_THROW_IF(endTime < timeCol.front() ||\n                         endTime > timeCol.back(),\n                         TimeOutOfRange,\n                         endTime, timeCol.front(), timeCol.back());\n\n        std::vector<double> comps(DT::numComponentsPerElement(), 0);\n        RowVector row{static_cast<int>(DT::getNumColumns()),\n                      DT::makeElement(comps.begin(), comps.end())};\n        unsigned numRowsInRange{};\n        for(unsigned r = 0; r < DT::getNumRows(); ++r) {\n            if(timeCol[r] >= beginTime && timeCol[r] <= endTime) {\n                row += DT::getRowAtIndex(r);\n                ++numRowsInRange;\n            }\n        }\n        row /= numRowsInRange;\n\n        return row;\n    }\n    /**\n     * Trim TimeSeriesTable to rows that have times that lies between \n     * newStartTime, newFinalTime. The trimming is done in place, no copy is made. \n     * Uses getRowIndexAfterTime to locate first row and\n     * getNearestRowIndexForTime method to locate last row.\n     */\n    void trim(const double& newStartTime, const double& newFinalTime) {\n        OPENSIM_THROW_IF(newFinalTime < newStartTime, EmptyTable);\n        const auto& timeCol = this->getIndependentColumn();\n        size_t start_index = 0;\n        size_t last_index = this->getNumRows() - 1;\n        // Avoid throwing exception if newStartTime is less than first time\n        // or newFinalTime is greater than last value in table\n        start_index = this->getRowIndexAfterTime(newStartTime);\n        last_index = this->getRowIndexBeforeTime(newFinalTime);\n        // Make sure last_index >= start_index before attempting to trim\n        OPENSIM_THROW_IF(last_index < start_index, EmptyTable);\n        // do the actual trimming based on index instead of time.\n        trimToIndices(start_index, last_index);\n        // If resulting table is empty, throw\n        if (this->getNumRows()==0)\n            log_warn("Trimming resulted in an empty table.");\n    }\n    /**\n     * trim TimeSeriesTable, keeping rows at newStartTime to the end.\n     */\n    void trimFrom(const double& newStartTime) { \n        this->trim(newStartTime, this->getIndependentColumn().back());\n    }\n    /**\n     * trim TimeSeriesTable, keeping rows up to newFinalTime\n     */\n    void trimTo(const double& newFinalTime) {\n        this->trim(this->getIndependentColumn().front(), newFinalTime);\n    }\nprotected:\n    /** Validate the given row. \n\n    \\throws InvalidRow If the timestamp for the row breaks strictly increasing\n                       property of the independent column.                    */\n    void validateRow(size_t rowIndex,\n                     const double& time, \n                     const RowVector& row) const override {\n        using DT = DataTable_<double, ETY>;\n\n        if(DT::_indData.empty())\n            return;\n\n        if(rowIndex > 0) {\n            OPENSIM_THROW_IF(DT::_indData[rowIndex - 1] >= time,\n                             TimestampLessThanEqualToPrevious, rowIndex, time, \n                             DT::_indData[rowIndex - 1]);\n        }\n\n        if(rowIndex < DT::_indData.size() - 1) {\n            OPENSIM_THROW_IF(DT::_indData[rowIndex + 1] <= time,\n                             TimestampGreaterThanEqualToNext, rowIndex, time, \n                             DT::_indData[rowIndex + 1]);\n        }\n    }\n    /** trim table to rows between start_index and last_index inclusively\n     */\n    void trimToIndices(const size_t& start_index, const size_t& last_index) {\n        // This uses the rather invasive but efficient mechanism to copy a\n        // block of the underlying Matrix.\n        // Side effect may include that headers/metaData may be left stale.\n        // Alternatively we can create a new TimeSeriesTable and copy contents\n        // one row at a time but that\'s rather overkill\n        SimTK::Matrix_<ETY> matrixBlock = this->updMatrix()((int)start_index, 0,\n                (int)(last_index - start_index + 1),\n                (int)this->getNumColumns());\n        this->updMatrix() = matrixBlock;\n        std::vector<double> newIndependentVector = std::vector<double>(\n                this->getIndependentColumn().begin() + start_index,\n                this->getIndependentColumn().begin() + last_index + 1);\n        this->_indData = newIndependentVector;\n    }\n\n    friend class TableUtilities;\n\n}; // TimeSeriesTable_\n\n/** See TimeSeriesTable_ for details on the interface.                        */\ntypedef TimeSeriesTable_<SimTK::Real> TimeSeriesTable;\n\n/** See TimeSeriesTable_ for details on the interface.                        */\ntypedef TimeSeriesTable_<SimTK::Vec3> TimeSeriesTableVec3;\n\n/** See TimeSeriesTable_ for details on the interface.                        */\ntypedef TimeSeriesTable_<SimTK::Quaternion> TimeSeriesTableQuaternion;\n\n/** See TimeSeriesTable_ for details on the interface.                        */\ntypedef TimeSeriesTable_<SimTK::Rotation> TimeSeriesTableRotation;\n\n} // namespace OpenSim\n\n#endif // OPENSIM_TIME_SERIES_DATA_TABLE_H_\n', 'message': 'Wrap all necessary classes to make wrapping of DataTable and TimeSeriesTable work.\n* Wrap RowVectorBase, RowVectorView, VectorBase, VectorView\n* Wrap DataTable, TimeSeriesTable.\n', 'author_name': 'Shrinidhi KL', 'lang': 'h'}