OpenWalnut  1.4.0
WDataSetTimeSeries.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WDATASETTIMESERIES_H
26 #define WDATASETTIMESERIES_H
27 
28 #include <limits>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 #include <boost/enable_shared_from_this.hpp>
34 #include <boost/shared_ptr.hpp>
35 
36 #include "../common/WLimits.h"
37 #include "../common/WProperties.h"
38 #include "../common/WTransferable.h"
39 #include "WDataSetScalar.h"
40 
41 
42 //! forward declaration
44 
45 /**
46  * A dataset that stores a time series.
47  *
48  * \note Only works for scalar datasets at the moment!
49  * \note this is only a temporary solution
50  */
52 {
53  //! the test is a friend
54  friend class WDataSetTimeSeriesTest;
55 
56  //! a conveniance typedef
58 
59  //! a time slice
60  typedef std::pair< boost::shared_ptr< WDataSetScalar const >, float > TimeSlice;
61 
62 public:
63  /**
64  * Returns a name.
65  *
66  * \return A name.
67  */
68  std::string const getName() const;
69 
70  /**
71  * Returns a description.
72  *
73  * \return A description.
74  */
75  std::string const getDescription() const;
76 
77  /**
78  * Returns a prototype instantiated with the true type of the deriving class.
79  *
80  * \return the prototype.
81  */
82  static boost::shared_ptr< WPrototyped > getPrototype();
83 
84  /**
85  * Construct time series from multiple 3D datasets. They do not have to be sorted by time.
86  *
87  * \param datasets A list of datasets to add.
88  * \param times A list of times for the datasets.
89  */
90  WDataSetTimeSeries( std::vector< boost::shared_ptr< WDataSetScalar const > > datasets, std::vector< float > times );
91 
92  /**
93  * Destructor.
94  */
95  virtual ~WDataSetTimeSeries();
96 
97  /**
98  * Get the first point of time in the time series.
99  *
100  * \return The first point of time.
101  */
102  inline float getMinTime() const;
103 
104  /**
105  * Get the last point of time in the time series.
106  *
107  * \return The last point of time.
108  */
109  inline float getMaxTime() const;
110 
111  /**
112  * Check if there exists a predefined dataset at the given point in time, i.e.
113  * no interpolation has to be done to access data at that point in time.
114  *
115  * If the time is not in the represented interval [getMinTime(),getMaxTime()],
116  * it will return false.
117  *
118  * \param time The point in time to test.
119  * \return true, iff the time is one of those that were given in the constructor.
120  */
121  bool isTimeSlice( float time ) const;
122 
123  /**
124  * Find the nearest time slice for a given time. If there are two
125  * nearest time slices, the smaller one will be returned.
126  *
127  * \param time The time.
128  * \return The nearest time slice.
129  */
130  float findNearestTimeSlice( float time ) const;
131 
132  /**
133  * Get a pointer to the dataset at a given time or a NULL-pointer, if there
134  * was no dataset given for that point in time.
135  *
136  * \note You need to provide the exact time.
137  *
138  * \param time The time.
139  * \return A pointer to the appropriate dataset or a NULL-pointer.
140  */
141  boost::shared_ptr< WDataSetScalar const > getDataSetPtrAtTimeSlice( float time ) const;
142 
143  /**
144  * Calculates a new dataset with values interpolated between the two nearest
145  * time slices. if the time is not in the interval [getMinTime(),getMaxTime()],
146  * a NULL-pointer will be returned.
147  *
148  * \param time The time.
149  * \param name The name of the new dataset.
150  * \return A new interpolated dataset.
151  */
152  boost::shared_ptr< WDataSetScalar const > calcDataSetAtTime( float time, std::string const& name ) const;
153 
154  /**
155  * Interpolate a value for a single point in space and time.
156  *
157  * \param pos The spatial location.
158  * \param time The temporal location.
159  * \param[out] success A flag indicating if the position was in the dataset.
160  * \return The value at the given location.
161  */
162  template< typename Data_T >
163  Data_T interpolate( WVector3d const& pos, float time, bool* success ) const;
164 
165  /**
166  * Get the smallest value in all datasets.
167  *
168  * \return The smallest value.
169  */
170  double getMinValue();
171 
172  /**
173  * Get the largest value in all datasets.
174  *
175  * \return The largest value.
176  */
177  double getMaxValue();
178 
179 private:
180  /**
181  * Find the largest time slice position that is smaller than or equal to time,
182  * or return -inf, if there is no such time slice.
183  *
184  * \param time The time.
185  * \return The largest time slice that is smaller than or equal to time or -inf.
186  */
187  float getLBTimeSlice( float time ) const;
188 
189  /**
190  * Find the smallest time slice position that is larger than time, or return
191  * inf, if there is no such time slice.
192  *
193  * \param time The time.
194  * \return The largest time slice that is smaller than time or inf.
195  */
196  float getUBTimeSlice( float time ) const;
197 
198  /**
199  * Interpolate a valueset from two neighboring slices.
200  *
201  * \param lb Time of one slice.
202  * \param ub Time of the other slice.
203  * \param time The actual time of the interpolated slice.
204  * \return A valueset with linearly interpolated values.
205  */
206  template< typename Data_T >
207  boost::shared_ptr< WValueSetBase > calcInterpolatedValueSet( float lb, float ub, float time ) const;
208 
209  /**
210  * Standard constructor.
211  */
213 
214  /**
215  * A compare functor for time slices.
216  */
218  {
219  public:
220  /**
221  * Compares the time of two time slices.
222  *
223  * \param t0 The first time slice.
224  * \param t1 The other time slice.
225  * \return true, iff the time of the first slice is smaller than that of the other one.
226  */
227  bool operator() ( TimeSlice const& t0, TimeSlice const& t1 );
228 
229  /**
230  * Compares the time of two time slices.
231  *
232  * \param t0 The first time slice.
233  * \param t1 The other time slice.
234  * \return true, iff the time of the first slice is smaller than that of the other one.
235  */
236  bool operator() ( float const& t0, TimeSlice const& t1 );
237 
238  /**
239  * Compares the time of two time slices.
240  *
241  * \param t0 The first time slice.
242  * \param t1 The other time slice.
243  * \return true, iff the time of the first slice is smaller than that of the other one.
244  */
245  bool operator() ( TimeSlice const& t0, float const& t1 );
246  };
247 
248  //! the datasets that compose the time series
249  std::vector< TimeSlice > m_dataSets;
250 
251  //! The prototype as singleton.
252  static boost::shared_ptr< WPrototyped > m_prototype;
253 
254  //! the smallest value
255  double m_minValue;
256 
257  //! the largest value
258  double m_maxValue;
259 };
260 
261 template< typename Data_T >
262 Data_T WDataSetTimeSeries::interpolate( WVector3d const& pos, float time, bool* success ) const
263 {
264  static const float inf = std::numeric_limits< float >::infinity();
265  WAssert( success, "" );
266  WAssert( !wlimits::isNaN( length( pos ) ), "" );
267  WAssert( !wlimits::isNaN( time ), "" );
268  if( time < getMinTime() || time > getMaxTime() )
269  {
270  *success = false;
271  throw WException( std::string( "The provided time is not in the interval of this time series." ) );
272  }
273  float lb = getLBTimeSlice( time );
274  float ub = getUBTimeSlice( time );
275  if( lb == time || ub == time )
276  {
277  boost::shared_ptr< WDataSetScalar const > ds = getDataSetPtrAtTimeSlice( time );
278  return static_cast< Data_T >( const_cast< WDataSetScalar& >( *ds ).interpolate( pos, success ) );
279  }
280  WAssert( lb != -inf && ub != inf, "" );
281  boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
282  boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
283  WAssert( f && g, "" );
284  float ml = ( ub - time ) / ( ub - lb );
285  float mu = ( time - lb ) / ( ub - lb );
286  return static_cast< Data_T >( ml * const_cast< WDataSetScalar& >( *f ).interpolate( pos, success )
287  + mu * const_cast< WDataSetScalar& >( *g ).interpolate( pos, success ) );
288 }
289 
290 template< typename Data_T >
291 boost::shared_ptr< WValueSetBase > WDataSetTimeSeries::calcInterpolatedValueSet( float lb, float ub, float time ) const
292 {
293  static const float inf = std::numeric_limits< float >::infinity();
294  WAssert( lb != -inf && ub != inf, "" );
295  boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
296  boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
297  WAssert( f && g, "" );
298  boost::shared_ptr< WValueSet< Data_T > > vf = boost::dynamic_pointer_cast< WValueSet< Data_T > >( f->getValueSet() );
299  boost::shared_ptr< WValueSet< Data_T > > vg = boost::dynamic_pointer_cast< WValueSet< Data_T > >( g->getValueSet() );
300  WAssert( vf && vg, "" );
301  boost::shared_ptr< std::vector< Data_T > > values( new std::vector< Data_T >( vf->size() ) );
302  float ml = ( ub - time ) / ( ub - lb );
303  float mu = ( time - lb ) / ( ub - lb );
304  for( std::size_t k = 0; k < values->size(); ++k )
305  {
306  ( *values )[ k ] = ml * vf->getScalar( k ) + mu * vg->getScalar( k );
307  }
308  return boost::shared_ptr< WValueSetBase >( new WValueSet< Data_T >( 0, 1, values, DataType< Data_T >::type ) );
309 }
310 
312 {
313  return m_dataSets.front().second;
314 }
315 
317 {
318  return m_dataSets.back().second;
319 }
320 
321 #endif // WDATASETTIMESERIES_H
double m_maxValue
the largest value
std::string const getName() const
Returns a name.
A dataset that stores a time series.
boost::shared_ptr< WValueSetBase > calcInterpolatedValueSet(float lb, float ub, float time) const
Interpolate a valueset from two neighboring slices.
std::pair< boost::shared_ptr< WDataSetScalar const >, float > TimeSlice
a time slice
Base class for all data set types.
Definition: WDataSet.h:51
double interpolate(const WPosition &pos, bool *success) const
Interpolate the value fo the valueset at the given position.
double m_minValue
the smallest value
float getUBTimeSlice(float time) const
Find the smallest time slice position that is larger than time, or return inf, if there is no such ti...
static boost::shared_ptr< WPrototyped > m_prototype
The prototype as singleton.
virtual ~WDataSetTimeSeries()
Destructor.
float getLBTimeSlice(float time) const
Find the largest time slice position that is smaller than or equal to time, or return -inf...
std::string const getDescription() const
Returns a description.
boost::shared_ptr< WDataSetScalar const > getDataSetPtrAtTimeSlice(float time) const
Get a pointer to the dataset at a given time or a NULL-pointer, if there was no dataset given for tha...
An object that knows an appropriate dataType flag for the typename T.
double getMaxValue()
Get the largest value in all datasets.
static boost::shared_ptr< WPrototyped > getPrototype()
Returns a prototype instantiated with the true type of the deriving class.
double getMinValue()
Get the smallest value in all datasets.
bool operator()(TimeSlice const &t0, TimeSlice const &t1)
Compares the time of two time slices.
float findNearestTimeSlice(float time) const
Find the nearest time slice for a given time.
Unit tests the time series class.
A compare functor for time slices.
bool isNaN(T value)
Determines if a number is considered as NaN (aka Not a Number) or not.
Definition: WLimits.h:82
WDataSetTimeSeries This
a conveniance typedef
WDataSetTimeSeries()
Standard constructor.
Base Class for all value set types.
Definition: WValueSet.h:46
bool isTimeSlice(float time) const
Check if there exists a predefined dataset at the given point in time, i.e.
std::vector< TimeSlice > m_dataSets
the datasets that compose the time series
This data set type contains scalars as values.
float getMaxTime() const
Get the last point of time in the time series.
Data_T interpolate(WVector3d const &pos, float time, bool *success) const
Interpolate a value for a single point in space and time.
Basic exception handler.
Definition: WException.h:38
boost::shared_ptr< WDataSetScalar const > calcDataSetAtTime(float time, std::string const &name) const
Calculates a new dataset with values interpolated between the two nearest time slices.
float getMinTime() const
Get the first point of time in the time series.