Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge dev into master #19

Merged
merged 21 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ git clone https://github.com/arnodelorme/roiconnect.git
```
That's it! If you want to run the plugin, please start [EEGLAB](https://github.com/sccn/eeglab#to-use-eeglab) first. You may need to add EEGLAB to the [MATLAB path](https://de.mathworks.com/help/matlab/ref/addpath.html).

📌 `test_pipes/` includes some test pipelines which can be used to get started.

# Key features
The features of the toolbox are implemented in the following three main functions: `pop_roi_activity`, `pop_roi_connect` and `pop_roi_connectplot`.

Expand Down Expand Up @@ -66,12 +68,12 @@ The function computes all FC metrics in a frequency-resolved way, i.e., the outp
You can visualize power and FC in different modes by calling `pop_roi_connectplot`. Below, we show results of a single subject from the real data example in [[1]](#1). You can find the MATLAB code and corresponding analyses [here](https://github.com/fpellegrini/MotorImag). The plots show power or FC in left motor imagery condition. Due to the nature of the task, we show results in the 8 to 13 Hz frequency band but you are free to choose any frequency or frequency band you want.

:pushpin: If any of the images are too small for you, simply click on them, they will open in full size in another tab.<br>
:round_pushpin: Plotting is particularly optimized for PSD, MIM/MIC and GC/TRGC. The matrix plots are only available for the Desikan-Killiany atlas (68 ROIs). We are currently working on a generalized solution for all atlases.
:round_pushpin: Plotting is particularly optimized for PSD, MIM/MIC and GC/TRGC.

### Power as a region-wise bar plot
If you wish to visualize power as a barplot only, please make sure to explicitely turn `plotcortex` off because it is turned on by default.
```matlab
EEG = pop_roi_connectplot(EEG, 'measure', 'roipsd', 'plotcortex', 'off', 'plotbarplot', on, 'freqrange', [8 13]) % alpha band;
EEG = pop_roi_connectplot(EEG, 'measure', 'roipsd', 'plotcortex', 'off', 'plotbarplot', 'on', 'freqrange', [8 13]) % alpha band;
```
<p float="middle">
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/power_barplot_left.jpg?raw=true" width="400"/>
Expand All @@ -93,7 +95,7 @@ Again, if you do not wish to see the cortex plot, you should explicitely turn `p
EEG = pop_roi_connectplot(EEG, 'measure', 'mim', 'plotcortex', 'off', 'plotmatrix', 'on', 'freqrange', [8 13]);
```
<p float="middle">
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix_left.jpg?raw=true" width="400"/>
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix.png?raw=true" width="400"/>
&nbsp; &nbsp;
</p>

Expand All @@ -103,17 +105,17 @@ pop_roi_connectplot(EEG, 'measure', 'mim', 'plotcortex', 'off', 'plotmatrix', 'o
```

<p float="middle">
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix_groupedhems_left.jpg?raw=true" width="400"/>
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix_groupedhems.png?raw=true" width="400"/>
&nbsp; &nbsp;
</p>

You can additionally filter by hemispheres and regions belonging to specific brain lobes. As an example, let us see how FC of the left hemisphere looks like.

```matlab
pop_roi_connectplot(EEG, 'measure', 'mim', 'plotcortex', 'off', 'plotmatrix', 'on', 'freqrange', [8 13], 'hemisphere', 'left') % left hemisphere, left motor imagery;
pop_roi_connectplot(EEG, 'measure', 'mim', 'plotcortex', 'off', 'plotmatrix', 'on', 'freqrange', [8 13], 'hemisphere', 'left');
```
<p float="middle">
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix_lefthem_left.jpg?raw=true" width="400"/>
<img src="https://github.com/Hiyeri/roiconnect/blob/master/resources/FC_MIM_matrix_lefthem.png?raw=true" width="400"/>
&nbsp; &nbsp;
</p>

Expand Down
185 changes: 109 additions & 76 deletions pop_roi_connectplot.m
Original file line number Diff line number Diff line change
Expand Up @@ -416,13 +416,14 @@

% plot on matrix
if strcmpi(g.plotmatrix, 'on') && ~isempty(matrix)
matrix = matrix.*seedMask;
try
roi_plotcoloredlobes(EEG, matrix, titleStr, g.measure, g.hemisphere, g.grouphemispheres, g.region);
catch
warning('Functionalities only available for the Desikan-Killiany atlas (68 ROIs).')
figure; imagesc(matrix);
end
matrix = matrix.*seedMask;
roi_plotcoloredlobes(EEG, matrix, titleStr, g.measure, g.hemisphere, g.grouphemispheres, g.region);
% try
% roi_plotcoloredlobes(EEG, matrix, titleStr, g.measure, g.hemisphere, g.grouphemispheres, g.region);
% catch
% warning('Functionalities only available for the Desikan-Killiany atlas (68 ROIs).')
% figure; imagesc(matrix);
% end
end

