Why is Scipy implementation of Hilbert() function different from Matlab implementation of the function?

I am trying to fit Hilbert envelop to a high frequency ultrasonic signal of frequency 250 KHZ and sampling rate 12000000. Raw signal looks like below: .

I used hilbert() function from scipy.signal package in python this is what it looks like .

The python code looks like below

from scipy.signal import hilbert
import numpy as np
def Hilbert(self,i=0):
analytical_signal = hilbert(self.sensor["s"+str(i)])
amplitude_envelope = np.abs(analytical_signal)
return amplitude_envelope

The Matlab implementation looks like this Matlab code is as follows:

figure;
plot(abs(hilbert(signal)),'r');
hold on;
plot(signal,'b');

The line data is as follows Signal. I am wondering which one is correct?

• It seems like there some kind of low-pass filtering in the Matlab code? Care to show us your Matlab code? – Ben Jan 10 '18 at 20:58
• @Ben I am just using the default matlab code hilbert(), I dont think I am using any low pass filter. The edits contain the matlab code – Spandy Jan 10 '18 at 21:54
• For starters, doesn't the hilbert function in Matlab return complex values? If so, I would expect that you plot the module of the hilbert transform and not the complex values. – Ben Jan 10 '18 at 22:16
• @Ben Its absolute of hilbert. There was a typo in matlab code – Spandy Jan 10 '18 at 22:25
• It still seems like you have some kind of smoothing in Matlab. Why not do it with a simple sine wave in both Python and Matlab ? You should get a constant enveloppe – Ben Jan 11 '18 at 14:27

It works fine for me:

from scipy.signal import hilbert
import numpy as np
from matplotlib.pyplot import plot

plot(sensor)

analytical_signal = hilbert(sensor)
plot(analytical_signal.real)
plot(analytical_signal.imag)

amplitude_envelope = np.abs(analytical_signal)
plot(amplitude_envelope)  What are you doing differently? Maybe you're throwing away the imaginary part of analytical_signal somehow?

• could you share your signal.txt, because I am having the same problem as OP. – Dr Sokoban Jul 25 at 11:03
• @DrSokoban The link to the signal is in the original question – endolith Jul 25 at 14:31

You should apply a LPF after applying the hilbert method. Here is an example.

import numpy
from scipy.signal import butter, filtfilt, hilbert
import matplotlib.pyplot as plt

def FilteredSignal(signal, fs, cutoff):
B, A = butter(1, cutoff / (fs / 2), btype='low')
filtered_signal = filtfilt(B, A, signal, axis=0)
return filtered_signal

fs = 10000.
T = .1
time = numpy.arange(0., T, 1 / fs)
frequency = 1000
noise = numpy.random.normal(0, 1, int(fs/10))
signal = numpy.sin(2 * numpy.pi * frequency * time) + 0.2 * noise
analyticSignal = hilbert(signal)
amplitudeEvelope = numpy.abs(analyticSignal)
cutoff = 1000
filteredSignal = FilteredSignal(amplitudeEvelope, fs, cutoff)

fig2, ax2 = plt.subplots(1, 1)
ax2.plot(time, signal)
ax2.plot(time, filteredSignal)
ax2.set_xlabel('Tiempo')
ax2.set_ylabel('Amplitud')
ax2.grid(True)
plt.show()
• There is no lowpass filter in the matlab code. It's just the magnitude of the analytical signal, which should produce an envelope in both cases. – endolith Apr 9 '18 at 19:39

I had the same issue. As https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.hilbert.html says @Notes, you need to need to take the imaginary part of the hilbet transform result... "The Hilbert transformed signal can be obtained from np.imag(hilbert(x)), and the original signal from np.real(hilbert(x))."