Created
July 21, 2017 18:01
-
-
Save mvacha/a1315ab6a4697905441551e6d2e4e5d1 to your computer and use it in GitHub Desktop.
C# implementation of Thresholding algorithm used for peek (and through) detection from https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data/22771985
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Algo from: https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data/22771985 | |
/// </summary> | |
public static (IList<double> avg, IList<double> sd, IList<int> detected) | |
ThresholdingAlgo(this IList<double> values, int windowSize, double threshold, double influence){ | |
//number in constructor represent capacity, not size | |
var avg = new List<double>(values.Count); | |
var mad = new List<double>(values.Count); | |
var filteredValues = new List<double>(values.Count); //used for calculating avg and sd | |
var signals = new List<int>(values.Count); | |
//init lists | |
avg.AddRange(Enumerable.Repeat(double.NaN, values.Count)); | |
mad.AddRange(Enumerable.Repeat(double.NaN, values.Count)); | |
filteredValues.AddRange(values.Take(windowSize)); | |
signals.AddRange(Enumerable.Repeat(0, values.Count)); | |
//eval first step of running mean/mad (insert at index windowSize-1) | |
avg[windowSize - 1] = filteredValues.Take(windowSize).Average(); | |
mad[windowSize - 1] = filteredValues.Take(windowSize).MedianAbsoluteDeviation(); //used mad instead of sd from original algo | |
for (int i = windowSize; i < values.Count; i++) | |
{ | |
//adding one to mad to combat false detections when mad was really low, not part of original algo | |
if (Math.Abs(values[i]) > avg[i - 1] + threshold * (1 + mad[i - 1])) | |
{ | |
if (values[i] > avg[i - 1]) | |
signals[i] = 1; | |
else | |
signals[i] = -1; | |
filteredValues.Add(influence * values[i] + (1 - influence) * filteredValues[i - 1]); | |
} | |
else | |
{ | |
filteredValues.Add(values[i]); | |
} | |
//bug - takes windowsSize + 1 value to count | |
//left intentionally in code to achieve same results as referential implementation/pseudocode | |
//should start at (i - windowSize + 1) and take only (windowSize items) | |
avg[i] = filteredValues.Skip(i - windowSize).Take(windowSize + 1).Average(); | |
mad[i] = filteredValues.Skip(i - windowSize).Take(windowSize + 1).MedianAbsoluteDeviation(); | |
} | |
return (avg, mad, signals); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment