2
$\begingroup$

I am trying to remove low frequencies from a signal and intuitively I chose the high-pass filter, more specifically - a Butterworth filter, Order 4 (because I am not sure how to choose properly the order and 4 seemed as a good choice) and cutoff frequency of 50 Hz. The problem is, that the filter removes the low frequencies, however, the peaks that were caused from those low frequencies are still to be seen.

I have read also about adaptive filtering, but according to the literature, I need a reference signal, which would be used as a desired signal. I tried implementing an adaptive RLS/LMS filter and as a reference signal, I processed my data with a low-pass filter - Butterworth, 4th Order, 50 Hz for the cutoff frequency. This method also did not get me far.

I have provided a a copy of my data, which is sampled at 1500 Hz. enter image description here

$\endgroup$
  • 1
    $\begingroup$ Can you please clarify what you mean by "remove low frequencies" for your signal? Are you trying to remove the "blips" that seem to appear roughly every 1 second in this signal? $\endgroup$ – Atul Ingle Aug 26 '17 at 21:31
  • 4
    $\begingroup$ Your fundamental mistake is that eventhough those heartbeat peaks have a period which approximately gives a fundamental frequency of 35 Hz, the quasi periodic beat pattern do have many harmonics in higher frequencies as a matter of continuous Fouerier series analysis. You should either try a comb filter, or use a nonlinear and/or time varying filter (an example is an adaptive filter) to remove those peaks without degrading the original signal. $\endgroup$ – Fat32 Aug 26 '17 at 23:49
  • 1
    $\begingroup$ Rather than talking about removing unwanted signal, of you look at the spectrum of your unfiltered signal, can you point out where your signal of interest lies? $\endgroup$ – Marcus Müller Aug 26 '17 at 23:59
  • 1
    $\begingroup$ Or even more important: what is your signal of interest? This might be a case of xyproblem.info $\endgroup$ – Marcus Müller Aug 27 '17 at 0:00
  • 1
    $\begingroup$ "I am interested in … the error" That requires you to define the error between which and what! So, what error are you talking about? $\endgroup$ – Marcus Müller Aug 27 '17 at 9:45
5
$\begingroup$

You want to remove the heart beat signal and keep the "noise". We can solve this problem by using a denoising algorithm, and subtracting the denoised signal from the original signal.

Setting frequency cutoffs for a frequency domain filter can get tricky and turn into a game of whack-a-mole because there's "high frequency" components in the heartbeat blip (due to the sudden rise and fall) and also in the wiggly stuff between a heart beat's T wave and the next heart beat's P wave.

Loosely speaking, the requirements in this de-noising problem are as follows:

  • Remove the little wiggles
  • Maintain larger jumps that appear in a heart beat PQRST waveform

This sounds like a great place to apply $\ell_1$ denoising or total variation denoising. The idea is to approximate the given signal $y$ with a signal $x$ such that the derivative of $x$ is "sparse" i.e. it doesn't change too frequently, but when it changes, the change is large. The denoised estimate $\hat x$ is given by: $$ \hat x = \min_x ||y-x||_2^2 +\lambda\sum|x_i-x_{i-1}| $$

I used proxTV toolbox in Python to solve this optimization problem.

import scipy.io as sio
import numpy as np
import matplotlib.pyplot as plt
import prox_tv as ptv

mat_struct = sio.loadmat('Signal1.mat')
noisy_signal = mat_struct['x'].T[0]

filtered_signal = ptv.tv1_1d(noisy_signal, 50)

time_vec = np.linspace(0, len(noisy_signal)/1500., len(noisy_signal))

plt.close('all')

fig, ax = plt.subplots(3,1,sharex=True)

ax[0].plot(time_vec,noisy_signal)
ax[0].set_title('noisy signal')

ax[1].plot(time_vec,filtered_signal)
ax[1].set_title('filtered signal')

ax[2].plot(time_vec,noisy_signal - filtered_signal)
ax[2].set_title('noise')
ax[2].set_xlabel('time (s)')

plt.tight_layout()
plt.show(block=False)

And here's the resulting plot: enter image description here

Of course, there's a different kind of whack-a-mole you'll have to play with this technique: the $\lambda$ parameter which I set to $50$ in the code.

$\endgroup$
  • $\begingroup$ Thanks! I will test it on my computer as well! However, I would like to ask what is the cause for the peaks on the places, where the QRS was? $\endgroup$ – filtfilt Aug 28 '17 at 0:47
  • $\begingroup$ The algorithm isn't perfect after all! You'll notice, by playing with the $\lambda$ parameter, you can get those peaks to go away, at the price of adding some extra wiggles in the filtered signal. Also note that the y axis labels on the bottom subplot are different, about 1/10th of those of the top two. $\endgroup$ – Atul Ingle Aug 28 '17 at 2:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.