OpenWalnut  1.3.1
WDataSetTimeSeries_test.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_TEST_H
26 #define WDATASETTIMESERIES_TEST_H
27 
28 #include <vector>
29 #include <limits>
30 #include <algorithm>
31 #include <string>
32 
33 #include <boost/shared_ptr.hpp>
34 #include <cxxtest/TestSuite.h>
35 
36 #include "../../common/WLimits.h"
37 #include "../../common/WLogger.h"
38 
39 #include "../WDataSetTimeSeries.h"
40 
41 
42 /**
43  * Unit tests the time series class.
44  */
45 class WDataSetTimeSeriesTest : public CxxTest::TestSuite
46 {
47  //! a typedef
48  typedef std::vector< boost::shared_ptr< WDataSetScalar const > > DataSetPtrVector;
49 
50  //! a typdef
51  typedef std::vector< float > TimesVector;
52 
53 public:
54  /**
55  * The input should be sorted correctly and all data should be stored correctly.
56  * Also there should be only one grid for all datasets.
57  */
59  {
60  // test with 3 time slices
61  {
62  double data[] = { 1.0, 2.0, 3.0 };
64  TimesVector t;
65 
66  // test what happens when the input is empty
67  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
68 
69  // test what happens when the vector sizes don't match
70  createData( data, 3, d, t );
71  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
72  t.push_back( 4.0f );
73  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
74 
75  // test what happens when there is an invalid time value
76  t.resize( 3 );
77  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
78  t[ 2 ] = -0.0 / 0.0;
79  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
80 
81  // test what happens when there are equal time values
82  t[ 2 ] = t[ 1 ];
83  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
84 
85  // test what happens if the grids don't match
86  t[ 2 ] = 2.0;
87  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
88 
89  t.push_back( 4.0f );
90 
91  WMatrix< double > mat( 4, 4 );
92  boost::shared_ptr< std::vector< double > > v = boost::shared_ptr< std::vector< double > >( new std::vector< double >( 27, 4 ) );
93  mat.makeIdentity();
94  mat( 0, 0 ) = 1.0;
95  mat( 1, 1 ) = 0.5;
96  mat( 2, 2 ) = 2.0;
97 
98  WGridTransformOrtho transform( mat );
99  boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
100 
101  boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
102  d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
103  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
104 
105  // test what happens if the valuesets data types don't match
106  d.resize( 3 );
107  t.resize( 3 );
108  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
109 
110  t.push_back( 4.0f );
111  boost::shared_ptr< std::vector< float > > v2 = boost::shared_ptr< std::vector< float > >( new std::vector< float >( 27, 4 ) );
112  boost::shared_ptr< WValueSet< float > > vs2( new WValueSet< float >( 0, 1, v2, W_DT_FLOAT ) );
113  d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs2, d.front()->getGrid() ) ) );
114  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
115  }
116 
117  // test with 2 time slices
118  {
119  double data[] = { 1.0, 2.0 };
121  TimesVector t;
122 
123  // test what happens when the input is empty
124  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
125 
126  // test what happens when the vector sizes don't match
127  createData( data, 2, d, t );
128  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
129  t.push_back( 4.0f );
130  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
131 
132  // test what happens when there is an invalid time value
133  t.resize( 2 );
134  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
135  t[ 1 ] = 0.0f / 0.0f;
136  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
137 
138  // test what happens when there are equal time values
139  t[ 1 ] = t[ 0 ];
140  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
141 
142  // test what happens if the grids don't match
143  t[ 1 ] = 2.0;
144  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
145 
146  t.push_back( 4.0f );
147 
148  WMatrix< double > mat( 4, 4 );
149  boost::shared_ptr< std::vector< double > > v = boost::shared_ptr< std::vector< double > >( new std::vector< double >( 27, 4 ) );
150  mat.makeIdentity();
151  mat( 0, 0 ) = 1.0;
152  mat( 1, 1 ) = 0.5;
153  mat( 2, 2 ) = 2.0;
154 
155  WGridTransformOrtho transform( mat );
156  boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
157 
158  boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
159  d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
160  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
161 
162  // test what happens if the valuesets data types don't match
163  d.resize( 2 );
164  t.resize( 2 );
165  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
166 
167  t.push_back( 4.0f );
168  boost::shared_ptr< std::vector< float > > v2 = boost::shared_ptr< std::vector< float > >( new std::vector< float >( 27, 4 ) );
169  boost::shared_ptr< WValueSet< float > > vs2( new WValueSet< float >( 0, 1, v2, W_DT_FLOAT ) );
170  d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs2, d.front()->getGrid() ) ) );
171  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
172  }
173 
174  // test with 1 time slice
175  {
176  double data[] = { 1.0 };
178  TimesVector t;
179 
180  // test what happens when the input is empty
181  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
182 
183  // test what happens when the vector sizes don't match
184  createData( data, 1, d, t );
185  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
186  t.push_back( 4.0f );
187  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
188 
189  // test what happens when there is an invalid time value
190  t.resize( 1 );
191  TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
192  t[ 0 ] = -0.0f / 0.0f;
193  TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
194  }
195 
196  // datasets should be sorted by time
197  {
198  double data[] = { 1.0, 2.0, 3.0 };
200  TimesVector t;
201 
202  createData( data, 3, d, t );
203  std::swap( t[ 1 ], t[ 2 ] );
204  WDataSetTimeSeries ts( d, t );
205 
206  TS_ASSERT_EQUALS( d[ 0 ], ts.m_dataSets[ 0 ].first );
207  TS_ASSERT_EQUALS( d[ 2 ], ts.m_dataSets[ 1 ].first );
208  TS_ASSERT_EQUALS( d[ 1 ], ts.m_dataSets[ 2 ].first );
209  }
210  }
211 
212  /**
213  * The correct minimum and maximum times should be returned.
214  */
216  {
217  double data[] = { 1.0, 2.0, 3.0 };
219  TimesVector t;
220 
221  createData( data, 3, d, t );
222  {
223  WDataSetTimeSeries ts( d, t );
224 
225  TS_ASSERT_EQUALS( ts.getMinTime(), 0.0f );
226  TS_ASSERT_EQUALS( ts.getMaxTime(), 2.0f );
227  }
228 
229  createData( data, 3, d, t );
230  t[ 0 ] = 1.34f;
231  t[ 2 ] = 1.43f;
232  {
233  WDataSetTimeSeries ts( d, t );
234 
235  TS_ASSERT_EQUALS( ts.getMinTime(), 1.0f );
236  TS_ASSERT_EQUALS( ts.getMaxTime(), 1.43f );
237  }
238  }
239 
240  /**
241  * Times that were provided on construction should be found. Times outside of the
242  * interval [getMinTime(),getMaxTime()] should be rejected.
243  */
245  {
246  double data[] = { 1.0, 2.0, 3.0 };
248  TimesVector t;
249 
250  createData( data, 3, d, t );
251  {
252  WDataSetTimeSeries ts( d, t );
253  TS_ASSERT( ts.isTimeSlice( 0.0f ) );
254  TS_ASSERT( ts.isTimeSlice( 1.0f ) );
255  TS_ASSERT( ts.isTimeSlice( 2.0f ) );
256  TS_ASSERT( !ts.isTimeSlice( 5.0f ) );
257  TS_ASSERT( !ts.isTimeSlice( 0.0f / 0.0f ) );
258  TS_ASSERT( !ts.isTimeSlice( std::numeric_limits< float >::infinity() ) );
259  TS_ASSERT( !ts.isTimeSlice( 1.00001f ) );
260  TS_ASSERT( !ts.isTimeSlice( 2.345f ) );
261  TS_ASSERT( !ts.isTimeSlice( 0.5234f ) );
262  TS_ASSERT( !ts.isTimeSlice( -wlimits::FLT_EPS ) );
263  }
264 
265  createData( data, 3, d, t );
266  t[ 0 ] = 1.34f;
267  t[ 2 ] = 1.43f;
268  {
269  WDataSetTimeSeries ts( d, t );
270  TS_ASSERT( ts.isTimeSlice( 1.34f ) );
271  TS_ASSERT( ts.isTimeSlice( 1.43f ) );
272  TS_ASSERT( ts.isTimeSlice( 1.0f ) );
273  TS_ASSERT( !ts.isTimeSlice( 5.0f ) );
274  TS_ASSERT( !ts.isTimeSlice( 0.0f / 0.0f ) );
275  TS_ASSERT( !ts.isTimeSlice( std::numeric_limits< float >::infinity() ) );
276  TS_ASSERT( !ts.isTimeSlice( 1.00001f ) );
277  TS_ASSERT( !ts.isTimeSlice( 2.345f ) );
278  TS_ASSERT( !ts.isTimeSlice( 0.5234f ) );
279  TS_ASSERT( !ts.isTimeSlice( -wlimits::FLT_EPS ) );
280  }
281  }
282 
283  /**
284  * The nearest time slices should be calculated correctly. Boundary conditions must be
285  * handled correctly.
286  */
288  {
289  double data[] = { 1.0, 2.0, 3.0 };
291  TimesVector t;
292 
293  createData( data, 3, d, t );
294  WDataSetTimeSeries ts( d, t );
295 
296  float f = ts.findNearestTimeSlice( -std::numeric_limits< float >::infinity() );
297  TS_ASSERT_EQUALS( 0.0, f );
298  f = ts.findNearestTimeSlice( -3346.0 );
299  TS_ASSERT_EQUALS( 0.0, f );
300  f = ts.findNearestTimeSlice( -1.0 );
301  TS_ASSERT_EQUALS( 0.0, f );
302  f = ts.findNearestTimeSlice( -0.01 );
303  TS_ASSERT_EQUALS( 0.0, f );
305  TS_ASSERT_EQUALS( 0.0, f );
306  f = ts.findNearestTimeSlice( 0.0 );
307  TS_ASSERT_EQUALS( 0.0, f );
309  TS_ASSERT_EQUALS( 0.0, f );
310  f = ts.findNearestTimeSlice( 0.3 );
311  TS_ASSERT_EQUALS( 0.0, f );
312  f = ts.findNearestTimeSlice( 0.5 );
313  TS_ASSERT_EQUALS( 0.0, f );
314  f = ts.findNearestTimeSlice( 0.5 + wlimits::FLT_EPS );
315  TS_ASSERT_EQUALS( 1.0, f );
316  f = ts.findNearestTimeSlice( 1.0 - wlimits::FLT_EPS );
317  TS_ASSERT_EQUALS( 1.0, f );
318  f = ts.findNearestTimeSlice( 1.5 - wlimits::FLT_EPS );
319  TS_ASSERT_EQUALS( 1.0, f );
320  f = ts.findNearestTimeSlice( 1.5 );
321  TS_ASSERT_EQUALS( 1.0, f );
322  f = ts.findNearestTimeSlice( 2.0 - wlimits::FLT_EPS );
323  TS_ASSERT_EQUALS( 2.0f, f );
324  f = ts.findNearestTimeSlice( 2.0 );
325  TS_ASSERT_EQUALS( 2.0f, f );
326  f = ts.findNearestTimeSlice( std::numeric_limits< float >::infinity() );
327  TS_ASSERT_EQUALS( 2.0f, f );
328  TS_ASSERT_THROWS( ts.findNearestTimeSlice( 0.0 / 0.0 ), WException );
329  }
330 
331  /**
332  * Provided datasets should be returned for provided time slices.
333  */
335  {
336  double data[] = { 1.0, 2.0, 3.0 };
338  TimesVector t;
339 
340  createData( data, 3, d, t );
341  WDataSetTimeSeries ts( d, t );
342 
343  boost::shared_ptr< WDataSetScalar const > null;
344 
345  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.0f / 0.0f ), null );
346  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( -std::numeric_limits< float >::infinity() ), null );
347  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.0f ), d[ 0 ] );
348  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( wlimits::FLT_EPS ), null );
349  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.999f ), null );
350  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 1.0f ), d[ 1 ] );
351  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 2.0f ), d[ 2 ] );
352  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 344643.0f ), null );
353  TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( std::numeric_limits< float >::infinity() ), null );
354  }
355 
356  /**
357  * Interpolated datasets need to be correct.
358  */
360  {
361  double data[] = { 1.0, 2.0, 3.0 };
363  TimesVector t;
364 
365  createData( data, 3, d, t );
366  WDataSetTimeSeries ts( d, t );
367 
368  boost::shared_ptr< WDataSetScalar const > null;
369  boost::shared_ptr< WDataSetScalar const > ds;
370  std::string name( "a name" );
371 
372  ds = ts.calcDataSetAtTime( -std::numeric_limits< float >::infinity(), name );
373  TS_ASSERT_EQUALS( ds, null );
374 
375  ds = ts.calcDataSetAtTime( -wlimits::FLT_EPS, name );
376  TS_ASSERT_EQUALS( ds, null );
377 
378  ds = ts.calcDataSetAtTime( std::numeric_limits< float >::infinity(), name );
379  TS_ASSERT_EQUALS( ds, null );
380 
381  ds = ts.calcDataSetAtTime( 2.0f + 2.0f * wlimits::FLT_EPS, name );
382  TS_ASSERT_EQUALS( ds, null );
383 
384  ds = ts.calcDataSetAtTime( 0.0f, name );
385  TS_ASSERT_EQUALS( ds, d[ 0 ] );
386 
387  ds = ts.calcDataSetAtTime( 1.0f, name );
388  TS_ASSERT_EQUALS( ds, d[ 1 ] );
389 
390  ds = ts.calcDataSetAtTime( 2.0f, name );
391  TS_ASSERT_EQUALS( ds, d[ 2 ] );
392 
393  {
394  std::vector< double > v( 27, 1.35 );
395  ds = ts.calcDataSetAtTime( 0.35f, name );
396  TS_ASSERT( ds );
397  boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
398  TS_ASSERT( vs );
399  for( std::size_t k = 0; k < v.size(); ++k )
400  {
401  TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
402  }
403  }
404  {
405  std::vector< double > v( 27, 1.99 );
406  ds = ts.calcDataSetAtTime( 0.99f, name );
407  TS_ASSERT( ds );
408  boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
409  TS_ASSERT( vs );
410  for( std::size_t k = 0; k < v.size(); ++k )
411  {
412  TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
413  }
414  }
415  {
416  std::vector< double > v( 27, 2.598 );
417  ds = ts.calcDataSetAtTime( 1.598f, name );
418  TS_ASSERT( ds );
419  boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
420  TS_ASSERT( vs );
421  for( std::size_t k = 0; k < v.size(); ++k )
422  {
423  TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
424  }
425  }
426  }
427 
428  /**
429  * Interpolation of values should be correct.
430  */
432  {
433  double data[] = { 1.0, 2.0, 3.0 };
435  TimesVector t;
436 
437  createData( data, 3, d, t );
438  WDataSetTimeSeries ts( d, t );
439 
440  float inf = std::numeric_limits< float >::infinity();
441  bool success;
442  double h;
443 
444  // test invalid times
445  WVector3d pos( 1.0, 0.5, 1.0 );
446 
447  TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -inf, &success ), WException );
448  TS_ASSERT( !success );
449  TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -3.0f, &success ), WException );
450  TS_ASSERT( !success );
451  TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -wlimits::FLT_EPS, &success ), WException );
452  TS_ASSERT( !success );
453  TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, 2.0f + 2.0f * wlimits::FLT_EPS, &success ), WException );
454  TS_ASSERT( !success );
455  TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, inf, &success ), WException );
456  TS_ASSERT( !success );
457 
458  // test invalid position
459  float time = 0.99f;
460  pos[ 0 ] = -wlimits::FLT_EPS;
461  h = ts.interpolate< double >( pos, time, &success );
462  TS_ASSERT( !success );
463 
464  // now test some valid cases
465  pos[ 0 ] = 1.0f;
466  h = ts.interpolate< double >( pos, time, &success );
467  TS_ASSERT( success );
468  TS_ASSERT_DELTA( h, 1.99, wlimits::FLT_EPS );
469  }
470 
471  /**
472  * Test the lower bound time helper routine.
473  * It should return the largest time slice that is smaller than or equal
474  * to the input time, or -inf if there is no such time slice.
475  */
476  void testLBTime()
477  {
478  double data[] = { 1.0, 2.0, 3.0 };
480  TimesVector t;
481 
482  createData( data, 3, d, t );
483  WDataSetTimeSeries ts( d, t );
484 
485  float neginf = -std::numeric_limits< float >::infinity();
486 
487  // not using TS_ASSERT_EQUALS here because of a bug
488  // passing inf as a parameter leads to an endless loop
489  TS_ASSERT( ts.getLBTimeSlice( neginf ) == neginf );
490  TS_ASSERT( ts.getLBTimeSlice( -0.01f ) == neginf );
491  TS_ASSERT( ts.getLBTimeSlice( 0.0f ) == 0.0f );
492  TS_ASSERT( ts.getLBTimeSlice( -wlimits::FLT_EPS ) == neginf );
493  TS_ASSERT( ts.getLBTimeSlice( wlimits::FLT_EPS ) == 0.0f );
494  TS_ASSERT( ts.getLBTimeSlice( 1.0f ) == 1.0f );
495  TS_ASSERT( ts.getLBTimeSlice( 1.2f ) == 1.0f );
496  TS_ASSERT( ts.getLBTimeSlice( 2.0f - wlimits::FLT_EPS ) == 1.0f );
497  TS_ASSERT( ts.getLBTimeSlice( 2.0f ) == 2.0f );
498  TS_ASSERT( ts.getLBTimeSlice( -neginf ) == 2.0f );
499 
500  // note that there is no test for nan, as these routines are private
501  // it is the callers responsibility to check for nan
502  }
503 
504  /**
505  * Test the upper bound time helper routine.
506  * It should return the smallest time slice that is larger than the input
507  * time, or inf if there is no such time slice.
508  */
509  void testUBTime()
510  {
511  double data[] = { 1.0, 2.0, 3.0 };
513  TimesVector t;
514 
515  createData( data, 3, d, t );
516  WDataSetTimeSeries ts( d, t );
517 
518  float inf = std::numeric_limits< float >::infinity();
519 
520  // not using TS_ASSERT_EQUALS here because of a bug
521  // passing inf as a parameter leads to an endless loop
522  TS_ASSERT( ts.getUBTimeSlice( -inf ) == 0.0f );
523  TS_ASSERT( ts.getUBTimeSlice( -0.01f ) == 0.0f );
524  TS_ASSERT( ts.getUBTimeSlice( 0.0f ) == 1.0f );
525  TS_ASSERT( ts.getUBTimeSlice( -wlimits::FLT_EPS ) == 0.0f );
526  TS_ASSERT( ts.getUBTimeSlice( wlimits::FLT_EPS ) == 1.0f );
527  TS_ASSERT( ts.getUBTimeSlice( 1.0f ) == 2.0f );
528  TS_ASSERT( ts.getUBTimeSlice( 1.2f ) == 2.0f );
529  TS_ASSERT( ts.getUBTimeSlice( 2.0f - wlimits::FLT_EPS ) == 2.0f );
530  TS_ASSERT( ts.getUBTimeSlice( 2.0f ) == inf );
531  TS_ASSERT( ts.getUBTimeSlice( inf ) == inf );
532 
533  // note that there is no test for nan, as these routines are private
534  // it is the callers responsibility to check for nan
535  }
536 
537 private:
538  /**
539  * A helper function that creates some input data.
540  *
541  * \param data An array of data values, one for each time slice.
542  * \param number The number of time slices.
543  * \param dsets The output datasets.
544  * \param times Some times for the output datasets.
545  */
546  void createData( double* data, int number, DataSetPtrVector& dsets, TimesVector& times ) // NOLINT
547  {
548  dsets.clear();
549  times.clear();
550 
551  WMatrix< double > mat( 4, 4 );
552  mat.makeIdentity();
553  mat( 0, 0 ) = 1.0;
554  mat( 1, 1 ) = 0.5;
555  mat( 2, 2 ) = 2.0;
556 
557  WGridTransformOrtho transform( mat );
558  boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
559 
560  for( int i = 0; i < number; ++i )
561  {
562  boost::shared_ptr< std::vector< double > > v = boost::shared_ptr< std::vector< double > >( new std::vector< double >( 27, data[i] ) );
563  boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
564  dsets.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
565  times.push_back( static_cast< float >( i ) );
566  }
567  }
568 
569  /**
570  * Setup logger and other stuff for each test.
571  */
572  void setUp()
573  {
575  }
576 };
577 
578 #endif // WDATASETTIMESERIES_TEST_H