OpenWalnut  1.4.0
WDataSetTimeSeries_test.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_TEST_H
00026 #define WDATASETTIMESERIES_TEST_H
00027 
00028 #include <vector>
00029 #include <limits>
00030 #include <algorithm>
00031 #include <string>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 #include <cxxtest/TestSuite.h>
00035 
00036 #include "../../common/WLimits.h"
00037 #include "../../common/WLogger.h"
00038 
00039 #include "../WDataSetTimeSeries.h"
00040 
00041 
00042 /**
00043  * Unit tests the time series class.
00044  */
00045 class WDataSetTimeSeriesTest : public CxxTest::TestSuite
00046 {
00047     //! a typedef
00048     typedef std::vector< boost::shared_ptr< WDataSetScalar const > > DataSetPtrVector;
00049 
00050     //! a typdef
00051     typedef std::vector< float > TimesVector;
00052 
00053 public:
00054     /**
00055      * The input should be sorted correctly and all data should be stored correctly.
00056      * Also there should be only one grid for all datasets.
00057      */
00058     void testConstruction()
00059     {
00060         // test with 3 time slices
00061         {
00062             double data[] = { 1.0, 2.0, 3.0 };
00063             DataSetPtrVector d;
00064             TimesVector t;
00065 
00066             // test what happens when the input is empty
00067             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00068 
00069             // test what happens when the vector sizes don't match
00070             createData( data, 3, d, t );
00071             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00072             t.push_back( 4.0f );
00073             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00074 
00075             // test what happens when there is an invalid time value
00076             t.resize( 3 );
00077             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00078             t[ 2 ] = -0.0 / 0.0;
00079             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00080 
00081             // test what happens when there are equal time values
00082             t[ 2 ] = t[ 1 ];
00083             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00084 
00085             // test what happens if the grids don't match
00086             t[ 2 ] = 2.0;
00087             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00088 
00089             t.push_back( 4.0f );
00090 
00091             WMatrix< double > mat( 4, 4 );
00092             boost::shared_ptr< std::vector< double > > v( new std::vector< double >( 27, 4 ) );
00093             mat.makeIdentity();
00094             mat( 0, 0 ) = 1.0;
00095             mat( 1, 1 ) = 0.5;
00096             mat( 2, 2 ) = 2.0;
00097 
00098             WGridTransformOrtho transform( mat );
00099             boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
00100 
00101             boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
00102             d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
00103             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00104 
00105             // test what happens if the valuesets data types don't match
00106             d.resize( 3 );
00107             t.resize( 3 );
00108             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00109 
00110             t.push_back( 4.0f );
00111             boost::shared_ptr< std::vector< float > > v2( new std::vector< float >( 27, 4 ) );
00112             boost::shared_ptr< WValueSet< float > > vs2( new WValueSet< float >( 0, 1, v2, W_DT_FLOAT ) );
00113             d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs2, d.front()->getGrid() ) ) );
00114             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00115         }
00116 
00117         // test with 2 time slices
00118         {
00119             double data[] = { 1.0, 2.0 };
00120             DataSetPtrVector d;
00121             TimesVector t;
00122 
00123             // test what happens when the input is empty
00124             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00125 
00126             // test what happens when the vector sizes don't match
00127             createData( data, 2, d, t );
00128             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00129             t.push_back( 4.0f );
00130             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00131 
00132             // test what happens when there is an invalid time value
00133             t.resize( 2 );
00134             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00135             t[ 1 ] = 0.0f / 0.0f;
00136             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00137 
00138             // test what happens when there are equal time values
00139             t[ 1 ] = t[ 0 ];
00140             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00141 
00142             // test what happens if the grids don't match
00143             t[ 1 ] = 2.0;
00144             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00145 
00146             t.push_back( 4.0f );
00147 
00148             WMatrix< double > mat( 4, 4 );
00149             boost::shared_ptr< std::vector< double > > v( new std::vector< double >( 27, 4 ) );
00150             mat.makeIdentity();
00151             mat( 0, 0 ) = 1.0;
00152             mat( 1, 1 ) = 0.5;
00153             mat( 2, 2 ) = 2.0;
00154 
00155             WGridTransformOrtho transform( mat );
00156             boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
00157 
00158             boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
00159             d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
00160             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00161 
00162             // test what happens if the valuesets data types don't match
00163             d.resize( 2 );
00164             t.resize( 2 );
00165             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00166 
00167             t.push_back( 4.0f );
00168             boost::shared_ptr< std::vector< float > > v2( new std::vector< float >( 27, 4 ) );
00169             boost::shared_ptr< WValueSet< float > > vs2( new WValueSet< float >( 0, 1, v2, W_DT_FLOAT ) );
00170             d.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs2, d.front()->getGrid() ) ) );
00171             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00172         }
00173 
00174         // test with 1 time slice
00175         {
00176             double data[] = { 1.0 };
00177             DataSetPtrVector d;
00178             TimesVector t;
00179 
00180             // test what happens when the input is empty
00181             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00182 
00183             // test what happens when the vector sizes don't match
00184             createData( data, 1, d, t );
00185             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00186             t.push_back( 4.0f );
00187             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00188 
00189             // test what happens when there is an invalid time value
00190             t.resize( 1 );
00191             TS_ASSERT_THROWS_NOTHING( WDataSetTimeSeries( d, t ) );
00192             t[ 0 ] = -0.0f / 0.0f;
00193             TS_ASSERT_THROWS( WDataSetTimeSeries( d, t ), WException );
00194         }
00195 
00196         // datasets should be sorted by time
00197         {
00198             double data[] = { 1.0, 2.0, 3.0 };
00199             DataSetPtrVector d;
00200             TimesVector t;
00201 
00202             createData( data, 3, d, t );
00203             std::swap( t[ 1 ], t[ 2 ] );
00204             WDataSetTimeSeries ts( d, t );
00205 
00206             TS_ASSERT_EQUALS( d[ 0 ], ts.m_dataSets[ 0 ].first );
00207             TS_ASSERT_EQUALS( d[ 2 ], ts.m_dataSets[ 1 ].first );
00208             TS_ASSERT_EQUALS( d[ 1 ], ts.m_dataSets[ 2 ].first );
00209         }
00210     }
00211 
00212     /**
00213      * The correct minimum and maximum times should be returned.
00214      */
00215     void testTimeMinMax()
00216     {
00217         double data[] = { 1.0, 2.0, 3.0 };
00218         DataSetPtrVector d;
00219         TimesVector t;
00220 
00221         createData( data, 3, d, t );
00222         {
00223             WDataSetTimeSeries ts( d, t );
00224 
00225             TS_ASSERT_EQUALS( ts.getMinTime(), 0.0f );
00226             TS_ASSERT_EQUALS( ts.getMaxTime(), 2.0f );
00227         }
00228 
00229         createData( data, 3, d, t );
00230         t[ 0 ] = 1.34f;
00231         t[ 2 ] = 1.43f;
00232         {
00233             WDataSetTimeSeries ts( d, t );
00234 
00235             TS_ASSERT_EQUALS( ts.getMinTime(), 1.0f );
00236             TS_ASSERT_EQUALS( ts.getMaxTime(), 1.43f );
00237         }
00238     }
00239 
00240     /**
00241      * Times that were provided on construction should be found. Times outside of the
00242      * interval [getMinTime(),getMaxTime()] should be rejected.
00243      */
00244     void testIsTimeSlice()
00245     {
00246         double data[] = { 1.0, 2.0, 3.0 };
00247         DataSetPtrVector d;
00248         TimesVector t;
00249 
00250         createData( data, 3, d, t );
00251         {
00252             WDataSetTimeSeries ts( d, t );
00253             TS_ASSERT( ts.isTimeSlice( 0.0f ) );
00254             TS_ASSERT( ts.isTimeSlice( 1.0f ) );
00255             TS_ASSERT( ts.isTimeSlice( 2.0f ) );
00256             TS_ASSERT( !ts.isTimeSlice( 5.0f ) );
00257             TS_ASSERT( !ts.isTimeSlice( 0.0f / 0.0f ) );
00258             TS_ASSERT( !ts.isTimeSlice( std::numeric_limits< float >::infinity() ) );
00259             TS_ASSERT( !ts.isTimeSlice( 1.00001f ) );
00260             TS_ASSERT( !ts.isTimeSlice( 2.345f ) );
00261             TS_ASSERT( !ts.isTimeSlice( 0.5234f ) );
00262             TS_ASSERT( !ts.isTimeSlice( -wlimits::FLT_EPS ) );
00263         }
00264 
00265         createData( data, 3, d, t );
00266         t[ 0 ] = 1.34f;
00267         t[ 2 ] = 1.43f;
00268         {
00269             WDataSetTimeSeries ts( d, t );
00270             TS_ASSERT( ts.isTimeSlice( 1.34f ) );
00271             TS_ASSERT( ts.isTimeSlice( 1.43f ) );
00272             TS_ASSERT( ts.isTimeSlice( 1.0f ) );
00273             TS_ASSERT( !ts.isTimeSlice( 5.0f ) );
00274             TS_ASSERT( !ts.isTimeSlice( 0.0f / 0.0f ) );
00275             TS_ASSERT( !ts.isTimeSlice( std::numeric_limits< float >::infinity() ) );
00276             TS_ASSERT( !ts.isTimeSlice( 1.00001f ) );
00277             TS_ASSERT( !ts.isTimeSlice( 2.345f ) );
00278             TS_ASSERT( !ts.isTimeSlice( 0.5234f ) );
00279             TS_ASSERT( !ts.isTimeSlice( -wlimits::FLT_EPS ) );
00280         }
00281     }
00282 
00283     /**
00284      * The nearest time slices should be calculated correctly. Boundary conditions must be
00285      * handled correctly.
00286      */
00287     void testGetNearestTimeSlice()
00288     {
00289         double data[] = { 1.0, 2.0, 3.0 };
00290         DataSetPtrVector d;
00291         TimesVector t;
00292 
00293         createData( data, 3, d, t );
00294         WDataSetTimeSeries ts( d, t );
00295 
00296         float f = ts.findNearestTimeSlice( -std::numeric_limits< float >::infinity() );
00297         TS_ASSERT_EQUALS( 0.0, f );
00298         f = ts.findNearestTimeSlice( -3346.0 );
00299         TS_ASSERT_EQUALS( 0.0, f );
00300         f = ts.findNearestTimeSlice( -1.0 );
00301         TS_ASSERT_EQUALS( 0.0, f );
00302         f = ts.findNearestTimeSlice( -0.01 );
00303         TS_ASSERT_EQUALS( 0.0, f );
00304         f = ts.findNearestTimeSlice( -wlimits::FLT_EPS );
00305         TS_ASSERT_EQUALS( 0.0, f );
00306         f = ts.findNearestTimeSlice( 0.0 );
00307         TS_ASSERT_EQUALS( 0.0, f );
00308         f = ts.findNearestTimeSlice( wlimits::FLT_EPS );
00309         TS_ASSERT_EQUALS( 0.0, f );
00310         f = ts.findNearestTimeSlice( 0.3 );
00311         TS_ASSERT_EQUALS( 0.0, f );
00312         f = ts.findNearestTimeSlice( 0.5 );
00313         TS_ASSERT_EQUALS( 0.0, f );
00314         f = ts.findNearestTimeSlice( 0.5 + wlimits::FLT_EPS );
00315         TS_ASSERT_EQUALS( 1.0, f );
00316         f = ts.findNearestTimeSlice( 1.0 - wlimits::FLT_EPS );
00317         TS_ASSERT_EQUALS( 1.0, f );
00318         f = ts.findNearestTimeSlice( 1.5 - wlimits::FLT_EPS );
00319         TS_ASSERT_EQUALS( 1.0, f );
00320         f = ts.findNearestTimeSlice( 1.5 );
00321         TS_ASSERT_EQUALS( 1.0, f );
00322         f = ts.findNearestTimeSlice( 2.0 - wlimits::FLT_EPS );
00323         TS_ASSERT_EQUALS( 2.0f, f );
00324         f = ts.findNearestTimeSlice( 2.0 );
00325         TS_ASSERT_EQUALS( 2.0f, f );
00326         f = ts.findNearestTimeSlice( std::numeric_limits< float >::infinity() );
00327         TS_ASSERT_EQUALS( 2.0f, f );
00328         TS_ASSERT_THROWS( ts.findNearestTimeSlice( 0.0 / 0.0 ), WException );
00329     }
00330 
00331     /**
00332      * Provided datasets should be returned for provided time slices.
00333      */
00334     void testGetDataSetPtrAtTimeSlice()
00335     {
00336         double data[] = { 1.0, 2.0, 3.0 };
00337         DataSetPtrVector d;
00338         TimesVector t;
00339 
00340         createData( data, 3, d, t );
00341         WDataSetTimeSeries ts( d, t );
00342 
00343         boost::shared_ptr< WDataSetScalar const > null;
00344 
00345         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.0f / 0.0f ), null );
00346         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( -std::numeric_limits< float >::infinity() ), null );
00347         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.0f ), d[ 0 ] );
00348         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( wlimits::FLT_EPS ), null );
00349         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 0.999f ), null );
00350         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 1.0f ), d[ 1 ] );
00351         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 2.0f ), d[ 2 ] );
00352         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( 344643.0f ), null );
00353         TS_ASSERT_EQUALS( ts.getDataSetPtrAtTimeSlice( std::numeric_limits< float >::infinity() ), null );
00354     }
00355 
00356     /**
00357      * Interpolated datasets need to be correct.
00358      */
00359     void testInterpolatedDataSets()
00360     {
00361         double data[] = { 1.0, 2.0, 3.0 };
00362         DataSetPtrVector d;
00363         TimesVector t;
00364 
00365         createData( data, 3, d, t );
00366         WDataSetTimeSeries ts( d, t );
00367 
00368         boost::shared_ptr< WDataSetScalar const > null;
00369         boost::shared_ptr< WDataSetScalar const > ds;
00370         std::string name( "a name" );
00371 
00372         ds = ts.calcDataSetAtTime( -std::numeric_limits< float >::infinity(), name );
00373         TS_ASSERT_EQUALS( ds, null );
00374 
00375         ds = ts.calcDataSetAtTime( -wlimits::FLT_EPS, name );
00376         TS_ASSERT_EQUALS( ds, null );
00377 
00378         ds = ts.calcDataSetAtTime( std::numeric_limits< float >::infinity(), name );
00379         TS_ASSERT_EQUALS( ds, null );
00380 
00381         ds = ts.calcDataSetAtTime( 2.0f + 2.0f * wlimits::FLT_EPS, name );
00382         TS_ASSERT_EQUALS( ds, null );
00383 
00384         ds = ts.calcDataSetAtTime( 0.0f, name );
00385         TS_ASSERT_EQUALS( ds, d[ 0 ] );
00386 
00387         ds = ts.calcDataSetAtTime( 1.0f, name );
00388         TS_ASSERT_EQUALS( ds, d[ 1 ] );
00389 
00390         ds = ts.calcDataSetAtTime( 2.0f, name );
00391         TS_ASSERT_EQUALS( ds, d[ 2 ] );
00392 
00393         {
00394             std::vector< double > v( 27, 1.35 );
00395             ds = ts.calcDataSetAtTime( 0.35f, name );
00396             TS_ASSERT( ds );
00397             boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
00398             TS_ASSERT( vs );
00399             for( std::size_t k = 0; k < v.size(); ++k )
00400             {
00401                 TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
00402             }
00403         }
00404         {
00405             std::vector< double > v( 27, 1.99 );
00406             ds = ts.calcDataSetAtTime( 0.99f, name );
00407             TS_ASSERT( ds );
00408             boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
00409             TS_ASSERT( vs );
00410             for( std::size_t k = 0; k < v.size(); ++k )
00411             {
00412                 TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
00413             }
00414         }
00415         {
00416             std::vector< double > v( 27, 2.598 );
00417             ds = ts.calcDataSetAtTime( 1.598f, name );
00418             TS_ASSERT( ds );
00419             boost::shared_ptr< WValueSet< double > > vs = boost::dynamic_pointer_cast< WValueSet< double > >( ds->getValueSet() );
00420             TS_ASSERT( vs );
00421             for( std::size_t k = 0; k < v.size(); ++k )
00422             {
00423                 TS_ASSERT_DELTA( v[ k ], vs->rawData()[ k ], 1.0f * wlimits::FLT_EPS );
00424             }
00425         }
00426     }
00427 
00428     /**
00429      * Interpolation of values should be correct.
00430      */
00431     void testInterpolate()
00432     {
00433         double data[] = { 1.0, 2.0, 3.0 };
00434         DataSetPtrVector d;
00435         TimesVector t;
00436 
00437         createData( data, 3, d, t );
00438         WDataSetTimeSeries ts( d, t );
00439 
00440         float inf = std::numeric_limits< float >::infinity();
00441         bool success;
00442         double h;
00443 
00444         // test invalid times
00445         WVector3d pos( 1.0, 0.5, 1.0 );
00446 
00447         TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -inf, &success ), WException );
00448         TS_ASSERT( !success );
00449         TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -3.0f, &success ), WException );
00450         TS_ASSERT( !success );
00451         TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, -wlimits::FLT_EPS, &success ), WException );
00452         TS_ASSERT( !success );
00453         TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, 2.0f + 2.0f * wlimits::FLT_EPS, &success ), WException );
00454         TS_ASSERT( !success );
00455         TS_ASSERT_THROWS( h = ts.interpolate< double >( pos, inf, &success ), WException );
00456         TS_ASSERT( !success );
00457 
00458         // test invalid position
00459         float time = 0.99f;
00460         pos[ 0 ] = -wlimits::FLT_EPS;
00461         h = ts.interpolate< double >( pos, time, &success );
00462         TS_ASSERT( !success );
00463 
00464         // now test some valid cases
00465         pos[ 0 ] = 1.0f;
00466         h = ts.interpolate< double >( pos, time, &success );
00467         TS_ASSERT( success );
00468         TS_ASSERT_DELTA( h, 1.99, wlimits::FLT_EPS );
00469     }
00470 
00471     /**
00472      * Test the lower bound time helper routine.
00473      * It should return the largest time slice that is smaller than or equal
00474      * to the input time, or -inf if there is no such time slice.
00475      */
00476     void testLBTime()
00477     {
00478         double data[] = { 1.0, 2.0, 3.0 };
00479         DataSetPtrVector d;
00480         TimesVector t;
00481 
00482         createData( data, 3, d, t );
00483         WDataSetTimeSeries ts( d, t );
00484 
00485         float neginf = -std::numeric_limits< float >::infinity();
00486 
00487         // not using TS_ASSERT_EQUALS here because of a bug
00488         // passing inf as a parameter leads to an endless loop
00489         TS_ASSERT( ts.getLBTimeSlice( neginf ) == neginf );
00490         TS_ASSERT( ts.getLBTimeSlice( -0.01f ) == neginf );
00491         TS_ASSERT( ts.getLBTimeSlice( 0.0f ) == 0.0f );
00492         TS_ASSERT( ts.getLBTimeSlice( -wlimits::FLT_EPS ) == neginf );
00493         TS_ASSERT( ts.getLBTimeSlice( wlimits::FLT_EPS ) == 0.0f );
00494         TS_ASSERT( ts.getLBTimeSlice( 1.0f ) == 1.0f );
00495         TS_ASSERT( ts.getLBTimeSlice( 1.2f ) == 1.0f );
00496         TS_ASSERT( ts.getLBTimeSlice( 2.0f - wlimits::FLT_EPS ) == 1.0f );
00497         TS_ASSERT( ts.getLBTimeSlice( 2.0f ) == 2.0f );
00498         TS_ASSERT( ts.getLBTimeSlice( -neginf ) == 2.0f );
00499 
00500         // note that there is no test for nan, as these routines are private
00501         // it is the callers responsibility to check for nan
00502     }
00503 
00504     /**
00505      * Test the upper bound time helper routine.
00506      * It should return the smallest time slice that is larger than the input
00507      * time, or inf if there is no such time slice.
00508      */
00509     void testUBTime()
00510     {
00511         double data[] = { 1.0, 2.0, 3.0 };
00512         DataSetPtrVector d;
00513         TimesVector t;
00514 
00515         createData( data, 3, d, t );
00516         WDataSetTimeSeries ts( d, t );
00517 
00518         float inf = std::numeric_limits< float >::infinity();
00519 
00520         // not using TS_ASSERT_EQUALS here because of a bug
00521         // passing inf as a parameter leads to an endless loop
00522         TS_ASSERT( ts.getUBTimeSlice( -inf ) == 0.0f );
00523         TS_ASSERT( ts.getUBTimeSlice( -0.01f ) == 0.0f );
00524         TS_ASSERT( ts.getUBTimeSlice( 0.0f ) == 1.0f );
00525         TS_ASSERT( ts.getUBTimeSlice( -wlimits::FLT_EPS ) == 0.0f );
00526         TS_ASSERT( ts.getUBTimeSlice( wlimits::FLT_EPS ) == 1.0f );
00527         TS_ASSERT( ts.getUBTimeSlice( 1.0f ) == 2.0f );
00528         TS_ASSERT( ts.getUBTimeSlice( 1.2f ) == 2.0f );
00529         TS_ASSERT( ts.getUBTimeSlice( 2.0f - wlimits::FLT_EPS ) == 2.0f );
00530         TS_ASSERT( ts.getUBTimeSlice( 2.0f ) == inf );
00531         TS_ASSERT( ts.getUBTimeSlice( inf ) == inf );
00532 
00533         // note that there is no test for nan, as these routines are private
00534         // it is the callers responsibility to check for nan
00535     }
00536 
00537 private:
00538     /**
00539      * A helper function that creates some input data.
00540      *
00541      * \param data An array of data values, one for each time slice.
00542      * \param number The number of time slices.
00543      * \param dsets The output datasets.
00544      * \param times Some times for the output datasets.
00545      */
00546     void createData( double* data, int number, DataSetPtrVector& dsets, TimesVector& times ) // NOLINT
00547     {
00548         dsets.clear();
00549         times.clear();
00550 
00551         WMatrix< double > mat( 4, 4 );
00552         mat.makeIdentity();
00553         mat( 0, 0 ) = 1.0;
00554         mat( 1, 1 ) = 0.5;
00555         mat( 2, 2 ) = 2.0;
00556 
00557         WGridTransformOrtho transform( mat );
00558         boost::shared_ptr< WGridRegular3D > g( new WGridRegular3D( 3, 3, 3, transform ) );
00559 
00560         for( int i = 0; i < number; ++i )
00561         {
00562             boost::shared_ptr< std::vector< double > > v( new std::vector< double >( 27, data[i] ) );
00563             boost::shared_ptr< WValueSet< double > > vs( new WValueSet< double >( 0, 1, v, W_DT_DOUBLE ) );
00564             dsets.push_back( boost::shared_ptr< WDataSetScalar const >( new WDataSetScalar( vs, g ) ) );
00565             times.push_back( static_cast< float >( i ) );
00566         }
00567     }
00568 
00569     /**
00570      * Setup logger and other stuff for each test.
00571      */
00572     void setUp()
00573     {
00574         WLogger::startup();
00575     }
00576 };
00577 
00578 #endif  // WDATASETTIMESERIES_TEST_H