示例#1
0
        /// <summary>
        /// Applies the delta function to each pair of consecutive values.
        /// </summary>
        /// <param name="ts">A time series</param>
        /// <returns></returns>
        public Timeseries Apply(Timeseries ts)
        {
            const string paramNameTs = "ts";

            if (ts == null)
            {
                throw new ArgumentException("Must be non-null", paramNameTs);
            }

            //if (ts.Count < 2) throw new ArgumentException("ts must contain at least two elements", paramNameTs);

            var result = new Timeseries();

            using (var enumerator = ts.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    throw new ArgumentException("ts must contain at least two elements", paramNameTs);
                }

                var previous = enumerator.Current;
                result.Add(new Tvq(previous.Time, 0, Quality.Ok)); // trying to indicate that the consumption starts at 0, but that may not work well if algorithms extrapolate backwards
                while (enumerator.MoveNext())
                {
                    var current = enumerator.Current;
                    var delta   = CalculateDelta(current, previous);
                    result.Add(delta);
                    previous = current;
                }
            }
            return(result);
        }
示例#2
0
        public void Apply_WhenAverageAndOneValueAtStart_ReturnsValue()
        {
            // Arrange
            _ts.Add(_tvqs.Tvq20150301);

            // Act
            var result = _aggregate.Apply(_average, _ts);

            // Assert
            Assert.Equal(result.First().V, _tvqs.Tvq20150301.V);
        }
示例#3
0
        public void SplitPerYear_WhenOnly20150101_ReturnsOneEnumerableWithTheValue()
        {
            var ts = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Equal(1, result.Count);
        }
示例#4
0
        public void SplitPerYear_WhenOnly20150101_ReturnsOneEnumerableWithTheValue()
        {
            var ts     = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Single(result);
        }
示例#5
0
        private Timeseries Create(DateTime tvq20160201, int nValues, int v0, int delta)
        {
            var ts = new Timeseries();

            for (int i = 0; i < nValues; i++)
            {
                ts.Add(new Tvq(tvq20160201.AddMonths(i), v0 + i * delta, Quality.Ok));
            }
            return(ts);
        }
示例#6
0
        public void SplitPerYear_WhenOnlyOneYear_ReturnsOneEnumerableWithAllValues()
        {
            var ts = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101).Add(m_Tvqs.Tvq20150601);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Equal(1, result.Count);
            Assert.Equal(2, result[0].Count);
            Assert.Equal(m_Tvqs.Tvq20150101, result[0][0]);
            Assert.Equal(m_Tvqs.Tvq20150601, result[0][1]);
        }
示例#7
0
        public void SplitPerYear_WhenOnlyOneYear_ReturnsOneEnumerableWithAllValues()
        {
            var ts     = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101).Add(m_Tvqs.Tvq20150601);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Single(result);
            Assert.Equal(2, result[0].Count);
            Assert.Equal(m_Tvqs.Tvq20150101, result[0][0]);
            Assert.Equal(m_Tvqs.Tvq20150601, result[0][1]);
        }
示例#8
0
        public void SplitPerYear_WhenOneEachYear_ReturnsTwoEnumerablesWithEachOneValue()
        {
            var ts     = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101).Add(m_Tvqs.Tvq20160101);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Equal(2, result.Count);
            Assert.Single(result[0]);
            Assert.Single(result[1]);
            Assert.Equal(m_Tvqs.Tvq20150101, result[0].First());
            Assert.Equal(m_Tvqs.Tvq20160101, result[1].First());
        }
示例#9
0
        public void SplitPerYear_WhenOneEachYear_ReturnsTwoEnumerablesWithEachOneValue()
        {
            var ts = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101).Add(m_Tvqs.Tvq20160101);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Equal(2, result.Count);
            Assert.Equal(1, result[0].Count);
            Assert.Equal(1, result[1].Count);
            Assert.Equal(m_Tvqs.Tvq20150101, result[0].First());
            Assert.Equal(m_Tvqs.Tvq20160101, result[1].First());
        }
示例#10
0
        public void SplitPerYear_WhenTwoPerYear_Returns2EnumerablesWith2Values()
        {
            var ts     = new Timeseries();
            var source = ts.Add(m_Tvqs.Tvq20150101)
                         .Add(m_Tvqs.Tvq20150601)
                         .Add(m_Tvqs.Tvq20160101)
                         .Add(m_Tvqs.Tvq20160601);

            var result = m_Periodizer.SplitPerYear(source).ToList();

            Assert.Equal(2, result.Count);
            Assert.Equal(2, result[0].Count);
            Assert.Equal(2, result[1].Count);
            Assert.Equal(m_Tvqs.Tvq20150101, result[0][0]);
            Assert.Equal(m_Tvqs.Tvq20150601, result[0][1]);
            Assert.Equal(m_Tvqs.Tvq20160101, result[1][0]);
            Assert.Equal(m_Tvqs.Tvq20160601, result[1][1]);
        }
示例#11
0
        public Timeseries Apply(IUnaryAggregateOperator op, Timeseries ts)
        {
            if (ts == null || ! ts.Any()) return new Timeseries();

            var result = new Timeseries();

            // Default to monthly
            var t = ts.First().Time;
            do
            {
                var t0 = new DateTime(t.Year, t.Month, 1, 0, 0, 0);
                var t1 = new DateTime(t.Year, t.Month, DateTime.DaysInMonth(t.Year, t.Month), 23, 59, 59);
                result.Add(op.Apply(t0, t1, ts));
                t = t0.AddMonths(1);
            } while (t <= ts.Last().Time);

            return result;
        }
示例#12
0
        public static Timeseries ParseTimeseries(string tabSeparatedTimeseries)
        {
            var reader = new StringReader(tabSeparatedTimeseries);
            var result = new Timeseries();

            var line = reader.ReadLine();
            while (line != null)
            {
                var trimmedLine = line.Trim();
                if (!string.IsNullOrEmpty(trimmedLine))
                {
                    var tvq = ParseLine(trimmedLine);
                    result.Add(tvq);
                }
                line = reader.ReadLine();
            }

            return result;
        }
示例#13
0
        public static Timeseries ParseTimeseries(string tabSeparatedTimeseries)
        {
            var reader = new StringReader(tabSeparatedTimeseries);
            var result = new Timeseries();

            var line = reader.ReadLine();

            while (line != null)
            {
                var trimmedLine = line.Trim();
                if (!string.IsNullOrEmpty(trimmedLine))
                {
                    var tvq = ParseLine(trimmedLine);
                    result.Add(tvq);
                }
                line = reader.ReadLine();
            }

            return(result);
        }
示例#14
0
        /// <summary>
        /// Applies the delta function to each pair of consecutive values.
        /// </summary>
        /// <param name="ts">A time series</param>
        /// <returns></returns>
        public Timeseries Apply(Timeseries ts)
        {
            const string paramNameTs = "ts";
            if (ts == null) throw new ArgumentException("Must be non-null", paramNameTs);

            if (ts.Count < 2) throw new ArgumentException("ts must contain at least two elements", paramNameTs);

            var result = new Timeseries();

            var enumerator = ts.GetEnumerator();
            enumerator.MoveNext();
            var previous = enumerator.Current;
            while (enumerator.MoveNext())
            {
                var current = enumerator.Current;
                var delta = CalculateDelta(current, previous);
                result.Add(delta);
                previous = current;
            }

            return result;
        }
示例#15
0
        public Timeseries Apply(IUnaryAggregateOperator op, Timeseries ts)
        {
            if (ts == null || !ts.Any())
            {
                return(new Timeseries());
            }

            var result = new Timeseries();

            // Default to monthly
            var t = ts.First().Time;

            do
            {
                var t0 = new DateTime(t.Year, t.Month, 1, 0, 0, 0);
                var t1 = new DateTime(t.Year, t.Month, DateTime.DaysInMonth(t.Year, t.Month), 23, 59, 59);
                result.Add(op.Apply(t0, t1, ts));
                t = t0.AddMonths(1);
            } while (t <= ts.Last().Time);

            return(result);
        }
