Skip to content

Instantly share code, notes, and snippets.

@lnacquaroli
Last active May 18, 2021 19:40
Show Gist options
  • Save lnacquaroli/c97fbc9a15488607e236b3472bcdf097 to your computer and use it in GitHub Desktop.
Save lnacquaroli/c97fbc9a15488607e236b3472bcdf097 to your computer and use it in GitHub Desktop.
Implementation of the Saviztky-Golay filter in julia version 1.0 or later. Adapted from: https://github.com/BBN-Q/Qlab.jl/blob/master/src/SavitskyGolay.jl
"""
Polynomial smoothing with the Savitzky Golay filters. Adapted for julia >= 1.0.
Sources: https://github.com/BBN-Q/Qlab.jl/blob/master/src/SavitskyGolay.jl
Requires LinearAlgebra and DSP modules loaded.
"""
function savitzkyGolay(x::Vector, windowSize::Int, polyOrder::Int; deriv::Int=0)
isodd(windowSize) || throw("Window size must be an odd integer.")
polyOrder < windowSize || throw("Polynomial order must me less than window size.")
halfWindow = Int( ceil((windowSize-1)/2) )
# Setup the S matrix of basis vectors
S = zeros.(windowSize, polyOrder+1)
for ct = 0:polyOrder
S[:,ct+1] = (-halfWindow:halfWindow).^(ct)
end
## Compute the filter coefficients for all orders
# From the scipy code it seems pinv(S) and taking rows should be enough
G = S * pinv(S' * S)
# Slice out the derivative order we want
filterCoeffs = G[:, deriv+1] * factorial(deriv)
# Pad the signal with the endpoints and convolve with filter
paddedX = [x[1]*ones(halfWindow); x; x[end]*ones(halfWindow)]
y = conv(filterCoeffs[end:-1:1], paddedX)
# Return the valid midsection
return y[2*halfWindow+1:end-2*halfWindow]
end
@henry2004y
Copy link

The result from this function is not entirely correct. As someone else posted on StackOverflow, e.g

x=[1,2,3,4,5,6,7,8,9,10]
savitzkyGolay(x,5,1)

The expected values are exactly x, but the Julia results are not.

@lnacquaroli
Copy link
Author

Can you provide the SO link please. Also, could you submit an issue here. Thanks for reporting.

@lnacquaroli
Copy link
Author

You could also check this implementation to check.

@lnacquaroli
Copy link
Author

Note that the values at the edges are actually not handled correctly.

@henry2004y
Copy link

Note that the values at the edges are actually not handled correctly.

Yes, exactly. I will submit an issue.

@lnacquaroli
Copy link
Author

There is a standalone package for the Savitzky-Golay filter: check SavitzkyGolay.jl

@henry2004y
Copy link

Thank you for making this small package!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment