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_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