OpenWalnut  1.3.1
WDataSetTimeSeries.cpp
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 #include <algorithm>
26 #include <limits>
27 #include <string>
28 #include <vector>
29 
30 #include "../common/WAssert.h"
31 #include "../common/WLimits.h"
32 #include "WDataSetTimeSeries.h"
33 
34 // prototype instance as singleton
35 boost::shared_ptr< WPrototyped > WDataSetTimeSeries::m_prototype = boost::shared_ptr< WPrototyped >();
36 
37 WDataSetTimeSeries::WDataSetTimeSeries( std::vector< boost::shared_ptr< WDataSetScalar const > > datasets,
38  std::vector< float > times )
39  : m_dataSets()
40 {
41  WAssert( !datasets.empty(), "" );
42  WAssert( datasets.size() == times.size(), "" );
43  std::vector< boost::shared_ptr< WDataSetScalar const > >::iterator dit;
44  std::vector< float >::iterator tit;
45  boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( datasets.front()->getGrid() );
46  WAssert( g, "" );
47  dataType d = datasets.front()->getValueSet()->getDataType();
48  m_minValue = datasets.front()->getMin();
49  m_maxValue = datasets.front()->getMax();
50  for( dit = datasets.begin(), tit = times.begin(); dit != datasets.end() && tit != times.end(); ++dit, ++tit )
51  {
52  WAssert( *dit, "" );
53  WAssert( g == boost::shared_dynamic_cast< WGridRegular3D >( ( *dit )->getGrid() ), "" );
54  WAssert( !wlimits::isNaN( *tit ), "" );
55  WAssert( d == ( *dit )->getValueSet()->getDataType(), "" );
56  WAssert( ( *dit )->getValueSet()->dimension() == 1, "" );
57  WAssert( ( *dit )->getValueSet()->order() == 0, "" );
58  m_dataSets.push_back( TimeSlice( *dit, *tit ) );
59  if( m_minValue > ( *dit )->getMin() )
60  {
61  m_minValue = ( *dit )->getMin();
62  }
63  if( m_maxValue < ( *dit )->getMax() )
64  {
65  m_maxValue = ( *dit )->getMax();
66  }
67  }
68  std::sort( m_dataSets.begin(), m_dataSets.end(), TimeSliceCompare() );
69  for( std::size_t k = 1; k < m_dataSets.size(); ++k )
70  {
71  if( m_dataSets[ k ].second == m_dataSets[ k - 1 ].second )
72  {
73  throw WException( std::string( "There are multiple time slices at the same point in time!" ) );
74  }
75  }
76 }
77 
79 {
80 }
81 
82 std::string const WDataSetTimeSeries::getName() const
83 {
84  return std::string( "WDataSetTimeSeries" );
85 }
86 
87 std::string const WDataSetTimeSeries::getDescription() const
88 {
89  return std::string( "A time series." );
90 }
91 
92 boost::shared_ptr< WPrototyped > WDataSetTimeSeries::getPrototype()
93 {
94  if( !m_prototype )
95  {
96  m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetTimeSeries() );
97  }
98 
99  return m_prototype;
100 }
101 
102 bool WDataSetTimeSeries::isTimeSlice( float time ) const
103 {
104  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
105  return f != m_dataSets.end() && f->second == time;
106 }
107 
109 {
110  WAssert( !wlimits::isNaN( time ), "" );
111  if( time > getMaxTime() )
112  {
113  return getMaxTime();
114  }
115  float lb = getLBTimeSlice( time );
116  float ub = getUBTimeSlice( time );
117  return time - lb <= ub - time ? lb : ub;
118 }
119 
120 boost::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::getDataSetPtrAtTimeSlice( float time ) const
121 {
122  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
123  if( f != m_dataSets.end() && f->second == time )
124  {
125  return f->first;
126  }
127  return boost::shared_ptr< WDataSetScalar const >();
128 }
129 
130 boost::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::calcDataSetAtTime( float time, std::string const& name ) const
131 {
132  WAssert( !wlimits::isNaN( time ), "" );
133  if( time < getMinTime() || time > getMaxTime() )
134  {
135  return boost::shared_ptr< WDataSetScalar const >();
136  }
137  float lb = getLBTimeSlice( time );
138  float ub = getUBTimeSlice( time );
139  if( lb == time || ub == time )
140  {
141  // not optimal if the compiler does not inline
142  return getDataSetPtrAtTimeSlice( time );
143  }
144 
145  boost::shared_ptr< WValueSetBase > vs;
146  switch( m_dataSets.front().first->getValueSet()->getDataType() )
147  {
148  case W_DT_UINT8:
149  vs = calcInterpolatedValueSet< uint8_t >( lb, ub, time );
150  break;
151  case W_DT_INT8:
152  vs = calcInterpolatedValueSet< int8_t >( lb, ub, time );
153  break;
154  case W_DT_UINT16:
155  vs = calcInterpolatedValueSet< uint16_t >( lb, ub, time );
156  break;
157  case W_DT_INT16:
158  vs = calcInterpolatedValueSet< int16_t >( lb, ub, time );
159  break;
160  case W_DT_UINT32:
161  vs = calcInterpolatedValueSet< uint32_t >( lb, ub, time );
162  break;
163  case W_DT_SIGNED_INT:
164  vs = calcInterpolatedValueSet< int32_t >( lb, ub, time );
165  break;
166  case W_DT_UINT64:
167  vs = calcInterpolatedValueSet< uint64_t >( lb, ub, time );
168  break;
169  case W_DT_INT64:
170  vs = calcInterpolatedValueSet< int64_t >( lb, ub, time );
171  break;
172  case W_DT_FLOAT:
173  vs = calcInterpolatedValueSet< float >( lb, ub, time );
174  break;
175  case W_DT_DOUBLE:
176  vs = calcInterpolatedValueSet< double >( lb, ub, time );
177  break;
178  default:
179  throw WException( std::string( "Unsupported datatype in WDataSetTimeSeries::calcDataSetAtTime()" ) );
180  break;
181  }
182  boost::shared_ptr< WDataSetScalar > ds( new WDataSetScalar( vs, m_dataSets.front().first->getGrid() ) );
183  ds->setFilename( name );
184  return ds;
185 }
186 
188 {
189  return t0.second < t1.second;
190 }
191 
193 {
194  return t0 < t1.second;
195 }
196 
198 {
199  return t0.second < t1;
200 }
201 
202 float WDataSetTimeSeries::getLBTimeSlice( float time ) const
203 {
204  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
205  float t = -std::numeric_limits< float >::infinity();
206  if( f != m_dataSets.end() && f->second == time )
207  {
208  return time;
209  }
210  if( f != m_dataSets.begin() )
211  {
212  --f;
213  t = f->second;
214  }
215  return t;
216 }
217 
218 float WDataSetTimeSeries::getUBTimeSlice( float time ) const
219 {
220  std::vector< TimeSlice >::const_iterator g = std::upper_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
221  float t = std::numeric_limits< float >::infinity();
222  if( g != m_dataSets.end() )
223  {
224  t = g->second;
225  }
226  return t;
227 }
228 
230  : m_dataSets()
231 {
232 }
233 
235 {
236  return m_minValue;
237 }
238 
240 {
241  return m_maxValue;
242 }