OpenWalnut  1.4.0
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::dynamic_pointer_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::dynamic_pointer_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 }
double m_maxValue
the largest value
A grid that has parallelepiped cells which all have the same proportion.
std::string const getName() const
Returns a name.
std::pair< boost::shared_ptr< WDataSetScalar const >, float > TimeSlice
a time slice
double m_minValue
the smallest value
float getUBTimeSlice(float time) const
Find the smallest time slice position that is larger than time, or return inf, if there is no such ti...
static boost::shared_ptr< WPrototyped > m_prototype
The prototype as singleton.
virtual ~WDataSetTimeSeries()
Destructor.
float getLBTimeSlice(float time) const
Find the largest time slice position that is smaller than or equal to time, or return -inf...
std::string const getDescription() const
Returns a description.
boost::shared_ptr< WDataSetScalar const > getDataSetPtrAtTimeSlice(float time) const
Get a pointer to the dataset at a given time or a NULL-pointer, if there was no dataset given for tha...
double getMaxValue()
Get the largest value in all datasets.
static boost::shared_ptr< WPrototyped > getPrototype()
Returns a prototype instantiated with the true type of the deriving class.
double getMinValue()
Get the smallest value in all datasets.
bool operator()(TimeSlice const &t0, TimeSlice const &t1)
Compares the time of two time slices.
float findNearestTimeSlice(float time) const
Find the nearest time slice for a given time.
dataType
Data types and number values taken from the nifti1.h, at this point it's unknown if it makes sense to...
A compare functor for time slices.
bool isNaN(T value)
Determines if a number is considered as NaN (aka Not a Number) or not.
Definition: WLimits.h:82
WDataSetTimeSeries()
Standard constructor.
bool isTimeSlice(float time) const
Check if there exists a predefined dataset at the given point in time, i.e.
std::vector< TimeSlice > m_dataSets
the datasets that compose the time series
This data set type contains scalars as values.
float getMaxTime() const
Get the last point of time in the time series.
Basic exception handler.
Definition: WException.h:38
boost::shared_ptr< WDataSetScalar const > calcDataSetAtTime(float time, std::string const &name) const
Calculates a new dataset with values interpolated between the two nearest time slices.
float getMinTime() const
Get the first point of time in the time series.