faif
Transformations.hpp
1 #ifndef FAIF_TS_TRANSFORMATIONS
2 #define FAIF_TS_TRANSFORMATIONS
3 
4 // file with transformations -> changest real time series into digit one and digit time series into real one
5 
6 #include <ostream>
7 #include <algorithm>
8 #include <boost/bind.hpp>
9 
10 #include <boost/lambda/lambda.hpp>
11 #include <boost/lambda/bind.hpp>
12 #include <boost/lambda/construct.hpp>
13 
14 #include "TimeSeries.hpp"
15 
16 namespace faif {
17  namespace timeseries {
18 
19  /** \brief transformation - class to change timeseries stored in TimeSeriesDigit and/or TimeSeriesReal
20  */
22  public:
23  Transformation(const RealTime& present, const RealDuration& delta)
24  : present_(present), delta_(delta) {}
26  : present_(t.present_), delta_(t.delta_) {}
27  ~Transformation() {}
28 
29  Transformation& operator=(const Transformation& t) {
30  present_ = t.present_;
31  delta_ = t.delta_;
32  return *this;
33  }
34 
35  /** accessor - reference point in time */
36  const RealTime& getPresent() const { return present_; }
37  /** accessor - distance between probes */
38  const RealDuration& getDelta() const { return delta_; }
39 
40  /** transform digit time to real time (gives the reference points in time) */
41  RealTime toReal(const DigitTime& d) const {
42  return RealTime( present_ + delta_ * d);
43  }
44 
45  /** transform real time to digit time
46  D = toDigit(R), then
47  toReal(D) in <R - delta/2;R + delta/2)
48  -- includes R - delta/2
49  -- excludes R + delta/2
50 
51  example: delta=4
52 
53  -2 -1 0 1 2
54  |---|---|---|---|---
55  -2111100001111222233
56  */
57  DigitTime toDigit(const RealTime& r) const {
58  if(delta_.total_seconds() != 0) {
59  //accuracy of the sec
60  long delta_2 = delta_.total_seconds() / 2;
61  RealDuration dur = boost::posix_time::time_period(present_, r).length();
62  long duration_sec = dur.total_seconds() + delta_2;
63  int correction_for_minus = ( (duration_sec >= 0) ? 0 : 1 );
64  long out = (duration_sec + correction_for_minus) / delta_.total_seconds() - correction_for_minus;
65  return out;
66  } else {
67  //accuracy of the millisec
68  long delta_2 = static_cast<long>( delta_.total_milliseconds() / 2 ); //TODO: use long long or __int64 when switch to C++0x
69  RealDuration dur = boost::posix_time::time_period(present_, r).length();
70  long duration_sec = static_cast<long>(dur.total_milliseconds() + delta_2); //TODO: use long long or __int64 when switch to C++0x
71  int correction_for_minus = ( (duration_sec >= 0) ? 0 : 1 );
72  long out = (duration_sec + correction_for_minus) / static_cast<long>(delta_.total_milliseconds() ) - correction_for_minus;
73  return out;
74  }
75 
76  }
77  private:
78  RealTime present_;
79  RealDuration delta_;
80  };
81 
82 
83  namespace {
84 
85  /** function to linear approximation. Given two points (start and end).
86  Calculates all middle points, and add it to collection.
87  */
88  void linearApproximate(DigitTime start_time, DigitTime end_time,
89  Value start_value, Value end_value,
90  Quality start_quality, Quality end_quality,
91  TimeSeriesDigit& out_ts) {
92 
93  for(DigitTime t = start_time + 1; t < end_time; ++t ) {
94 
95  DigitTime proportion_A = end_time - t;
96  DigitTime proportion_B = t - start_time;
97  DigitTime proportion_weight = end_time - start_time;
98 
99  Value v = (start_value * proportion_A + end_value * proportion_B) / proportion_weight;
100  Quality q = (start_quality * proportion_A + end_quality * proportion_B) / proportion_weight;
101  out_ts.push_back( TimeValueDigit(t, v, q) );
102  }
103 
104  }
105 
106 
107  /** counted time value digit - to agregate many probes */
108  struct CountedTimeValue {
109  CountedTimeValue(const DigitTime& time, const TimeValueReal& tv)
110  : time_(time), value_(tv.getValue()), quality_(tv.getQuality()), counter_(1)
111  {}
112 
113  /** add another time value with the same time (aggregate) */
114  void append(const TimeValueReal& tv) {
115  //modyfikuje wartosc
116  value_ += tv.getValue();
117  quality_ += tv.getQuality();
118  ++counter_;
119  }
120  /** accessor */
121  const DigitTime& getTime() const { return time_; }
122 
123  /** return the aggregated time value */
124  TimeValueDigit get() { return TimeValueDigit(time_, value_/counter_, quality_/counter_); }
125  private:
126  DigitTime time_;
127  Value value_;
128  Quality quality_;
129  int counter_;
130  };
131 
132  /** class to transform real time series into digit one */
133  class LinearResampler : boost::noncopyable {
134  public:
135  LinearResampler(const Transformation& trans, const TimeValueReal& first)
136  : trans_(trans),
137  current_(trans_.toDigit(first.getTime()), first ) {}
138  ~LinearResampler() {}
139 
140  /** method called when the given time-value is added to result time-series */
141  void addTimeValue(const TimeValueReal& tv) {
142  DigitTime act_time = trans_.toDigit( tv.getTime() );
143  //cout << tv.getTime() << ' ' << act_time << ' ' << tv.getValue() << endl;
144  if(act_time == current_.getTime() )
145  current_.append(tv);
146  else {
147  addCurrentValue();
148  //check if linear approximation is necessary
149  if(act_time > current_.getTime() + 1) {
150  const TimeValueDigit& last_tv = ts_.back();
151  //linear approximation:
152  linearApproximate( last_tv.getTime(), act_time,
153  last_tv.getValue(), tv.getValue(),
154  last_tv.getQuality(), tv.getQuality(),
155  ts_ );
156  }
157  current_ = CountedTimeValue( act_time, tv );
158  }
159  }
160 
161  /** method called when the last time value could be calculated */
162  void finish() { addCurrentValue(); }
163 
164  /** returns the calculated time series */
165  const TimeSeriesDigit& getTimeSeries() { return ts_; }
166  private:
167  void addCurrentValue() { ts_.push_back( current_.get() ); }
168  const Transformation& trans_;
169  CountedTimeValue current_;
170  TimeSeriesDigit ts_;
171  };
172  } //namespace
173 
174 
175  /** creates digit time series from real time series.
176  Linear resampling: arythmetic everage for aggregation,
177  the linear approxymation for missing data.
178  */
179  inline TimeSeriesDigit create(const TimeSeriesReal& in, const Transformation& transformation) {
180  if( in.empty() )
181  return TimeSeriesDigit();
182  TimeSeriesReal::const_iterator it = in.begin();
183  //initialize with first time value
184  LinearResampler resampler(transformation, *it);
185  ++it;
186  std::for_each( it, in.end(), boost::bind(&LinearResampler::addTimeValue, boost::ref(resampler), _1 ) );
187  resampler.finish();
188  return resampler.getTimeSeries();
189  }
190 
191  /** creates real time series from digit time series.
192  */
193  inline TimeSeriesReal create(const TimeSeriesDigit& in, const Transformation& transformation) {
194  TimeSeriesReal out;
195  std::transform( in.begin(), in.end(), back_inserter(out),
196  boost::lambda::bind( boost::lambda::constructor<TimeValueReal>(),
197  boost::lambda::bind(&Transformation::toReal, boost::ref(transformation),
198  boost::lambda::bind(&TimeValueDigit::getTime, boost::lambda::_1) ),
199  boost::lambda::bind(&TimeValueDigit::getValue, boost::lambda::_1 ),
200  boost::lambda::bind(&TimeValueDigit::getQuality, boost::lambda::_1 ) ) );
201  // bind(&createTV, _1, transformation) );
202  return out;
203  }
204 
205  } //namespace timeseries
206 } //namespace faif
207 
208 #endif //FAIF_TS_TRANSFORMATIONS
timeseries - time hold as RealTime
Definition: TimeSeries.hpp:76
Definition: Chain.h:17
TimeSeriesDigit create(const TimeSeriesReal &in, const Transformation &transformation)
Definition: Transformations.hpp:179
double Quality
quality - real 0..1
Definition: TimeSeries.hpp:51
const Value & getValue() const
Definition: TimeSeries.hpp:140
int DigitTime
digit time type. DigitTime < 0 past, DigitTime >= 0 future, DigitTime == 0 now.
Definition: TimeSeries.hpp:47
double Value
value - real number
Definition: TimeSeries.hpp:49
const RealTime & getTime() const
Definition: TimeSeries.hpp:61
const DigitTime & getTime() const
Definition: TimeSeries.hpp:138
const Quality & getQuality() const
Definition: TimeSeries.hpp:65
RealTime toReal(const DigitTime &d) const
Definition: Transformations.hpp:41
const Quality & getQuality() const
Definition: TimeSeries.hpp:142
const RealDuration & getDelta() const
Definition: Transformations.hpp:38
timeseries value, single value in given real time. Plain old data
Definition: TimeSeries.hpp:54
Definition: TimeSeries.hpp:151
DigitTime toDigit(const RealTime &r) const
Definition: Transformations.hpp:57
Definition: TimeSeries.hpp:131
const Value & getValue() const
Definition: TimeSeries.hpp:63
boost::posix_time::time_duration RealDuration
the real time duration
Definition: TimeSeries.hpp:37
boost::posix_time::ptime RealTime
the real time type
Definition: TimeSeries.hpp:35
transformation - class to change timeseries stored in TimeSeriesDigit and/or TimeSeriesReal ...
Definition: Transformations.hpp:21
const RealTime & getPresent() const
Definition: Transformations.hpp:36