% plot on cortical surface
Expand All @@ -440,6 +441,8 @@
end
h = textsc(cortexTitle, 'title');
set(h, 'fontsize', 20);
elseif cortexFlag == -1
warning('EEG.roi.cortex does not contain the field "Faces" required to plot surface topographies.')
end

% plot 3D
Expand Down Expand Up @@ -477,15 +480,24 @@
end
end

function [colors, color_idxx, roi_idxx, labels_dk_cell_idx, roi_loc] = get_colored_labels(EEG)
% retrieve labels from atlas
function labels = get_labels(EEG)
% retrieve labels from atlas
labels = strings(1,length(EEG.roi.atlas.Scouts));
for i = 1:length(labels)
scout = struct2cell(EEG.roi.atlas.Scouts(i));
labels(i) = char(scout(1));
end
labels = cellstr(labels);

end

function new_labels = replace_underscores(labels)
% remove underscores in label names to avoid bug
new_labels = strrep(labels, '_', ' ');
end

function [colors, color_idxx, roi_idxx, labels_sorted, roi_loc] = get_colored_labels(EEG)
labels = get_labels(EEG);

colors = {[0,0,0]/255, [163, 107, 64]/255, [171, 163, 71]/255, [217, 37, 88]/255, [113, 15, 82]/255,[35, 103, 81]/255,[2, 45, 126]/255,};
% assign labels to colors
roi_loc ={'LT';'RT';'LL';'RL';'LF';'RF';'LO';'RO';'LT';'RT';'LPF';'RPF';'LT';'RT';'LP';'RP';'LT';'RT';'LT';'RT';'LL';'RL';'LO';'RO';'LPF';'RPF';'LO';'RO';'LPF';'RPF';'LT';'RT';'LC';'RC';'LT';'RT';'LF';'RF';'LPF';'RPF';'LF';'RF';'LO';'RO';'LC';'RC';'LL';'RL';'LC';'RC';'LP';'RP';'LL';'RL';'LF';'RF';'LF';'RF';'LP';'RP';'LT';'RT';'LP';'RP';'LT';'RT';'LT';'RT'};
Expand All @@ -502,21 +514,21 @@
roi_loc = strrep(roi_loc, 'R', '');
try
[color_idxx,roi_idxx] = sort(str2double(roi_loc));
labels_dk_cell_idx = labels(roi_idxx);
labels_sorted = labels(roi_idxx);
catch
roi_idxx = 1:length(labels);
color_idxx = mod(roi_idxx, length(colors))+1;
labels_dk_cell_idx = labels;
labels_sorted = labels;
end
end

function roi_plotpower(EEG, source_roi_power_norm_dB, titleStr)
[colors, color_idxx, roi_idxx, labels_dk_cell_idx, ~] = get_colored_labels(EEG);
n_roi_labels = size(labels_dk_cell_idx, 2);
[colors, color_idxx, roi_idxx, labels_sorted, ~] = get_colored_labels(EEG);
n_roi_labels = size(labels_sorted, 2);

