OpenWalnut
1.4.0
|
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