% POP_TOPOCHANSEL - pop up a topographic interface to select channels
%
% Pops up a topographic interface to select multiple channels with the
% mouse. Click a polygon around the electrodes you wish to select. Right
% click to finish.
%
% Usage:
% >> [chanlist] = pop_topochansel(chanlocs,selection);
%
% Inputs:
% chanstruct - channel structure. See READLOCS
% (optional if EEG structure with chanlocs in caller or
% base workspace)
% selection - currently selected electrodes.
% (optional)
%
%
% Output:
% chanlist - indices of selected channels
% cellchannames - names of selected channel names in a cell array
% strchannames - names of selected channel names in a concatenated string
% (channel names are separated by space characters)
%
function [chanlist, cellchannames, strchannames] = pop_topochansel(chanlocs,select,varargin)
if nargin == 0 || isempty(chanlocs)
try
chanlocs = evalin('caller','chanlocs');
catch
try
tmp = evalin('caller','EEG');
chanlocs = tmp.chanlocs;
catch
error('tell me where the electrodes are'),
end
end
end
if nargin >= 2
if ischar(select)|| iscellstr(select)
select = chnb(select,{chanlocs.labels});
end
end
g = finputcheck( varargin, ...
{ 'labels' 'string' {'on' 'off'} 'off'
'cellstrout' 'string' {'on' 'off'} 'off'
},'ignore');
h0 = figure(23537);clf;
set(gcf,'numbertitle','off','name','Channel selection');
topoplot([],chanlocs,'electrodes','on', 'style','blank');
chi = get(gca,'children');
% chi = chi(1:numel(chanlocs));
todel = [];
for i = 1:numel(chi)
try
if numel(get(chi(i),'XData')) == sum(~emptycells({chanlocs.X}))
continue % we found electrodes
else
todel(end+1) = i;
end
catch
todel(end+1) = i;
end
end
chi(todel) = [];
hold on
X = get(chi,'XData');
Y = get(chi,'YData');
delete(chi)
if strcmp(g.labels,'on')
for i = 1:numel(X)
text(X(i),Y(i),chanlocs(i).labels);
end
end
if exist('select','var')
plot(X(select),Y(select),'r.','markersize',20);
else
select = [];
end
[dum dum chanlist] = lasso(X,Y);
if isempty(chanlist)
disp('No new elecs selected. Keeping old selection')
chanlist = select;
end
strchannames = '';
for i = 1:numel(chanlist)
strchannames = [strchannames chanlocs(chanlist(i)).labels];
if i ~= numel(chanlist)
strchannames = [strchannames ' '];
end
cellchannames{i} = chanlocs(chanlist(i)).labels;
end
if strcmp(g.cellstrout,'on')
chanlist = cellchannames;
end
if nargout == 0
disp(strchannames)
disp(chanlist)
clear
end
% close(h0);
function [selx,sely,indexnr]=lasso(x,y)
% lasso - enables the selection/encircling of (clusters of) events in a scatter plot by hand
% using the mouse
%
% Input: x,y - a set of points in 2 column vectors.
% Output: selx,sely,indexnr - a set of selected points in 3 column vectors
%
% Note: After the scatter plot is given, selection by mouse is started after any key press.
% This is done to be able to ZOOM or CHANGE AXES etc. in the representation before selection
% by mouse.
% Encircling is done by pressing subsequently the LEFT button mouse at the requested positions
% in a scatter plot.
% Closing the loop is done by a RIGHT button press.
%
% T.Rutten V2.0/9/2003
% downloaded and adapted from mathworks fileexchange by M. Chaumon 2011
plot(x,y,'ob')
las_x=[];
las_y=[];
c=1;
key=0;
while c==1
try
[a,b,c]=ginput(1);
las_x=[las_x;a];las_y=[las_y;b];
line(las_x,las_y)
catch
selx = [];sely = []; indexnr = [];
return
end
end
las_x(length(las_x)+1)=las_x(1);
las_y(length(las_y)+1)=las_y(1);
line(las_x,las_y)
pause(.2)
in=inpolygon(x,y,las_x,las_y);
ev_in=find(in>0);
selx=x(ev_in);
sely=y(ev_in);
plot(selx,sely,'r.','markersize',20);
drawnow
indexnr=ev_in;
function nb = chnb(channame, varargin)
% CHNB - return channel number corresponding to channel names in an EEG
% structure
%
% Usage:
% >> [nb] = chnb(channame);
% >> [nb] = chnb(channame, labels);
%
% Input:
% channame - name of channels to search. Either a string with space
% separated channel names, or a cell array of strings.
% Note that regular expressions can be used to match
% several channels. See regexp.
% labels - channel labels as found in EEG.chanlocs.labels.
%
% Output:
% nb - channel numbers in the EEG structure found in the
% caller workspace (i.e. where the function is called
% from) or in the base workspace, if no EEG structure
% exists in the caller workspace.
%
error(nargchk(1,2,nargin));
if nargin == 2
labels = varargin{1};
else
try
EEG = evalin('caller','EEG');
catch
try
EEG = evalin('base','EEG');
catch
error('Could not find EEG structure');
end
end
if not(isfield(EEG,'chanlocs'))
error('No channel list found');
end
labels = {EEG.chanlocs.labels};
end
if ischar(channame)
tmp = regexp(channame,'(\S*) ?','tokens');
channame = {};
for i = 1:numel(tmp)
channame{i} = tmp{i}{1};
end
if isempty(channame)
nb = [];
return
end
end
nb = regexpcell(labels,channame,'exactignorecase');
function idx = regexpcell(c,pat, cmds)
% idx = regexpcell(c,pat, cmds)
%
% Return indices idx of cells in c that match pattern(s) pat (regular expression).
% Pattern pat can be char or cellstr. In the later case regexpcell returns
% indexes of cells that match any pattern in pat.
%
% cmds is a string that can contain one or several of these commands:
% 'inv' return indexes that do not match the pattern.
% 'ignorecase' will use regexpi instead of regexp
% 'exact' performs an exact match (regular expression should match the whole strings in c).
% 'all' (default) returns all indices, including repeats (if several pat match a single cell in c).
% 'unique' will return unique sorted indices.
% 'intersect' will return only indices in c that match ALL the patterns in pat.
%
% v1 Maximilien Chaumon 01/05/09
% v1.1 Maximilien Chaumon 24/05/09 - added ignorecase
% v2 Maximilien Chaumon 02/03/2010 changed input method.
% inv,ignorecase,exact,combine are replaced by cmds
error(nargchk(2,3,nargin))
if not(iscellstr(c))
error('input c must be a cell array of strings');
end
if nargin == 2
cmds = '';
end
if not(isempty(regexpi(cmds,'inv', 'once' )))
inv = true;
else
inv = false;
end
if not(isempty(regexpi(cmds,'ignorecase', 'once' )))
ignorecase = true;
else
ignorecase = false;
end
if not(isempty(regexpi(cmds,'exact', 'once' )))
exact = true;
else
exact = false;
end
if not(isempty(regexpi(cmds,'unique', 'once' )))
combine = 2;
elseif not(isempty(regexpi(cmds,'intersect', 'once' )))
combine = 3;
else
combine = 1;
end
if ischar(pat)
pat = cellstr(pat);
end
if exact
for i_pat = 1:numel(pat)
pat{i_pat} = ['^' pat{i_pat} '$'];
end
end
for i_pat = 1:length(pat)
if ignorecase
trouv = regexpi(c,pat{i_pat}); % apply regexp on each pattern
else
trouv = regexp(c,pat{i_pat}); % apply regexp on each pattern
end
idx{i_pat} = [];
for i = 1:numel(trouv)
if not(isempty(trouv{i}))% if there is a match, store index
idx{i_pat}(end+1) = i;
end
end
end
switch combine
case 1
idx = [idx{:}];
case 2
idx = unique([idx{:}]);
case 3
for i_pat = 2:length(pat)
idx{1} = intersect(idx{1},idx{i_pat});
end
idx = idx{1};
end
if inv % if we want to invert result, then do so.
others = 1:numel(trouv);
others(idx) = [];
idx = others;
end