In this Python tutorial, we will learn about the “Scipy Signal” and cover the following topics.
- Scipy Signal
- Scipy Signal Butter
- Scipy Signal Processing
- Scipy Signal Find peaks
- Scipy Signal Convolve
- Scipy Signal Correlate
- Scipy Signal Ifilter
- Scipy Signal Impulse
- Scipy Signal Square
- Scipy Signal Spectrogram
Scipy Signal
The Scipy has a library scipy.signal
to modify, analyze and process the signal like video signal, audio signal, etc.
It has many functions or methods to deal with different kinds of signal problems in the following categories :
- B-splines
- Convolutional
- Filter design
- Filtering
- Continuous-time linear systems
- Matlab-style IIR filter design
- Discrete-time linear systems
- Window functions
- LTI representations
- Waveforms
- Chirp Z-transform and Zoom FFT
- Spectral analysis
- Wavelets
- Peak finding
Each category contains lots of functions, so here we will cover the commonly used methods of some categories.
Read: Scipy Misc + Examples
Scipy Signal Butter
Scipy has a method butter()
to apply the Butterworth filter to the signal. In other words, we can create the design of the digital or analog Butterworth filter of Nth order that flattens the frequency.
The syntax is given below.
scipy.signal.butter(N, Wn, btype='low', analog=False, output='ba', fs=None)
Where parameters are:
- N(int): It is used to specify the filter’s order.
- Wn(array_data): It is used to specify the critical frequencies of highpass and lowpass filters.
- btype: Used to specify which kind of filters to use like bandstop, highpass, lowpass, and bandpass.
- analog(boolean): if it is true, then the analog filter is used, otherwise, in the case of false, a digital filter is used.
- output: It is used to specify the output type like zpk ( ploe-zero), sos (second-order sections), and ba (backward compatibility).
Let’s take an example by following the below steps:
Import the required libraries using the below python code.
from scipy.signal import butter
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Create the time duration of the signal using the below code.
t_duration = np.linspace(0,0.5,2000,False)
Generate a signal of 20 and 40 Hz frequency using the below code.
sign = np.sin(2*np.pi*20*t_duration) + np.sin(2*np.pi*40*t_duration)
Plot the created signal using the below code.
fig, (ax1) = plt.subplots(1, 1, sharex=True)
ax1.plot(t_duration, sign)
ax1.set_title('20 and 40 Hz Sinusoid')
ax1.axis([0, 0.5, -2, 2.5])
Create a Butterworth high pass filter of 25 Hz and apply it to the above-created signal using the below code.
from scipy import signal
sos = butter(15, 20, 'hp', fs=2000, output='sos')
filtd = signal.sosfilt(sos, sign)
Plot the signal after applying the filter using the below code.
fig, (ax2) = plt.subplots(1, 1, sharex=True)
ax2.plot(t_duration, filtd)
ax2.set_title('After applying 20 Hz high-pass filter')
ax2.axis([0, 0.5, -2, 2.5])
ax2.set_xlabel('Time (seconds)')
plt.tight_layout()
plt.show()
This is how to apply Butterworth on the signal.
Read: Scipy Integrate + Examples
Scipy Signal Find peaks
The Scipy has a method find_peaks()
within a module scipy.signal
that returns all the peaks on the basis of given peak properties.
The syntax is given below.
scipy.signal.find_peaks(x, height=1, prominence=4, distance=2, width=2, threshold=1, rel_height=0.5, wlen=1, )
Where parameters are:
- x(sequence): It is used to accept the signal having peaks.
- height(sequence,ndarray, number): It is used to provide the peak height.
- threshold(sequence, ndarray, number): It is used to provide the peak threshold.
- distance(number): It is used to provide the minimum horizontal distance between adjacent peaks.
- prominence(sequence,ndarray, number): It is used to provide peak prominence.
- width(sequence,ndarray, number): It is used to provide the width of the peak.
- wlen(int): It is used to calculate the peak prominence.
- rel_height(int): It is used to calculate the peak height.
Let’s take an example by following the below steps:
Import the required library using the below python code.
from scipy.signal import find_peaks
from scipy.misc import electrocardiogram
import matplotlib.pyplot as plt
%matplotlib inline
Generate an electrocardiogram using the below code.
value = electrocardiogram()[1000:5000]
Now the peaks using the below code.
peak, _ = find_peaks(value, height=0)
plt.plot(value)
plt.plot(peak, value[peak], "*")
plt.plot(np.zeros_like(value), "--", color="green")
plt.show()
This is how to find all peaks of the signal.
Read: Scipy Stats – Complete Guide
Scipy Signal Convolve
The Scipy has a method convolve()
in module scipy.signal
that returns the third signal by combining two signals.
The syntax is given below.
scipy.signal.convolve(in1, in2, mode='full', method='auto')
Where parameters are:
- in1(array_data): It is used to input the first signal in the form of an array.
- in2(array_data): It is used to input the second signal in the form of an array, the dimension must be the same as the first input array.
- mode: It is used to specify the string that determines the size of the output. The mode can be
same
,full
andvalid
. - method: It is used to specify the method that computes the convolution. The method can be
auto
,direct
andfft
.
Let’s understand with an example by following the below steps:
Import the required library using the below python code.
from scipy.signal import convolve
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Create two different signals using the below code.
signal_1 = np.repeat([1., 2., 1.], 50)
signal_2 = np.repeat([2., 4., 5.], 50)
Now add both signals to create a third signal using the below code.
conv = signal.convolve(signal_1, signal_2, mode='same') / sum(signal_2)
Let’s plot the above signals using the below code.
fig, (ax_actual, ax_sig_1, ax_conv) = plt.subplots(3, 1, sharex=True)
ax_actual.plot(signal_1)
ax_actual.set_title('Actual pulse')
ax_actual.margins(0, 0.1)
ax_sig_1.plot(signal_2)
ax_sig_1.set_title(' It is the Filter impulse response')
ax_sig_1.margins(0, 0.1)
ax_conv.plot(conv)
ax_conv.set_title('Convolved signal')
ax_conv.margins(0, 0.1)
fig.tight_layout()
fig.show()
This how-to generates the third signal by combining two different signals.
Read: Scipy Rotate Image + Examples
Scipy Signal Correlate
The Scipy has a method correlate()
within a module scipy.signal
that is similar to the method scipy.signal.convolve()
. It also generates the third signal by adding two signals and the generated signal is known as cross correlation
.
The syntax is given below.
scipy.signal.correlate(in1, in2, mode='full', method='auto')
Where parameters are:
- in1(array_data): It is used to input the first signal in the form of an array.
- in2(array_data): It is used to input the second signal in the form of an array, the dimension must be the same as the first input array.
- mode: It is used to specify the string that determines the size of the output. The mode can be
same
,full
andvalid
. - method: It is used to specify the method that computes the convolution. The method can be
auto
,direct
andfft
.
Let’s understand with an example by following the below steps:
Import the required library using the below python code.
from scipy.signal import correlate
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Create two different signals using the below code.
signal_1 = np.repeat([1., 2., 1.], 50)
signal_2 = np.repeat([2., 4., 5.], 50)
Now add both signals to create a third signal using the below code.
conv = signal.correlate(signal_1, signal_2, mode='same') / sum(signal_2)
Let’s plot the above signals using the below code.
fig, (ax_actual, ax_sig_1, ax_conv) = plt.subplots(3, 1, sharex=True)
ax_actual.plot(signal_1)
ax_actual.set_title('Actual pulse')
ax_actual.margins(0, 0.1)
ax_sig_1.plot(signal_2)
ax_sig_1.set_title(' It is the Filter impulse response')
ax_sig_1.margins(0, 0.1)
ax_conv.plot(conv)
ax_conv.set_title('Correlated signal')
ax_conv.margins(0, 0.1)
fig.tight_layout()
fig.show()
This is how to correlate the signals using Scipy in Python.
Read: Scipy Optimize – Helpful Guide
Scipy Signal Ifilter
The Scipy has a method ifilter()
within module scipy.signal
that clean the signal data in one dimension using the filter Finite Impulse Respose
(FIR) or Infinite Impulse Response
.
The syntax is given below.
scipy.signal.lfilter(b, a, x, axis=- 1, zi=None)
Where parameters are:
- b(array_data): It is a one-dimension sequence of vectors containing numerator coefficients.
- a(array_data): It is a one-dimension sequence of vectors containing denominator coefficients.
- x(array_data): It is ndarray as an input.
- axis(int): It is the name of the axis of the given array one to which a linear filter is applied.
- zi(array_data): It is used to specify the initial condition to hold up the filter.
The above method returns two values y
and zi
.
Let’s see with an example using the below steps:
Import the required libraries using the below python code.
from scipy.signal import lfilter,butter,filtfilt
import matplotlib.pyplot as plt
import numpy as np
Create a noisy signal that we are going to filter using the below code.
rng = np.random.default_rng()
array_data = np.linspace(-2, 2, 302)
sin_data = (np.sin(2*np.pi*0.65*array_data*(1-array_data) + 1.1) +
0.2*np.sin(2*np.pi*2.1*array_data + 1) +
0.20*np.cos(2*np.pi*2.58*array_data))
noisy_data = sin_data + rng.standard_normal(len(array_data)) * 0.07
Design Lowpass Butterworth filter of order 4 using the below code.
num_coff, deno_coff = butter(4, 0.06)
Let’s implement the filter on the noisy data.
zi = lfilter_zi(num_coff, deno_coff)
z, _ = lfilter(num_coff, deno_coff, noisy_data, zi=zi*noisy_data[0])
Implement the filter again.
z2, _ =lfilter(num_coff, deno_coff, z, zi=zi*z[0])
Now implement the filtfilt filter.
y = filtfilt(num_coff, deno_coff, noisy_data)
Plot all signals using the below code.
plt.figure
plt.plot(array_data, noisy_data, 'b', alpha=0.75)
plt.plot(array_data, z, 'r--', array_data, z2, 'r', array_data, y, 'k')
plt.legend(('This is noisy one', 'lfilter, once', 'lfilter, twice',
'This is filtfilt one'), loc='best')
plt.grid(True)
plt.show()
This is how to filter the noisy signal using the method lfilter()
.
Read: Scipy Sparse – Helpful Tutorial
Scipy Signal Impulse
The Scipy has a method impulse()
within scipy module scipy.signal
that is the retort of the continuous-time system in reply to external changes.
The syntax is given below.
scipy.signal.impulse(system, X0=None, T=None, N=None)
Where parameters are:
- system(tuple of array_data): It is used to define the systems.
- X0(array_data): It is the initial state array vector.
- T(array_data): It is the time points.
- N(int): To calculate the no of time points, use this parameter.
The method returns two values T
and yout
.
Let’s see with an example by following the below steps:
Import the required libraries using the below python code.
import matplotlib.pyplot as plt
from scipy.signal import impulse
Create a system using the below code.
sys = ([2.1], [2.1, 3.1, 2.1])
time_pts, impulse_res = signal.impulse(sys)
Now plot the generated impulse using the below code.
plt.plot(time_pts,impulse_res)
This is how to use the impulse method of the module scipy.signal
.
Read: Scipy Constants – Multiple Examples
Scipy Signal Square
The Scipy module scipy.signal
contains a method square()
that generates the waveform as a square wave.
The syntax is given below.
scipy.signal.square(t, duty=0.5)
Where parameters are:
- t(array_data): It is array data as input.
- duty(array_data): It is used to define the duty cycle, by default it is 0.5.
The method returns y
of type ndarray that contains the square wave.
Let’s generate a square waveform by following the below steps:
Import the required libraries using the below python code.
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import square
Create an array of data and square wave data using the below code.
array_data = np.linspace(0, 2, 1000, endpoint=False)
square_wave = square(2 * np.pi * 2 * array_data)
Now plot the created square waveform using the below code.
plt.plot(array_data,square_wave)
plt.ylim(-1.5, 1.5)
This is how to create a square waveform using Scipy in the Python program.
Read: Scipy Convolve – Complete Guide
Scipy Signal Spectrogram
The Scipy has a method spectrogram()
in a module scipy.signal
that shows the strength of a signal over time on different frequencies of a specific waveform.
The syntax is given below.
scipy.signal.spectrogram(x, fs=1.0, window=('tukey', 1), nperseg=None, noverlap=None, nfft=None, detrend='constant', return_onesided=False, axis=- 1, mode='psd')
Where parameters are:
- x(array_data): It is time series.
- fs(float): Used to provide time-series sampling frequency.
- window(array_data, tuple, string): It is used to specify what kind of window we want to implement.
- nperseg(int): To specify the length of every segment.
- nooverlap(int): It is used to specify the no of points to overlay among segments.
- nfft(int): It is the size of the FFT.
- detrend(False, string, function): Used to specify how to remove the trend from each segment.
- return_onesided(boolean): To get the side of the spectrum of data. If true, then it returns the one-sided, otherwise in the case of false returns the two-sided.
- axis(int): It is used to specify the along which axis to calculate the spectrogram.
- mode(string): To specify how we want the expected value like angle, magnitude, phase, complex, and PSD.
The method returns three values f
(frequencies as an array), t
(segment times as array) and sxx
(spectrogram).
Let’ understand with an example by following the below steps:
Import the required libraries using the below python code.
from scipy.signal import spectrogram
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fftshift
Defining the values of the required parameters to generate the signal using the below code.
rng = np.random.default_rng()
sample_fre = 9e3
n = 1e3
amp = 3 * np.sqrt(3)
noisep = 0.02 * sample_fre / 3
time_data = np.arange(n) / float(sample_fre)
mode = 600*np.cos(3*np.pi*0.4*time_data)
car_rier = amp * np.sin(3*np.pi*4e4*time_data + mode)
gen_noise = rng.normal(scale=np.sqrt(noisep), size=time_data.shape)
gen_noise *= np.exp(-time_data/5)
signal_data = car_rier + gen_noise
Now calculate and show the spectrogram using the below code.
sample_freq, segment_time, spectrogram = spectrogram(signal_data, sample_fre)
plt.pcolormesh(segment_time, sample_freq, spectrogram, shading='gouraud')
plt.ylabel('It is frequency in Hertz')
plt.xlabel('It is time in second')
plt.show()
This is how to compute the spectrogram using scipy in Python.
Also, take a look at some more Scipy tutorials.
So, in this tutorial, we have learned about the “Scipy Signal” and covered the following topics.
- Scipy Signal
- Scipy Signal Butter
- Scipy Signal Processing
- Scipy Signal Find peaks
- Scipy Signal Convolve
- Scipy Signal Correlate
- Scipy Signal Ifilter
- Scipy Signal Impulse
- Scipy Signal Square
- Scipy Signal Spectrogram
I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.