OpenWalnut  1.5.0dev
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 <memory>
28 #include <string>
29 #include <vector>
30 
31 #include "../common/WAssert.h"
32 #include "../common/WLimits.h"
33 #include "WDataSetTimeSeries.h"
34 
35 // prototype instance as singleton
36 std::shared_ptr< WPrototyped > WDataSetTimeSeries::m_prototype = std::shared_ptr< WPrototyped >();
37 
38 WDataSetTimeSeries::WDataSetTimeSeries( std::vector< std::shared_ptr< WDataSetScalar const > > datasets,
39  std::vector< float > times )
40  : m_dataSets()
41 {
42  WAssert( !datasets.empty(), "" );
43  WAssert( datasets.size() == times.size(), "" );
44  std::vector< std::shared_ptr< WDataSetScalar const > >::iterator dit;
45  std::vector< float >::iterator tit;
46  std::shared_ptr< WGridRegular3D > g = std::dynamic_pointer_cast< WGridRegular3D >( datasets.front()->getGrid() );
47  WAssert( g, "" );
48  dataType d = datasets.front()->getValueSet()->getDataType();
49  m_minValue = datasets.front()->getMin();
50  m_maxValue = datasets.front()->getMax();
51  for( dit = datasets.begin(), tit = times.begin(); dit != datasets.end() && tit != times.end(); ++dit, ++tit )
52  {
53  WAssert( *dit, "" );
54  WAssert( g == std::dynamic_pointer_cast< WGridRegular3D >( ( *dit )->getGrid() ), "" );
55  WAssert( !wlimits::isNaN( *tit ), "" );
56  WAssert( d == ( *dit )->getValueSet()->getDataType(), "" );
57  WAssert( ( *dit )->getValueSet()->dimension() == 1, "" );
58  WAssert( ( *dit )->getValueSet()->order() == 0, "" );
59  m_dataSets.push_back( TimeSlice( *dit, *tit ) );
60  if( m_minValue > ( *dit )->getMin() )
61  {
62  m_minValue = ( *dit )->getMin();
63  }
64  if( m_maxValue < ( *dit )->getMax() )
65  {
66  m_maxValue = ( *dit )->getMax();
67  }
68  }
69  std::sort( m_dataSets.begin(), m_dataSets.end(), TimeSliceCompare() );
70  for( std::size_t k = 1; k < m_dataSets.size(); ++k )
71  {
72  if( m_dataSets[ k ].second == m_dataSets[ k - 1 ].second )
73  {
74  throw WException( std::string( "There are multiple time slices at the same point in time!" ) );
75  }
76  }
77 }
78 
80 {
81 }
82 
83 std::string const WDataSetTimeSeries::getName() const
84 {
85  return std::string( "WDataSetTimeSeries" );
86 }
87 
88 std::string const WDataSetTimeSeries::getDescription() const
89 {
90  return std::string( "A time series." );
91 }
92 
93 std::shared_ptr< WPrototyped > WDataSetTimeSeries::getPrototype()
94 {
95  if( !m_prototype )
96  {
97  m_prototype = std::shared_ptr< WPrototyped >( new WDataSetTimeSeries() );
98  }
99 
100  return m_prototype;
101 }
102 
103 bool WDataSetTimeSeries::isTimeSlice( float time ) const
104 {
105  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
106  return f != m_dataSets.end() && f->second == time;
107 }
108 
110 {
111  WAssert( !wlimits::isNaN( time ), "" );
112  if( time > getMaxTime() )
113  {
114  return getMaxTime();
115  }
116  float lb = getLBTimeSlice( time );
117  float ub = getUBTimeSlice( time );
118  return time - lb <= ub - time ? lb : ub;
119 }
120 
121 std::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::getDataSetPtrAtTimeSlice( float time ) const
122 {
123  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
124  if( f != m_dataSets.end() && f->second == time )
125  {
126  return f->first;
127  }
128  return std::shared_ptr< WDataSetScalar const >();
129 }
130 
131 std::shared_ptr< WDataSetScalar const > WDataSetTimeSeries::calcDataSetAtTime( float time, std::string const& name ) const
132 {
133  WAssert( !wlimits::isNaN( time ), "" );
134  if( time < getMinTime() || time > getMaxTime() )
135  {
136  return std::shared_ptr< WDataSetScalar const >();
137  }
138  float lb = getLBTimeSlice( time );
139  float ub = getUBTimeSlice( time );
140  if( lb == time || ub == time )
141  {
142  // not optimal if the compiler does not inline
143  return getDataSetPtrAtTimeSlice( time );
144  }
145 
146  std::shared_ptr< WValueSetBase > vs;
147  switch( m_dataSets.front().first->getValueSet()->getDataType() )
148  {
149  case W_DT_UINT8:
150  vs = calcInterpolatedValueSet< uint8_t >( lb, ub, time );
151  break;
152  case W_DT_INT8:
153  vs = calcInterpolatedValueSet< int8_t >( lb, ub, time );
154  break;
155  case W_DT_UINT16:
156  vs = calcInterpolatedValueSet< uint16_t >( lb, ub, time );
157  break;
158  case W_DT_INT16:
159  vs = calcInterpolatedValueSet< int16_t >( lb, ub, time );
160  break;
161  case W_DT_UINT32:
162  vs = calcInterpolatedValueSet< uint32_t >( lb, ub, time );
163  break;
164  case W_DT_SIGNED_INT:
165  vs = calcInterpolatedValueSet< int32_t >( lb, ub, time );
166  break;
167  case W_DT_UINT64:
168  vs = calcInterpolatedValueSet< uint64_t >( lb, ub, time );
169  break;
170  case W_DT_INT64:
171  vs = calcInterpolatedValueSet< int64_t >( lb, ub, time );
172  break;
173  case W_DT_FLOAT:
174  vs = calcInterpolatedValueSet< float >( lb, ub, time );
175  break;
176  case W_DT_DOUBLE:
177  vs = calcInterpolatedValueSet< double >( lb, ub, time );
178  break;
179  default:
180  throw WException( std::string( "Unsupported datatype in WDataSetTimeSeries::calcDataSetAtTime()" ) );
181  break;
182  }
183  std::shared_ptr< WDataSetScalar > ds( new WDataSetScalar( vs, m_dataSets.front().first->getGrid() ) );
184  ds->setFilename( name );
185  return ds;
186 }
187 
189 {
190  return t0.second < t1.second;
191 }
192 
194 {
195  return t0 < t1.second;
196 }
197 
199 {
200  return t0.second < t1;
201 }
202 
203 float WDataSetTimeSeries::getLBTimeSlice( float time ) const
204 {
205  std::vector< TimeSlice >::const_iterator f = std::lower_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
206  float t = -std::numeric_limits< float >::infinity();
207  if( f != m_dataSets.end() && f->second == time )
208  {
209  return time;
210  }
211  if( f != m_dataSets.begin() )
212  {
213  --f;
214  t = f->second;
215  }
216  return t;
217 }
218 
219 float WDataSetTimeSeries::getUBTimeSlice( float time ) const
220 {
221  std::vector< TimeSlice >::const_iterator g = std::upper_bound( m_dataSets.begin(), m_dataSets.end(), time, TimeSliceCompare() );
222  float t = std::numeric_limits< float >::infinity();
223  if( g != m_dataSets.end() )
224  {
225  t = g->second;
226  }
227  return t;
228 }
229 
231  : m_dataSets()
232 {
233 }
234 
236 {
237  return m_minValue;
238 }
239 
241 {
242  return m_maxValue;
243 }
This data set type contains scalars as values.
A compare functor for time slices.
bool operator()(TimeSlice const &t0, TimeSlice const &t1)
Compares the time of two time slices.
float getLBTimeSlice(float time) const
Find the largest time slice position that is smaller than or equal to time, or return -inf,...
static std::shared_ptr< WPrototyped > m_prototype
The prototype as singleton.
std::pair< std::shared_ptr< WDataSetScalar const >, float > TimeSlice
a time slice
std::vector< TimeSlice > m_dataSets
the datasets that compose the time series
float getMinTime() const
Get the first point of time in the time series.
float getMaxTime() const
Get the last point of time in the time series.
WDataSetTimeSeries()
Standard constructor.
float findNearestTimeSlice(float time) const
Find the nearest time slice for a given time.
std::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.
virtual ~WDataSetTimeSeries()
Destructor.
double getMinValue()
Get the smallest value in all datasets.
double m_minValue
the smallest value
static std::shared_ptr< WPrototyped > getPrototype()
Returns a prototype instantiated with the true type of the deriving class.
std::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.
std::string const getName() const
Returns a name.
std::string const getDescription() const
Returns a description.
double m_maxValue
the largest value
bool isTimeSlice(float time) const
Check if there exists a predefined dataset at the given point in time, i.e.
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...
Basic exception handler.
Definition: WException.h:39
dataType
Data types and number values taken from the nifti1.h, at this point it's unknown if it makes sense to...
bool isNaN(T value)
Determines if a number is considered as NaN (aka Not a Number) or not.
Definition: WLimits.h:96