How can I combine complex spectrogram results as an image for multi-channel EEG signal?

14 ビュー (過去 30 日間)
Funda KUTLU ONAY
Funda KUTLU ONAY 2019 年 10 月 31 日
コメント済み: Daniel M 2020 年 6 月 24 日
I would like to put my multi-channel EEG spectrogram results upside down to get a single image and ad save it. How can I do this? Thank you.
  4 件のコメント
Funda KUTLU ONAY
Funda KUTLU ONAY 2019 年 10 月 31 日
stft.PNG
That's exactly what I want. To obtain a single image from different channels.
Or how can I use the spectrogram() function to get such an image?

サインインしてコメントする。

回答 (3 件)

Daniel M
Daniel M 2019 年 10 月 31 日
Take all your outputs from spectrogram, and assuming they are all sampled at the same time/freqs, just stack them (concatenate) vertically. Then you can use either imagesc or surf (with view([0,90])) to plot them. They both have their own different characteristics. Then just set your ticks and labels to be how you want them. See this post for how to do that.
  3 件のコメント
Daniel M
Daniel M 2019 年 10 月 31 日
Can you upload a .mat file here, along with the script you're using to create the figure?
Funda KUTLU ONAY
Funda KUTLU ONAY 2019 年 10 月 31 日
Fs=500; ws=250; ov=ws/2; nfft = 2^nextpow2(length(dt));
ss=[];
for i=1:8
[s f t]=spectrogram(dt(:,i),chebwin(ws),ov,Fs);
ss=[ss;s]
end
[s f t]=spectrogram(dt(:,i),chebwin(ws),ov,Fs);
surf(t, f, 20*log10(abs(s)), 'EdgeColor', 'none');
axis xy;
axis tight;
colormap(jet); view(0,90);
Now I can't set the t and f values. So, I can only draw one right now.
How do I draw 'ss' data which is the combination of 8 channels?

サインインしてコメントする。


Daniel M
Daniel M 2019 年 10 月 31 日
It usually takes a lot of work to get a figure to look just right. Here is what I came up with quickly, you can play around with it. See the attached figure. I left extra tidbits in the comments that might help your process.
You might want to try smoothing your data, either at the raw data level (i.e. additional preprocessing to remove noise, rereference channels, notch filter, etc.), at the spectrogram level (different windows, different overlaps), or at the visual level (there are functions that can smooth figures like this, such as smoothn on the FileExchange).
clearvars
close all
clc
mydata = load('mydata.mat');
dt = mydata.dt;
% look at the effects of detrending
figure
subplot(2,1,1)
plot(dt)
title('Raw data')
subplot(2,1,2)
plot(detrend(dt))
title('Detrended data')
dt = detrend(mydata.dt);
Fs=500;
ws=250;
ov=ws/2;
nfft = 2^nextpow2(length(dt));
% I'm sure you could preallocate s based on chebwin(ws) and ov, etc.
for i=1:8
[s(:,:,i), f, t]=spectrogram(dt(:,i),chebwin(ws),ov,Fs);
% since f and t should all be equal.
end
% you probably want to specify your own frequency set, as an input to
% spectrogram()
val = 20*log(abs(s));
% figure
% s1 = surf(t,f,val(:,:,1));
% view([0 90])
% set(s1,'EdgeColor','none')
% title('surf')
% xlabel('Time [s]')
% ylabel('Frequency [Hz]')
% c1 = colorbar;
% ylabel(c1,'Power/frequency')
% axis tight
f1 = figure;
i1 = imagesc(t,f,val(:,:,1));
ax1 = gca;
set(ax1,'YDir','normal')
% title('imagesc')
xlabel('Time [s]')
ylabel('Frequency [Hz]')
c2 = colorbar;
ylabel(c2,'Power/frequency')
% concatenate them such that val2 =
% [val(:,:,1); val(:,:,2);....; val(:,:,end)]
val2 = reshape(permute(val,[1 3 2]),[],19,1);
nchans = size(dt,2);
ff = repmat(f,nchans,1);
ff = 1:size(val2,1);
% get ytick and yticklabel based off ax1
ax1_tick = get(ax1,'YTick');
ftick_ax1 = round(interp1(f,1:length(f),ax1_tick(1:2:end-1))); % rounding is fine here
% need to replicate this
ftick = ftick_ax1' + length(f).*(0:nchans-1);
ftick = ftick(:);
ax1_label = get(ax1,'YTickLabel');
fticklabel = repmat(ax1_label(1:2:end-1),nchans,1);
% Look at a histogram of val2 to get a sense of the tails. If there are
% some extreme values, your colorbar (showing the min and max) will look
% odd.
% figure
% histogram(val2(:))
% Plot all channels
f2 = figure('Position',[680 378 805 600]);
i2 = imagesc(t,ff,val2);
ax2 = gca;
set(ax2,'YDir','normal')
xlabel('Time [s]')
ylabel('Frequency [Hz]')
c3 = colorbar;
ylabel(c3,'Power/frequency')
set(ax2,'YTick',ftick,'YTickLabel',fticklabel)
Ftsz = get(ax2,'FontSize'); % get original fontsize because yax changes it
yax = get(ax2,'YAxis');
set(yax,'FontSize',12);
set(get(yax,'Label'),'FontSize',Ftsz);
% set caxis based on percentile of val2.
[prc] = prctile(val2(:),[1,99]);
cmin = prc(1);
cmax = prc(2);
% can also try based on distribution
mu = mean(val2(:));
sd = std(val2(:));
cmin = mu-3*sd;
cmax = mu+3*sd;
caxis([cmin,cmax])
  11 件のコメント
Arthur Batte
Arthur Batte 2020 年 6 月 24 日
hello Daniel, it appears that the spectrograms created by the code above are stacked horizontally. I would wish to stack them vertically ( see figure attached) where by the horizontal axis is replaced by months of the year and the vertical axis is kept as frequency. In this case, each channel represents a certain month in which it was recorded. For the data given above, they are 8 channels that makes it january to august.
what changes can be do to this code?
Daniel M
Daniel M 2020 年 6 月 24 日
I recommend that you open a new question regarding this.

サインインしてコメントする。


Funda KUTLU ONAY
Funda KUTLU ONAY 2019 年 10 月 31 日
Thank you very much for your time. I think I can use it this way. But I have one more question for you. Can I save only the spectrogram part as an image?
  1 件のコメント
Daniel M
Daniel M 2019 年 10 月 31 日
編集済み: Daniel M 2019 年 10 月 31 日
f2 = figure('Position',[680 378 805 600]);
i2 = imagesc(t,ff,val2);
ax2 = gca;
set(ax2,'YDir','normal')
set(get(ax2,'YAxis'),'Visible','off')
set(get(ax2,'XAxis'),'Visible','off')
caxis([cmin,cmax])

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeSpectral Measurements についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by