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:
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:
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.
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.
Info are avaialable in the doc https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html