OpenWalnut  1.4.0
WDataSetTimeSeries.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WDATASETTIMESERIES_H
00026 #define WDATASETTIMESERIES_H
00027 
00028 #include <limits>
00029 #include <string>
00030 #include <utility>
00031 #include <vector>
00032 
00033 #include <boost/enable_shared_from_this.hpp>
00034 #include <boost/shared_ptr.hpp>
00035 
00036 #include "../common/WLimits.h"
00037 #include "../common/WProperties.h"
00038 #include "../common/WTransferable.h"
00039 #include "WDataSetScalar.h"
00040 
00041 
00042 //! forward declaration
00043 class WDataSetTimeSeriesTest;
00044 
00045 /**
00046  * A dataset that stores a time series.
00047  *
00048  * \note Only works for scalar datasets at the moment!
00049  * \note this is only a temporary solution
00050  */
00051 class WDataSetTimeSeries : public WDataSet
00052 {
00053     //! the test is a friend
00054     friend class WDataSetTimeSeriesTest;
00055 
00056     //! a conveniance typedef
00057     typedef WDataSetTimeSeries This;
00058 
00059     //! a time slice
00060     typedef std::pair< boost::shared_ptr< WDataSetScalar const >, float > TimeSlice;
00061 
00062 public:
00063     /**
00064      * Returns a name.
00065      *
00066      * \return A name.
00067      */
00068     std::string const getName() const;
00069 
00070     /**
00071      * Returns a description.
00072      *
00073      * \return A description.
00074      */
00075     std::string const getDescription() const;
00076 
00077     /**
00078      * Returns a prototype instantiated with the true type of the deriving class.
00079      *
00080      * \return the prototype.
00081      */
00082     static boost::shared_ptr< WPrototyped > getPrototype();
00083 
00084     /**
00085      * Construct time series from multiple 3D datasets. They do not have to be sorted by time.
00086      *
00087      * \param datasets A list of datasets to add.
00088      * \param times A list of times for the datasets.
00089      */
00090     WDataSetTimeSeries( std::vector< boost::shared_ptr< WDataSetScalar const > > datasets, std::vector< float > times );
00091 
00092     /**
00093      * Destructor.
00094      */
00095     virtual ~WDataSetTimeSeries();
00096 
00097     /**
00098      * Get the first point of time in the time series.
00099      *
00100      * \return The first point of time.
00101      */
00102     inline float getMinTime() const;
00103 
00104     /**
00105      * Get the last point of time in the time series.
00106      *
00107      * \return The last point of time.
00108      */
00109     inline float getMaxTime() const;
00110 
00111     /**
00112      * Check if there exists a predefined dataset at the given point in time, i.e.
00113      * no interpolation has to be done to access data at that point in time.
00114      *
00115      * If the time is not in the represented interval [getMinTime(),getMaxTime()],
00116      * it will return false.
00117      *
00118      * \param time The point in time to test.
00119      * \return true, iff the time is one of those that were given in the constructor.
00120      */
00121     bool isTimeSlice( float time ) const;
00122 
00123     /**
00124      * Find the nearest time slice for a given time. If there are two
00125      * nearest time slices, the smaller one will be returned.
00126      *
00127      * \param time The time.
00128      * \return The nearest time slice.
00129      */
00130     float findNearestTimeSlice( float time ) const;
00131 
00132     /**
00133      * Get a pointer to the dataset at a given time or a NULL-pointer, if there
00134      * was no dataset given for that point in time.
00135      *
00136      * \note You need to provide the exact time.
00137      *
00138      * \param time The time.
00139      * \return A pointer to the appropriate dataset or a NULL-pointer.
00140      */
00141     boost::shared_ptr< WDataSetScalar const > getDataSetPtrAtTimeSlice( float time ) const;
00142 
00143     /**
00144      * Calculates a new dataset with values interpolated between the two nearest
00145      * time slices. if the time is not in the interval [getMinTime(),getMaxTime()],
00146      * a NULL-pointer will be returned.
00147      *
00148      * \param time The time.
00149      * \param name The name of the new dataset.
00150      * \return A new interpolated dataset.
00151      */
00152     boost::shared_ptr< WDataSetScalar const > calcDataSetAtTime( float time, std::string const& name ) const;
00153 
00154     /**
00155      * Interpolate a value for a single point in space and time.
00156      *
00157      * \param pos The spatial location.
00158      * \param time The temporal location.
00159      * \param[out] success A flag indicating if the position was in the dataset.
00160      * \return The value at the given location.
00161      */
00162     template< typename Data_T >
00163     Data_T interpolate( WVector3d const& pos, float time, bool* success ) const;
00164 
00165     /**
00166      * Get the smallest value in all datasets.
00167      *
00168      * \return The smallest value.
00169      */
00170     double getMinValue();
00171 
00172     /**
00173      * Get the largest value in all datasets.
00174      *
00175      * \return The largest value.
00176      */
00177     double getMaxValue();
00178 
00179 private:
00180     /**
00181      * Find the largest time slice position that is smaller than or equal to time,
00182      * or return -inf, if there is no such time slice.
00183      *
00184      * \param time The time.
00185      * \return The largest time slice that is smaller than or equal to time or -inf.
00186      */
00187     float getLBTimeSlice( float time ) const;
00188 
00189     /**
00190      * Find the smallest time slice position that is larger than time, or return
00191      * inf, if there is no such time slice.
00192      *
00193      * \param time The time.
00194      * \return The largest time slice that is smaller than time or inf.
00195      */
00196     float getUBTimeSlice( float time ) const;
00197 
00198     /**
00199      * Interpolate a valueset from two neighboring slices.
00200      *
00201      * \param lb Time of one slice.
00202      * \param ub Time of the other slice.
00203      * \param time The actual time of the interpolated slice.
00204      * \return A valueset with linearly interpolated values.
00205      */
00206     template< typename Data_T >
00207     boost::shared_ptr< WValueSetBase > calcInterpolatedValueSet( float lb, float ub, float time ) const;
00208 
00209     /**
00210      * Standard constructor.
00211      */
00212     WDataSetTimeSeries();
00213 
00214     /**
00215      * A compare functor for time slices.
00216      */
00217     class TimeSliceCompare
00218     {
00219     public:
00220         /**
00221          * Compares the time of two time slices.
00222          *
00223          * \param t0 The first time slice.
00224          * \param t1 The other time slice.
00225          * \return true, iff the time of the first slice is smaller than that of the other one.
00226          */
00227         bool operator() ( TimeSlice const& t0, TimeSlice const& t1 );
00228 
00229         /**
00230          * Compares the time of two time slices.
00231          *
00232          * \param t0 The first time slice.
00233          * \param t1 The other time slice.
00234          * \return true, iff the time of the first slice is smaller than that of the other one.
00235          */
00236         bool operator() ( float const& t0, TimeSlice const& t1 );
00237 
00238         /**
00239          * Compares the time of two time slices.
00240          *
00241          * \param t0 The first time slice.
00242          * \param t1 The other time slice.
00243          * \return true, iff the time of the first slice is smaller than that of the other one.
00244          */
00245         bool operator() ( TimeSlice const& t0, float const& t1 );
00246     };
00247 
00248     //! the datasets that compose the time series
00249     std::vector< TimeSlice > m_dataSets;
00250 
00251     //! The prototype as singleton.
00252     static boost::shared_ptr< WPrototyped > m_prototype;
00253 
00254     //! the smallest value
00255     double m_minValue;
00256 
00257     //! the largest value
00258     double m_maxValue;
00259 };
00260 
00261 template< typename Data_T >
00262 Data_T WDataSetTimeSeries::interpolate( WVector3d const& pos, float time, bool* success ) const
00263 {
00264     static const float inf = std::numeric_limits< float >::infinity();
00265     WAssert( success, "" );
00266     WAssert( !wlimits::isNaN( length( pos ) ), "" );
00267     WAssert( !wlimits::isNaN( time ), "" );
00268     if( time < getMinTime() || time > getMaxTime() )
00269     {
00270         *success = false;
00271         throw WException( std::string( "The provided time is not in the interval of this time series." ) );
00272     }
00273     float lb = getLBTimeSlice( time );
00274     float ub = getUBTimeSlice( time );
00275     if( lb == time || ub == time )
00276     {
00277         boost::shared_ptr< WDataSetScalar const > ds = getDataSetPtrAtTimeSlice( time );
00278         return static_cast< Data_T >( const_cast< WDataSetScalar& >( *ds ).interpolate( pos, success ) );
00279     }
00280     WAssert( lb != -inf && ub != inf, "" );
00281     boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
00282     boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
00283     WAssert( f && g, "" );
00284     float ml = ( ub - time ) / ( ub - lb );
00285     float mu = ( time - lb ) / ( ub - lb );
00286     return static_cast< Data_T >( ml * const_cast< WDataSetScalar& >( *f ).interpolate( pos, success )
00287                                 + mu * const_cast< WDataSetScalar& >( *g ).interpolate( pos, success ) );
00288 }
00289 
00290 template< typename Data_T >
00291 boost::shared_ptr< WValueSetBase > WDataSetTimeSeries::calcInterpolatedValueSet( float lb, float ub, float time ) const
00292 {
00293     static const float inf = std::numeric_limits< float >::infinity();
00294     WAssert( lb != -inf && ub != inf, "" );
00295     boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
00296     boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
00297     WAssert( f && g, "" );
00298     boost::shared_ptr< WValueSet< Data_T > > vf = boost::dynamic_pointer_cast< WValueSet< Data_T > >( f->getValueSet() );
00299     boost::shared_ptr< WValueSet< Data_T > > vg = boost::dynamic_pointer_cast< WValueSet< Data_T > >( g->getValueSet() );
00300     WAssert( vf && vg, "" );
00301     boost::shared_ptr< std::vector< Data_T > > values( new std::vector< Data_T >( vf->size() ) );
00302     float ml = ( ub - time ) / ( ub - lb );
00303     float mu = ( time - lb ) / ( ub - lb );
00304     for( std::size_t k = 0; k < values->size(); ++k )
00305     {
00306         ( *values )[ k ] = ml * vf->getScalar( k ) + mu * vg->getScalar( k );
00307     }
00308     return boost::shared_ptr< WValueSetBase >( new WValueSet< Data_T >( 0, 1, values, DataType< Data_T >::type ) );
00309 }
00310 
00311 float WDataSetTimeSeries::getMinTime() const
00312 {
00313     return m_dataSets.front().second;
00314 }
00315 
00316 float WDataSetTimeSeries::getMaxTime() const
00317 {
00318     return m_dataSets.back().second;
00319 }
00320 
00321 #endif  // WDATASETTIMESERIES_H