Scipy Signal – Helpful Tutorial

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])
Scipy Signal Butter example
Scipy Signal Butter example

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()
Scipy Signal Butter
Scipy Signal Butter

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 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()
Scipy Signal Find peaks
Scipy Signal Find peaks

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 and valid.
  • method: It is used to specify the method that computes the convolution. The method can be auto, direct and fft.

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()
Scipy Signal Convolve
Scipy Signal Convolve

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 and valid.
  • method: It is used to specify the method that computes the convolution. The method can be auto, direct and fft.

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()
Scipy Signal Correlate
Scipy Signal Correlate

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
Scipy Signal Ifilter example
Scipy Signal Ifilter example

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()
Scipy Signal Ifilter
Scipy Signal Ifilter

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)
Scipy Signal Impulse
Scipy Signal Impulse

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)
Scipy Signal Square
Scipy Signal Square

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()
Scipy Signal Spectrogram
Scipy Signal Spectrogram

This is how to compute the spectrogram using scipy in Python.

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