barh(source_roi_power_norm_dB(roi_idxx));
set(gca, 'YDir', 'reverse');
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_dk_cell_idx(1:end), 'fontweight','bold','fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.7);
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_sorted(1:end), 'fontweight','bold','fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.7);
h = title([ 'ROI source power' ' (' titleStr ')' ]);
set(h, 'fontsize', 16);
ylabel('power [dB]')
Expand All @@ -542,43 +554,62 @@ function roi_plotcoloredlobes( EEG, matrix, titleStr, measure, hemisphere, group
error('Region plotting is only supported for the Desikan-Killiany atlas.');
end

% plot matrix with colored labels sorted by region according to the Desikan-Killiany atlas
% plot matrix with colored labels
load cm18
switch lower(measure)
case {'mim', 'mic', 'coh'}
cmap = cm18a;
otherwise
cmap = cm18;
end
[colors, color_idxx, roi_idxx, labels_dk_cell_idx, roi_loc] = get_colored_labels(EEG);

clim_min = min(matrix, [], 'all');
clim_max = max(matrix, [], 'all');

% assign region input to an index
[GC, GR] = groupcounts(roi_loc);
switch lower(region)
case 'cingulate'
region_idx = 1;
case 'prefrontal'
region_idx = 2;
case 'frontal'
region_idx = 3;
case 'temporal'
region_idx = 4;
case 'parietal'
region_idx = 5;
case 'central'
region_idx = 6;
case 'occipital'
region_idx = 7;
otherwise
region_idx = 99;

% hemisphere parameters to determine which labels to use
last_char = EEG.roi.atlas.Scouts(1).Label(end);
if strcmpi(hemisphere, 'left')
if strcmpi(last_char, 'R')
hem_idx = {2 2 2}; % use labels 2:2:end (first two values), only use 1/2 of the labels (3rd value)
else
hem_idx = {1 2 2}; % use labels 1:2:end (first two values), only use 1/2 of the labels (3rd value)
end
elseif strcmpi(hemisphere, 'right')
if strcmpi(last_char, 'L')
hem_idx = {1 2 2};
else
hem_idx = {2 2 2};
end
else
hem_idx = {1 1 1};
end

% sort matrix according to color scheme
% reduce matrix to only keep components corresponding to selected region
if isDKatlas == 1
[colors, color_idxx, roi_idxx, labels_sorted, roi_loc] = get_colored_labels(EEG);
labels = labels_sorted;

% assign region input to an index
[GC, ~] = groupcounts(roi_loc);
switch lower(region)
case 'cingulate'
region_idx = 1;
case 'prefrontal'
region_idx = 2;
case 'frontal'
region_idx = 3;
case 'temporal'
region_idx = 4;
case 'parietal'
region_idx = 5;
case 'central'
region_idx = 6;
case 'occipital'
region_idx = 7;
otherwise
region_idx = 99;
end

matrix = matrix(roi_idxx, roi_idxx);
if not(region_idx == 99)
if region_idx == 1
Expand All @@ -588,44 +619,40 @@ function roi_plotcoloredlobes( EEG, matrix, titleStr, measure, hemisphere, group
end
end_idx = start_idx + GC(region_idx) - 1;
matrix = matrix(start_idx:end_idx, start_idx:end_idx);
labels_dk_cell_idx = labels_dk_cell_idx(start_idx:end_idx);
labels = labels(start_idx:end_idx);
color_idxx = color_idxx(start_idx:end_idx);
end
n_roi_labels = size(matrix, 1);
end

% hemisphere parameters to determine which labels to use
if strcmpi(hemisphere, 'left')
hem_idx = {1 2 2}; % use labels 1:2:end (first two values), only use 1/2 of the labels (3rd value)
elseif strcmpi(hemisphere, 'right')
hem_idx = {2 2 2}; % use labels 2:2:end (first two values), only use 1/2 of the labels (3rd value)
else
hem_idx = {1 1 1}; % use labels 1:1:end (first two values, all labels), use 1/1 of the labels (3rd value, all labels)
labels = get_labels(EEG);
end

% remove underscores in labels to avoid plotting bug
labels = replace_underscores(labels);

% create dummy plot and add custom legend
f = figure();
%f.WindowState = 'maximized';
hold on
n_dummy_labels = 7;
x = 1:10;
for k=1:n_dummy_labels
plot(x, x*k, '-', 'LineWidth', 9, 'Color', colors{k});
end

% labels on dummy plot for positioning
xlim([0 n_roi_labels])
ylim([0 n_roi_labels])
set(gca,'xtick',[1:n_roi_labels],'xticklabel',labels_dk_cell_idx(hem_idx{1}:hem_idx{2}:n_roi_labels));%, 'TickLabelInterpreter','none');
set(gca,'xtick',1:n_roi_labels,'xticklabel',labels(hem_idx{1}:hem_idx{2}:n_roi_labels));%, 'TickLabelInterpreter','none');
ax = gca;
for i=hem_idx{1}:hem_idx{2}:n_roi_labels
ax.XTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.XTickLabel{ceil(i/2)});
end
xtickangle(90)
pos = get(gca, 'Position');
if isDKatlas == 1
for k=1:n_dummy_labels
plot(x, x*k, '-', 'LineWidth', 9, 'Color', colors{k});
end
for i=hem_idx{1}:hem_idx{2}:n_roi_labels
ax.XTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.XTickLabel{ceil(i/2)});
end
legend('Cingulate', 'Prefrontal', 'Frontal', 'Temporal', 'Parietal', 'Central', 'Occipital', 'Location', 'southeastoutside'); % modify legend position
end
xtickangle(90)
pos = get(gca, 'Position');
set(gca, 'Position', pos, 'DataAspectRatio',[1 1 1], 'visible', 'off')
axes('pos', [pos(1) pos(2) pos(3) pos(4)]) % plot matrix over the dummy plot and keep the legend

