/// <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); }
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); }
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); }
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); }
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); }
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]); }
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]); }
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()); }
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()); }
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]); }
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; }
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; }
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); }
/// <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; }
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); }
/// <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; }
/// <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; }
/// <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); }