示例#16
0
        /// <summary>
        /// Inserts point at the specified interval by attempting to interpolate and/or
        /// extrapolate values. Useful when splitting up a period into several series
        /// and displaying calculated start/end values in a graph.
        /// </summary>
        /// <param name="ts"></param>
        /// <param name="intervalLength"></param>
        /// <returns>A new timeseries that has values at the start and end of the interval</returns>
        /// <example>
        /// TODO FB
        /// </example>
        public Timeseries InsertPoints(Timeseries ts, Interval intervalLength)
        {
            if (ReferenceEquals(ts, null))
            {
                throw new ArgumentException("ts");
            }

            var result   = new Timeseries();
            Tvq previous = null;

            for (var i = 0; i < ts.Count; i++)
            {
                var current       = ts[i];
                var isNewInterval =
                    i == 0 ||
                    previous != null && IsNewInterval(previous.Time, current.Time, intervalLength);

                //
                // Previous interval end?
                //
                var doInsertPreviousEnd = isNewInterval && previous != null;  // && not last second
                if (doInsertPreviousEnd)
                {
                    var lastSecondOfPrevious = LastSecondOfInterval(previous.Time, intervalLength);
                    var tvq = Tvq.CalculateValueAt(lastSecondOfPrevious, previous, current);
                    result.Add(tvq);
                }

                if (previous != null)
                {
                    var hasEmptyIntervalInBetween =
                        HasEmptyIntervalInBetween(previous.Time, current.Time, intervalLength);
                    var t = previous.Time;
                    while (hasEmptyIntervalInBetween)
                    {
                        t = FirstSecondOfNextInterval(t, intervalLength);
                        var tvq = Tvq.CalculateValueAt(t, previous, current);
                        result.Add(tvq);

                        var tLastSecond = LastSecondOfInterval(t, intervalLength);
                        tvq = Tvq.CalculateValueAt(tLastSecond, previous, current);
                        result.Add(tvq);

                        hasEmptyIntervalInBetween = HasEmptyIntervalInBetween(t, current.Time, intervalLength);
                    }
                }

                //
                // Current interval start?
                //
                var firstSecond = FirstSecond(current.Time, intervalLength);
                if (isNewInterval && current.Time > firstSecond)
                {
                    var newTvq = previous == null ?
                                 new Tvq(firstSecond, current.V, Quality.Interpolated) : Tvq.CalculateValueAt(firstSecond, previous, current);
                    result.Add(newTvq);
                }

                //
                // Add point
                //
                result.Add(current);

                previous = current;
            }

            if (ts.Any())
            {
                if (previous != null)
                {
                    var lastSecond = LastSecondOfInterval(previous.Time, intervalLength);

                    var iLast   = ts.Count - 1;
                    var lastTvq = ts.Last();

                    if (ts.Count <= 1 && lastTvq.Time < lastSecond)
                    {
                        var newTvq = new Tvq(lastSecond, lastTvq.V, Quality.Interpolated);
                        result.Add(newTvq);
                    }
                    else if (lastTvq.Time < lastSecond)
                    {
                        var newTvq = Tvq.CalculateValueAt(lastSecond, ts[iLast - 1], lastTvq);
                        result.Add(newTvq);
                    }
                }
            }
            return(result);
        }
 private Timeseries Create(DateTime tvq20160201, int nValues, int v0, int delta)
 {
     var ts = new Timeseries();
     for (int i = 0; i < nValues; i++)
     {
         ts.Add(new Tvq(tvq20160201.AddMonths(i), v0 + i*delta, Quality.Ok));
     }
     return ts;
 }
示例#18
0
        /// <summary>
        /// Inserts point at the specified interval by attempting to interpolate and/or 
        /// extrapolate values. Useful when splitting up a period into several series
        /// and displaying calculated start/end values in a graph.
        /// </summary>
        /// <param name="ts"></param>
        /// <param name="intervalLength"></param>
        /// <returns>A new timeseries that has values at the start and end of the interval</returns>
        public Timeseries InsertPoints(Timeseries ts, Interval intervalLength)
        {
            if (ReferenceEquals(ts, null)) throw new ArgumentException("ts");

            var result = new Timeseries();
            Tvq previous = null;
            for (var i = 0; i < ts.Count; i++)
            {
                var current = ts[i];
                var isNewInterval =
                    i == 0 ||
                    (previous != null && previous.Time.Year != current.Time.Year);

                //
                // Previous interval end?
                //
                var doInsertPreviousEnd = isNewInterval && previous != null ; // && not last second
                if (doInsertPreviousEnd)
                {
                    var lastSecondOfPrevious = new DateTime(previous.Time.Year, 12, 31, 23, 59, 59);
                    var tvq = Tvq.CalculateValueAt(lastSecondOfPrevious, previous, current);
                    result.Add(tvq);
                }

                //
                // Current interval start?
                //
                var t = current.Time;
                var firstSecond = new DateTime(t.Year, 01, 01, 0, 0, 0);
                if (isNewInterval && t > firstSecond)
                {
                    var newTvq = previous == null ?
                        new Tvq(firstSecond, current.V, Quality.Interpolated) : Tvq.CalculateValueAt(firstSecond, previous, current);
                    result.Add(newTvq);
                }

                result.Add(current);

                previous = current;
            }

            if (ts.Any())
            {
                if (previous != null)
                {
                    var lastSecond = new DateTime(previous.Time.Year, 12, 31, 23, 59, 59);

                    var iLast = ts.Count - 1;
                    var lastTvq = ts.Last();

                    if (ts.Count <= 1 && lastTvq.Time < lastSecond)
                    {
                        var newTvq = new Tvq(lastSecond, lastTvq.V, Quality.Interpolated);
                        result.Add(newTvq);
                    }
                    else if (lastTvq.Time < lastSecond)
                    {
                        var newTvq = Tvq.CalculateValueAt(lastSecond, ts[iLast - 1], lastTvq);
                        result.Add(newTvq);
                    }
                }
            }
            return result;
        }
