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 #ifndef Q_MOC_RUN
34 #include <boost/enable_shared_from_this.hpp>
35 #endif
36 #ifndef Q_MOC_RUN
37 #include <boost/shared_ptr.hpp>
38 #endif
39 
40 #include "../common/WLimits.h"
41 #include "../common/WProperties.h"
42 #include "../common/WTransferable.h"
43 #include "WDataSetScalar.h"
44 
45 
46 //! forward declaration
48 
49 /**
50  * A dataset that stores a time series.
51  *
52  * \note Only works for scalar datasets at the moment!
53  * \note this is only a temporary solution
54  */
56 {
57  //! the test is a friend
58  friend class WDataSetTimeSeriesTest;
59 
60  //! a conveniance typedef
62 
63  //! a time slice
64  typedef std::pair< boost::shared_ptr< WDataSetScalar const >, float > TimeSlice;
65 
66 public:
67  /**
68  * Returns a name.
69  *
70  * \return A name.
71  */
72  std::string const getName() const;
73 
74  /**
75  * Returns a description.
76  *
77  * \return A description.
78  */
79  std::string const getDescription() const;
80 
81  /**
82  * Returns a prototype instantiated with the true type of the deriving class.
83  *
84  * \return the prototype.
85  */
86  static boost::shared_ptr< WPrototyped > getPrototype();
87 
88  /**
89  * Construct time series from multiple 3D datasets. They do not have to be sorted by time.
90  *
91  * \param datasets A list of datasets to add.
92  * \param times A list of times for the datasets.
93  */
94  WDataSetTimeSeries( std::vector< boost::shared_ptr< WDataSetScalar const > > datasets, std::vector< float > times );
95 
96  /**
97  * Destructor.
98  */
99  virtual ~WDataSetTimeSeries();
100 
101  /**
102  * Get the first point of time in the time series.
103  *
104  * \return The first point of time.
105  */
106  inline float getMinTime() const;
107 
108  /**
109  * Get the last point of time in the time series.
110  *
111  * \return The last point of time.
112  */
113  inline float getMaxTime() const;
114 
115  /**
116  * Check if there exists a predefined dataset at the given point in time, i.e.
117  * no interpolation has to be done to access data at that point in time.
118  *
119  * If the time is not in the represented interval [getMinTime(),getMaxTime()],
120  * it will return false.
121  *
122  * \param time The point in time to test.
123  * \return true, iff the time is one of those that were given in the constructor.
124  */
125  bool isTimeSlice( float time ) const;
126 
127  /**
128  * Find the nearest time slice for a given time. If there are two
129  * nearest time slices, the smaller one will be returned.
130  *
131  * \param time The time.
132  * \return The nearest time slice.
133  */
134  float findNearestTimeSlice( float time ) const;
135 
136  /**
137  * Get a pointer to the dataset at a given time or a NULL-pointer, if there
138  * was no dataset given for that point in time.
139  *
140  * \note You need to provide the exact time.
141  *
142  * \param time The time.
143  * \return A pointer to the appropriate dataset or a NULL-pointer.
144  */
145  boost::shared_ptr< WDataSetScalar const > getDataSetPtrAtTimeSlice( float time ) const;
146 
147  /**
148  * Calculates a new dataset with values interpolated between the two nearest
149  * time slices. if the time is not in the interval [getMinTime(),getMaxTime()],
150  * a NULL-pointer will be returned.
151  *
152  * \param time The time.
153  * \param name The name of the new dataset.
154  * \return A new interpolated dataset.
155  */
156  boost::shared_ptr< WDataSetScalar const > calcDataSetAtTime( float time, std::string const& name ) const;
157 
158  /**
159  * Interpolate a value for a single point in space and time.
160  *
161  * \param pos The spatial location.
162  * \param time The temporal location.
163  * \param[out] success A flag indicating if the position was in the dataset.
164  * \return The value at the given location.
165  */
166  template< typename Data_T >
167  Data_T interpolate( WVector3d const& pos, float time, bool* success ) const;
168 
169  /**
170  * Get the smallest value in all datasets.
171  *
172  * \return The smallest value.
173  */
174  double getMinValue();
175 
176  /**
177  * Get the largest value in all datasets.
178  *
179  * \return The largest value.
180  */
181  double getMaxValue();
182 
183 private:
184  /**
185  * Find the largest time slice position that is smaller than or equal to time,
186  * or return -inf, if there is no such time slice.
187  *
188  * \param time The time.
189  * \return The largest time slice that is smaller than or equal to time or -inf.
190  */
191  float getLBTimeSlice( float time ) const;
192 
193  /**
194  * Find the smallest time slice position that is larger than time, or return
195  * inf, if there is no such time slice.
196  *
197  * \param time The time.
198  * \return The largest time slice that is smaller than time or inf.
199  */
200  float getUBTimeSlice( float time ) const;
201 
202  /**
203  * Interpolate a valueset from two neighboring slices.
204  *
205  * \param lb Time of one slice.
206  * \param ub Time of the other slice.
207  * \param time The actual time of the interpolated slice.
208  * \return A valueset with linearly interpolated values.
209  */
210  template< typename Data_T >
211  boost::shared_ptr< WValueSetBase > calcInterpolatedValueSet( float lb, float ub, float time ) const;
212 
213  /**
214  * Standard constructor.
215  */
217 
218  /**
219  * A compare functor for time slices.
220  */
222  {
223  public:
224  /**
225  * Compares the time of two time slices.
226  *
227  * \param t0 The first time slice.
228  * \param t1 The other time slice.
229  * \return true, iff the time of the first slice is smaller than that of the other one.
230  */
231  bool operator() ( TimeSlice const& t0, TimeSlice const& t1 );
232 
233  /**
234  * Compares the time of two time slices.
235  *
236  * \param t0 The first time slice.
237  * \param t1 The other time slice.
238  * \return true, iff the time of the first slice is smaller than that of the other one.
239  */
240  bool operator() ( float const& t0, TimeSlice const& t1 );
241 
242  /**
243  * Compares the time of two time slices.
244  *
245  * \param t0 The first time slice.
246  * \param t1 The other time slice.
247  * \return true, iff the time of the first slice is smaller than that of the other one.
248  */
249  bool operator() ( TimeSlice const& t0, float const& t1 );
250  };
251 
252  //! the datasets that compose the time series
253  std::vector< TimeSlice > m_dataSets;
254 
255  //! The prototype as singleton.
256  static boost::shared_ptr< WPrototyped > m_prototype;
257 
258  //! the smallest value
259  double m_minValue;
260 
261  //! the largest value
262  double m_maxValue;
263 };
264 
265 template< typename Data_T >
266 Data_T WDataSetTimeSeries::interpolate( WVector3d const& pos, float time, bool* success ) const
267 {
268  static const float inf = std::numeric_limits< float >::infinity();
269  WAssert( success, "" );
270  WAssert( !wlimits::isNaN( length( pos ) ), "" );
271  WAssert( !wlimits::isNaN( time ), "" );
272  if( time < getMinTime() || time > getMaxTime() )
273  {
274  *success = false;
275  throw WException( std::string( "The provided time is not in the interval of this time series." ) );
276  }
277  float lb = getLBTimeSlice( time );
278  float ub = getUBTimeSlice( time );
279  if( lb == time || ub == time )
280  {
281  boost::shared_ptr< WDataSetScalar const > ds = getDataSetPtrAtTimeSlice( time );
282  return static_cast< Data_T >( const_cast< WDataSetScalar& >( *ds ).interpolate( pos, success ) );
283  }
284  WAssert( lb != -inf && ub != inf, "" );
285  boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
286  boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
287  WAssert( f && g, "" );
288  float ml = ( ub - time ) / ( ub - lb );
289  float mu = ( time - lb ) / ( ub - lb );
290  return static_cast< Data_T >( ml * const_cast< WDataSetScalar& >( *f ).interpolate( pos, success )
291  + mu * const_cast< WDataSetScalar& >( *g ).interpolate( pos, success ) );
292 }
293 
294 template< typename Data_T >
295 boost::shared_ptr< WValueSetBase > WDataSetTimeSeries::calcInterpolatedValueSet( float lb, float ub, float time ) const
296 {
297  static const float inf = std::numeric_limits< float >::infinity();
298  WAssert( lb != -inf && ub != inf, "" );
299  boost::shared_ptr< WDataSetScalar const > f = getDataSetPtrAtTimeSlice( lb );
300  boost::shared_ptr< WDataSetScalar const > g = getDataSetPtrAtTimeSlice( ub );
301  WAssert( f && g, "" );
302  boost::shared_ptr< WValueSet< Data_T > > vf = boost::dynamic_pointer_cast< WValueSet< Data_T > >( f->getValueSet() );
303  boost::shared_ptr< WValueSet< Data_T > > vg = boost::dynamic_pointer_cast< WValueSet< Data_T > >( g->getValueSet() );
304  WAssert( vf && vg, "" );
305  boost::shared_ptr< std::vector< Data_T > > values( new std::vector< Data_T >( vf->size() ) );
306  float ml = ( ub - time ) / ( ub - lb );
307  float mu = ( time - lb ) / ( ub - lb );
308  for( std::size_t k = 0; k < values->size(); ++k )
309  {
310  ( *values )[ k ] = ml * vf->getScalar( k ) + mu * vg->getScalar( k );
311  }
312  return boost::shared_ptr< WValueSetBase >( new WValueSet< Data_T >( 0, 1, values, DataType< Data_T >::type ) );
313 }
314 
316 {
317  return m_dataSets.front().second;
318 }
319 
321 {
322  return m_dataSets.back().second;
323 }
324 
325 #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:55
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:84
WDataSetTimeSeries This
a conveniance typedef
WDataSetTimeSeries()
Standard constructor.
Base Class for all value set types.
Definition: WValueSet.h:48
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.