Expand All @@ -640,14 +667,20 @@ function roi_plotcoloredlobes( EEG, matrix, titleStr, measure, hemisphere, group
matrix = horzcat(mat_left_col, mat_right_col); % sort columns

% sort labels
lc = {labels_dk_cell_idx; transpose(color_idxx)};
for i = 1:length(lc)
left = lc{i}(1:2:end);
right = lc{i}(2:2:end);
lc{i} = [left right];
try % if color can be assigned
lc = {labels; transpose(color_idxx)};
for i = 1:length(lc)
left = lc{i}(1:2:end);
right = lc{i}(2:2:end);
lc{i} = [left right];
end
labels = lc{1};
color_idxx = transpose(lc{2});
catch
left = labels(1:2:end);
right = labels(2:2:end);
labels = [left right];
end
labels_dk_cell_idx = lc{1};
color_idxx = transpose(lc{2});
end

% reduce matrix to keep only one hemisphere
Expand Down Expand Up @@ -677,16 +710,16 @@ function roi_plotcoloredlobes( EEG, matrix, titleStr, measure, hemisphere, group
set(gca, 'Position', pos, 'DataAspectRatio',[1 1 1], 'visible', 'on')

% add colored labels with display option
ax = gca;
set(gca,'xtick',1:n_roi_labels,'xticklabel',labels(hem_idx{1}:hem_idx{2}:n_roi_labels));
if isDKatlas == 1
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_dk_cell_idx(hem_idx{1}:hem_idx{2}:n_roi_labels), 'fontweight','bold', 'fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
set(gca,'ytick',1:n_roi_labels,'yticklabel',labels(hem_idx{1}:hem_idx{2}:n_roi_labels), 'fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
for i=hem_idx{1}:hem_idx{2}:n_roi_labels
ax.XTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.XTickLabel{ceil(i/hem_idx{3})});
ax.YTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.YTickLabel{ceil(i/hem_idx{3})});
end
else
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_dk_cell_idx(hem_idx{1}:hem_idx{2}:n_roi_labels), 'fontsize', 7, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
end
set(gca,'xtick',[1:n_roi_labels],'xticklabel',labels_dk_cell_idx(hem_idx{1}:hem_idx{2}:n_roi_labels));
ax = gca;
for i=hem_idx{1}:hem_idx{2}:n_roi_labels
ax.XTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.XTickLabel{ceil(i/hem_idx{3})});
ax.YTickLabel{ceil(i/hem_idx{3})} = sprintf('\\color[rgb]{%f,%f,%f}%s', colors{color_idxx(i)}, ax.YTickLabel{ceil(i/hem_idx{3})});
set(gca,'ytick',1:n_roi_labels,'yticklabel',labels(hem_idx{1}:hem_idx{2}:n_roi_labels), 'fontsize', 7, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
end
h = title([ 'ROI to ROI ' upper(measure) ' (' titleStr ')' ]);
set(h, 'fontsize', 16);
Expand All @@ -696,8 +729,8 @@ function roi_plotcoloredlobes( EEG, matrix, titleStr, measure, hemisphere, group
function roi_largeplot(EEG, mim, trgc, roipsd, titleStr)
% plot MIM, TRGC and power (barplot) in a single large figure
load cm18
[colors, color_idxx, roi_idxx, labels_dk_cell_idx, ~] = get_colored_labels(EEG);
n_roi_labels = size(labels_dk_cell_idx, 2);
[colors, color_idxx, roi_idxx, labels_sorted, ~] = get_colored_labels(EEG);
n_roi_labels = size(labels_sorted, 2);

f = figure();
f.WindowState = 'maximized';
Expand All @@ -713,8 +746,8 @@ function roi_largeplot(EEG, mim, trgc, roipsd, titleStr)
img_sorted = img(roi_idxx, roi_idxx);
imagesc(img_sorted)

set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_dk_cell_idx(1:end), 'fontsize', 5, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
set(gca,'xtick',[1:n_roi_labels],'xticklabel',labels_dk_cell_idx(1:end));
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_sorted(1:end), 'fontsize', 5, 'TickLength',[0.015, 0.02], 'LineWidth',0.75);
set(gca,'xtick',[1:n_roi_labels],'xticklabel',labels_sorted(1:end));
h = title([ 'ROI to ROI ' fc_names{k} ' (' titleStr ')' ]);
set(h, 'fontsize', 16);
hcb = colorbar;
Expand All @@ -735,7 +768,7 @@ function roi_largeplot(EEG, mim, trgc, roipsd, titleStr)
barh(roipsd(roi_idxx));

set(gca, 'YDir', 'reverse');
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_dk_cell_idx(1:end), 'fontweight','bold','fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.7);
set(gca,'ytick',[1:n_roi_labels],'yticklabel',labels_sorted(1:end), 'fontsize', 9, 'TickLength',[0.015, 0.02], 'LineWidth',0.7);
h = title([ 'ROI source power' ' (' titleStr ')' ]);
set(h, 'fontsize', 16);
ylabel('power [dB]')
Expand Down
Binary file added resources/FC_MIM_matrix.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/FC_MIM_matrix_groupedhems.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/FC_MIM_matrix_left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,4 @@
tic
EEG = pop_roi_connect(EEG, 'methods', measures(iMeasure));
t(iMeasure) = toc;
end

pop_roi_connectplot(EEG, 'measure', 'MIM', 'plotmatrix', 'on', 'plotcortex', 'on');
end
Loading