[TOC]
Imports System
Imports System.IO
Imports CenterSpace.NMath.Core
Namespace CenterSpace.NMath.Core.Examples.VisualBasic
' A .NET example in VB.NET showing the Savitzky-Golay algorithm for smoothing.
Module MovingWindowFilterExample
Sub Main()
Dim SignalLength As Integer = 2000
Console.WriteLine()
Dim Signal As DoubleVector = NoisySignal(SignalLength)
Dim noisySignalVariance As Double = NMathFunctions.Variance(Signal)
Console.WriteLine("Noisy signal variance = " & noisySignalVariance)
' Set up a moving average filter with an asymmetric window. A moving window
' filter replaces each input data point with a linear combination of
' its surrounding points. A filter is thus described by the number of
' of points to the left and right of the input point and the coefficients
' of the linear combination.
' This filter will replace each input data point with the average of
' its value with the 4 values to the left, and the 5 values to the right.
' Thus the coeffients to use are all equal to one over the number of points
' in the window, 10 in this case.
Dim numberLeft As Integer = 4
Dim numberRight As Integer = 5
Dim filterCoefficients As DoubleVector = MovingWindowFilter.MovingAverageCoefficients(numberLeft, numberRight)
Dim movingAverageFilter As New MovingWindowFilter(numberLeft, numberRight, filterCoefficients)
' Filter the signal. Note that we must specify a boundary option. When
' replacing the first input value, we don't have any points to the left, similarly, when
' replacing the last input value, we don't have any point to the right. The "PadWithZeros"
' boundary option prepends "numberLeft" zeros and appends "numberRight" zeros to the
' input vector to deal with this.
Dim filteredSignal As DoubleVector = movingAverageFilter.Filter(Signal, MovingWindowFilter.BoundaryOption.PadWithZeros)
Dim filteredSignalVariance As Double = NMathFunctions.Variance(filteredSignal)
Console.WriteLine("Moving Average: filtered signal variance = " & filteredSignalVariance)
' Set up a Savitzky-Golay filter. This is a smoothing filter that replaces input values with
' the value of a polynomial of specified degree fit through the input value and its
' surrounding points. A least squares algorithm is used to determine the fitting polynomial.
Dim Degree As Integer = 4
filterCoefficients = MovingWindowFilter.SavitzkyGolayCoefficients(numberLeft, numberRight, Degree)
Dim savitzkyGolayFilter As New MovingWindowFilter(numberLeft, numberRight, filterCoefficients)
' Filter the signal. Here we use a different boundary option: "DoNotFilterBoundaryPoints".
' This option will not filter or replace the first "numberLeft" or last "numberRight"
' values of the input signal.
filteredSignal = savitzkyGolayFilter.Filter(Signal, MovingWindowFilter.BoundaryOption.DoNotFilterBoundaryPoints)
filteredSignalVariance = NMathFunctions.Variance(filteredSignal)
Console.WriteLine("Savitzky-Golay: filtered signal variance = " & filteredSignalVariance)
Console.WriteLine()
' If you are filtering lots of signals with the same length, it is more
' economic to use the "Filter" method which allows you to specify
' the vector to place the output filtered signal in. This avoids having
' to allocate potentially large vectors on every call to "Filter".
Dim NumSignals As Integer = 10
Dim noisySignals As DoubleMatrix = NoisySignalsFunction(SignalLength, NumSignals)
Dim Y As New DoubleVector(Signal.Length)
Dim I As Integer
For I = 0 To NumSignals - 1
Dim S As DoubleVector = noisySignals.Col(I)
Console.WriteLine(String.Format("Noisy signal {0} variance = {1}", I, NMathFunctions.Variance(S)))
savitzkyGolayFilter.Filter(S, MovingWindowFilter.BoundaryOption.PadWithZeros, Y)
Console.WriteLine(String.Format("Savitzky-Golay filtered signal {0} variance = {1}", I, NMathFunctions.Variance(Y)))
Console.WriteLine()
Next
Console.WriteLine()
Console.WriteLine("Press Enter Key")
Console.Read()
End Sub
Function NoisySignal(ByVal Length As Integer) As DoubleVector
Dim rng As New RandGenNormal()
Dim Signal As New DoubleVector(Length)
Dim I As Integer
For I = 0 To Length - 1
Signal(I) = Math.Cos(0.2 * I) + rng.Next()
Next
Return Signal
End Function
Function NoisySignalsFunction(ByVal Rows As Integer, ByVal Columns As Integer) As DoubleMatrix
Dim RNG As New RandGenNormal()
Dim signals As New DoubleMatrix(Rows, Columns)
Dim i, j As Integer
For i = 0 To Rows - 1
For j = 0 To Columns - 1
signals(i, j) = Math.Cos(0.2 * i * j) + RNG.Next()
Next
Next
Return signals
End Function
End Module
End Namespace
[TOC]