0

I am trying to plot a spectrogram of an EEG signal whose sampling rate of 1000Hz and is filtered with a bandpass of 14 - 70 Hz, and the length of the signal is 440 ( and I cant increase the length of the signal). The signal(data link here) looks like this:

image_orginal_signal

I have tried the following parameter values to plot the spectrogram:

#plot spectrogram for a single channel
fs = 1000
nperseg = 200

plt.figure(figsize=(10,10))

f, t, Sxx = signal.spectrogram(Oz[0], fs, nperseg=nperseg, noverlap=nperseg-1)

plt.pcolormesh(t, f, Sxx, shading='gouraud')
plt.ylim([0,70])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()

which gave a plot like this:

spectrogram_of_signal

Can anyone suggest ideal parameter settings to improve the spectrogram resolution?

EDIT: To enhance my query, I want to know how the value of parameters like nperseg, nfft, window_size and noverlap are decided. And How would they be related if I have sampling rate(fs) and length of signal.

Alankrit
  • 658
  • 1
  • 6
  • 17
  • 1
    I think this question should not be asked on StackOverflow. Find a medical or physical StackExchange... – vossmalte May 10 '22 at 05:54
  • What do you mean with "optimal" here? Computing a spectrogram is a question of tradeoffs with time vs frequency resolution. Plotting it is another issue in itself. So please describe more fully what you hoped for, and why the result you have is not satisfactory. – LudvigH May 10 '22 at 07:23

1 Answers1

3

I don't know what output you expect but out can try to change the shading of the pcolormesh. Also you can add a window to the computation of the spectrogram. You can also change the colors use to represent the spectrogram with cmap.

import matplotlib.pyplot as plt
import numpy as np
from scipy import signal

my_data = np.genfromtxt('signal_value_spectro.csv', delimiter=',',skip_header=0)

Oz=my_data[1:,0]
fs = 1000
t = np.arange(len(Oz))/fs


# nperseg = len(Oz[0])-1
nperseg=50
f50, t50, Sxx_50 = signal.spectrogram(Oz, fs, nperseg=nperseg , noverlap=nperseg-1,window=signal.get_window('hann',nperseg))
nperseg=150
f150, t150, Sxx_150 = signal.spectrogram(Oz, fs, nperseg=nperseg , noverlap=nperseg-1,window=signal.get_window('hann',nperseg))
nperseg=350
f350, t350, Sxx_350 = signal.spectrogram(Oz, fs, nperseg=nperseg , noverlap=nperseg-1,window=signal.get_window('hann',nperseg))

plt.figure(figsize=(10,10))
plt.subplot(211)
plt.plot(np.arange(len(Oz))/fs,Oz)  
plt.subplot(234)
plt.pcolormesh(t50, f50, Sxx_50, shading='auto',cmap = 'inferno')
plt.ylim([0,70])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec], nperseg = 50')
plt.subplot(235)
plt.pcolormesh(t150, f150, Sxx_150, shading='auto',cmap = 'inferno')
plt.ylim([0,70])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec], nperseg = 150')
plt.subplot(236)
plt.pcolormesh(t350, f350, Sxx_350, shading='auto',cmap = 'inferno')
plt.ylim([0,70])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec], nperseg = 350')


plt.show()

But your big issue is the length of your signal. You are limited by the time-frequency resolution. Basically the number of frequency band you will get is the length of nperseg divided by 2, spread over the interval [0, FS/2]. As your signal is 440 samples, the nperseg should be lover. But if you increase the nperseg too much, you will loose the time resolution. For instance, if nperseg = 50, there will be 390 point in time but id nperseg = 350 there will only be 90 point in time.

enter image description here

Info are avaialable in the doc https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html

ymmx
  • 4,769
  • 5
  • 32
  • 64
  • Thank you, @ymnx for your answer. I have updated my question to be more specific. I need help understanding how the value of parameters like nperseg, nfft, window_size and noverlap are decided. And How would they be related if I have sampling rate(fs) and length of signal. – Alankrit May 10 '22 at 14:05
  • Everything is in the documentation : https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html. I've edited the post – ymmx May 10 '22 at 16:28