OpenWalnut  1.4.0
WDataSetTimeSeries.cpp
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 #include <algorithm>
00026 #include <limits>
00027 #include <string>
00028 #include <vector>
00029 
00030 #include "../common/WAssert.h"
00031 #include "../common/WLimits.h"
00032 #include "WDataSetTimeSeries.h"
00033 
00034 // prototype instance as singleton
00035 boost::shared_ptr< WPrototyped > WDataSetTimeSeries::m_prototype = boost::shared_ptr< WPrototyped >();
00036 
00037 WDataSetTimeSeries::WDataSetTimeSeries( std::vector< boost::shared_ptr< WDataSetScalar const > > datasets,
00038                                         std::vector< float > times )
00039     : m_dataSets()
00040 {
00041     WAssert( !datasets.empty(), "" );
00042     WAssert( datasets.size() == times.size(), "" );
00043     std::vector< boost::shared_ptr< WDataSetScalar const > >::iterator dit;
00044     std::vector< float >::iterator tit;
00045     boost::shared_ptr< WGridRegular3D > g = boost::dynamic_pointer_cast< WGridRegular3D >( datasets.front()->getGrid() );
00046     WAssert( g, "" );
00047     dataType d = datasets.front()->getValueSet()->getDataType();
00048     m_minValue = datasets.front()->getMin();
00049     m_maxValue = datasets.front()->getMax();
00050     for( dit = datasets.begin(), tit = times.begin(); dit != datasets.end() && tit != times.end(); ++dit, ++tit )
00051     {
00052         WAssert( *dit, "" );
00053         WAssert( g == boost::dynamic_pointer_cast< WGridRegular3D >( ( *dit )->getGrid() ), "" );
00054         WAssert( !wlimits::isNaN( *tit ), "" );
00055         WAssert( d == ( *dit )->getValueSet()->getDataType(), "" );
00056         WAssert( ( *dit )->getValueSet()->dimension() == 1, "" );
00057         WAssert( ( *dit )->getValueSet()->order() == 0, "" );
00058         m_dataSets.push_back( TimeSlice( *dit, *tit ) );
00059         if( m_minValue > ( *dit )->getMin() )
00060         {
00061             m_minValue = ( *dit )->getMin();
00062         }
00063         if( m_maxValue < ( *dit )->getMax() )
00064         {
00065             m_maxValue = ( *dit )->getMax();
00066         }
00067     }
00068     std::sort( m_dataSets.begin(), m_dataSets.end(), TimeSliceCompare() );
00069     for( std::size_t k = 1; k < m_dataSets.size(); ++k )
00070     {
00071         if( m_dataSets[ k ].second == m_dataSets[ k - 1 ].second )
00072         {
00073             throw WException( std::string( "There are multiple time slices at the same point in time!" ) );
00074         }
00075     }
00076 }
00077 
00078 WDataSetTimeSeries::~WDataSetTimeSeries()
00079 {
00080 }
00081 
00082 std::string const WDataSetTimeSeries::getName() const
00083 {
00084     return std::string( "WDataSetTimeSeries" );
00085 }
00086 
00087 std::string const WDataSetTimeSeries::getDescription() const
00088 {
00089     return std::string( "A time series." );
00090 }
00091 
00092 boost::shared_ptr< WPrototyped > WDataSetTimeSeries::getPrototype()
00093 {
00094     if( !m_prototype )
00095     {
00096         m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetTimeSeries() );
00097     }
00098 
00099     return m_prototype;
00100 }
00101 
00102 bool WDataSetTimeSeries::isTimeSlice( float time ) const
00103 {
00104     std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
00105     return f != m_dataSets.end() && f->second == time;
00106 }
00107 
00108 float WDataSetTimeSeries::findNearestTimeSlice( float time ) const
00109 {
00110     WAssert( !wlimits::isNaN( time ), "" );
00111     if( time > getMaxTime() )
00112     {
00113         return getMaxTime();
00114     }
00115     float lb = getLBTimeSlice( time );
00116     float ub = getUBTimeSlice( time );
00117     return time - lb <= ub - time ? lb : ub;
00118 }
00119 
00120 boost::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::getDataSetPtrAtTimeSlice( float time ) const
00121 {
00122     std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
00123     if( f != m_dataSets.end() && f->second == time )
00124     {
00125         return f->first;
00126     }
00127     return boost::shared_ptr< WDataSetScalar const >();
00128 }
00129 
00130 boost::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::calcDataSetAtTime( float time, std::string const& name ) const
00131 {
00132     WAssert( !wlimits::isNaN( time ), "" );
00133     if( time < getMinTime() || time > getMaxTime() )
00134     {
00135         return boost::shared_ptr< WDataSetScalar const >();
00136     }
00137     float lb = getLBTimeSlice( time );
00138     float ub = getUBTimeSlice( time );
00139     if( lb == time || ub == time )
00140     {
00141         // not optimal if the compiler does not inline
00142         return getDataSetPtrAtTimeSlice( time );
00143     }
00144 
00145     boost::shared_ptr< WValueSetBase > vs;
00146     switch( m_dataSets.front().first->getValueSet()->getDataType() )
00147     {
00148     case W_DT_UINT8:
00149         vs = calcInterpolatedValueSet< uint8_t >( lb, ub, time );
00150         break;
00151     case W_DT_INT8:
00152         vs = calcInterpolatedValueSet< int8_t >( lb, ub, time );
00153         break;
00154     case W_DT_UINT16:
00155         vs = calcInterpolatedValueSet< uint16_t >( lb, ub, time );
00156         break;
00157     case W_DT_INT16:
00158         vs = calcInterpolatedValueSet< int16_t >( lb, ub, time );
00159         break;
00160     case W_DT_UINT32:
00161         vs = calcInterpolatedValueSet< uint32_t >( lb, ub, time );
00162         break;
00163     case W_DT_SIGNED_INT:
00164         vs = calcInterpolatedValueSet< int32_t >( lb, ub, time );
00165         break;
00166     case W_DT_UINT64:
00167         vs = calcInterpolatedValueSet< uint64_t >( lb, ub, time );
00168         break;
00169     case W_DT_INT64:
00170         vs = calcInterpolatedValueSet< int64_t >( lb, ub, time );
00171         break;
00172     case W_DT_FLOAT:
00173         vs = calcInterpolatedValueSet< float >( lb, ub, time );
00174         break;
00175     case W_DT_DOUBLE:
00176         vs = calcInterpolatedValueSet< double >( lb, ub, time );
00177         break;
00178     default:
00179         throw WException( std::string( "Unsupported datatype in WDataSetTimeSeries::calcDataSetAtTime()" ) );
00180         break;
00181     }
00182     boost::shared_ptr< WDataSetScalar > ds( new WDataSetScalar( vs, m_dataSets.front().first->getGrid() ) );
00183     ds->setFilename( name );
00184     return ds;
00185 }
00186 
00187 bool WDataSetTimeSeries::TimeSliceCompare::operator() ( TimeSlice const& t0, TimeSlice const& t1 )
00188 {
00189     return t0.second < t1.second;
00190 }
00191 
00192 bool WDataSetTimeSeries::TimeSliceCompare::operator() ( float const& t0, TimeSlice const& t1 )
00193 {
00194     return t0 < t1.second;
00195 }
00196 
00197 bool WDataSetTimeSeries::TimeSliceCompare::operator() ( TimeSlice const& t0, float const& t1 )
00198 {
00199     return t0.second < t1;
00200 }
00201 
00202 float WDataSetTimeSeries::getLBTimeSlice( float time ) const
00203 {
00204     std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
00205     float t = -std::numeric_limits< float >::infinity();
00206     if( f != m_dataSets.end() && f->second == time )
00207     {
00208         return time;
00209     }
00210     if( f != m_dataSets.begin() )
00211     {
00212         --f;
00213         t = f->second;
00214     }
00215     return t;
00216 }
00217 
00218 float WDataSetTimeSeries::getUBTimeSlice( float time ) const
00219 {
00220     std::vector< TimeSlice >::const_iterator g = std::upper_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
00221     float t = std::numeric_limits< float >::infinity();
00222     if( g != m_dataSets.end() )
00223     {
00224         t = g->second;
00225     }
00226     return t;
00227 }
00228 
00229 WDataSetTimeSeries::WDataSetTimeSeries()
00230     : m_dataSets()
00231 {
00232 }
00233 
00234 double WDataSetTimeSeries::getMinValue()
00235 {
00236     return m_minValue;
00237 }
00238 
00239 double WDataSetTimeSeries::getMaxValue()
00240 {
00241     return m_maxValue;
00242 }