示例#19
0
        /// <summary>
        /// Periodizes a time series with relative consumption
        /// </summary>
        /// <param name="op"></param>
        /// <param name="ts">A time series with relative consumption, without roll over or meter change</param>
        /// <param name="interval"></param>
        /// <returns></returns>
        private Timeseries Periodize(IUnaryAggregateOperator op, Timeseries ts, Interval interval)
        {
            var result = new Timeseries();

            using (var enumerator = ts.GetEnumerator())
            {
                DateTime?intervalStart     = null;
                DateTime nextIntervalStart = DateTime.MinValue;
                var      areMoreValues     = enumerator.MoveNext();
                Tvq      currentTvq        = null;
                Tvq      previousTvq;
                Tvq      nextTvq      = enumerator.Current;
                var      doNeedToMove = true;
                double   sumForPeriod = 0;
                while (areMoreValues)
                {
                    // Setup previous, current and next if we need to
                    enumerator.MoveNext();
                    previousTvq = currentTvq;
                    currentTvq  = nextTvq;
                    nextTvq     = enumerator.Current;
                    Debug.Assert(currentTvq != null);

                    // Initialize interval
                    if (!intervalStart.HasValue)
                    {
                        intervalStart     = FirstSecond(currentTvq.Time, interval);
                        nextIntervalStart = FirstSecondOfNextInterval(intervalStart.Value, interval);
                        sumForPeriod      = 0;
                    }

                    Debug.Assert(currentTvq.Time >= intervalStart);
                    Debug.Assert(currentTvq.Time <= nextIntervalStart);

                    do  // next value may be many periods ahead
                    {
                        if (nextTvq == null)
                        {
                            if (previousTvq != null) // Prevent input with only one value from entering
                            {
                                sumForPeriod +=
                                    currentTvq.V
                                    / (currentTvq.Time - previousTvq.Time).TotalDays
                                    * (nextIntervalStart - previousTvq.Time).TotalDays; // Extrapolate consumption to end of interval
                            }

                            result.Add(new Tvq(intervalStart.Value, sumForPeriod, Quality.Interpolated));
                            sumForPeriod = 0;
                        }
                        else if (nextIntervalStart <= nextTvq.Time)
                        {
                            doNeedToMove = false;

                            sumForPeriod += currentTvq.V;

                            var remainingConsumptionBelongingToThisPeriod = nextTvq.V
                                                                            * (nextIntervalStart - currentTvq.Time).TotalDays
                                                                            / (nextTvq.Time - currentTvq.Time).TotalDays;

                            var consumptionInPeriod =
                                sumForPeriod
                                + remainingConsumptionBelongingToThisPeriod;
                            result.Add(new Tvq(intervalStart.Value, consumptionInPeriod, Quality.Interpolated));
                            sumForPeriod = -remainingConsumptionBelongingToThisPeriod - currentTvq.V; // This is how much of nextTvq.V that we already have added.

                            intervalStart     = nextIntervalStart;
                            nextIntervalStart = FirstSecondOfNextInterval(intervalStart.Value, interval);
                        }
                        else
                        {
                            sumForPeriod += currentTvq.V;
                            doNeedToMove  = true;
                        }
                    } while (!doNeedToMove);

                    areMoreValues = nextTvq != null;
                }
            }
            return(result);
        }