[Eeglablist] interpolating bad electrodes

Scott Makeig smakeig at ucsd.edu
Sun Jan 22 11:27:54 PST 2006

I'd like to offer a further idea re interpolation that we here have not 
had time to code, but that someone on the list might be interested in. 
Simply put, linear interpolation of scalp channel data is a less than 
perfect idea for the following reason. Say you want to interpolate 
missing channel A in the following montage

     B             D
     C             E

Then linear interpolation would estimate A, at each time point, by

        A = (B+C+D+E)/4;       (1)

Conventional objections to eq. (1) would be that spherical interpolation 
would be more accurate (at least, if the pattern were not a perfectly 
symmetrical  'quicunx' as above). However, there is a (literally) deeper 
ojection. Say that most of the activity at A was projected from two EEG 
sources, call them ABC and ADE, for the channels to which they project 
most strongly. At some points in time, source ABC will dominate the 
signal at A (e.g., when source ADE is at a zero crossing), and at other 
time points, ADE will dominate. Using eq. (1) above to estimate A will 
produce an error at any such time point.

The obvious alternative is to linearly (or otherwise) interpolate each 
source projection map, then sum their interpolated values at each time 
point, but weighted by their respective contributions, which will differ 
at each time point. How to find the source maps and time courses? One 
may use ICA. Thus, a more optimal interpolation routine would 
interpolate the scalp projections (maps) of a number of components of 
interest, then sum their interpolated back-projections over the time 
points of interest.

A signal processing function to do this might be

     function interpdata = srcinterp ( data,wts,sphere,comps,timepoints) 

where data is a (chans,times) data matrix, wts and sphere are ICA 
weights and sphering matrices, comps is a vector of component numbers to 
retain, and timepoints is a vetor of frame (time point) indices to 
interpolate. (Thought would be required to also handle 3-D epoched data).

The same function as an eeg_ function taking an EEG dataset:

     function interpdata = eeg_srcinterp ( EEG,comps,timepoints); 

Here, wts and sphere are assumed to be in the EEG structure. Finally, a 
pop_srcinterp(EEG) function could  collect arguments for srcinterp() or 
eeg_srcinterp(), and a plugin_srcinterp() function could make a call to 
pop_srcinterp() appear as a menu item in the EEGLAB gui menu.

Anyone interested in trying this? One should think carefully, first, 
about when and where such a function could be useful...

P.S. In the new EEGLAB cluster analysis tools (to be released soon), 
there is a version of topoplot() called toporeplot() that is used for 
faster interpolation of component maps. This allows clustering of 
components from multiple subjects with possibly different missing 
channels based on their scalp maps, or plotting of the mean scalp map of 
a cluster of such components defined using any component distance measure.

Scott Makeig

nkovacev at rotman-baycrest.on.ca wrote:

>Dear eeglablist users,
>Here is a quick hack at interpolation of bad electrode data - see
>bellow. It creates a temporary data set with bad electrodes removed. It
>calls topoplot to get interpolated values at locations of bad electrodes
>(thanks to Arno for the tip) and it does this for the entire time
>If anyone can suggest better/faster solution - that would be great. This
>is bit of a hack because it calls topolot for each timepoint so it can
>be very slow for long time courses. 
>Such a function would be extremely useful, because in practice, it is
>quite common to have a single bad electrode - it is always a shame to
>either have to remove that electrode from all subjects in the study, or
>drop the subject, or find another workaround. Interpolation would allow
>much more elegant preservation of group data without loss of spatial
>function eeg = interpolate_bad_electrodes(eeg, bad_electrodes)
>% Inputs: 
>%         eeg - eeglab dataset
>%         bad_electrodes - channels with bad data
>% Output: eeg - data set with bad electrode data replaced by
>% data
>  n = numel(bad_electrodes);
>  % get theta, rad of bad electrodes
>  theta = zeros(1,n); rad = zeros(1,n);
>  for i=1:n
>    be = bad_electrodes(i);
>    theta(i) = eeg.chanlocs(be).theta;
>    rad(i)= eeg.chanlocs(be).radius;
>  end
>  % create temporary set with bad electrodes removed
>  tmp_eeg = pop_select(eeg,'nochannel',bad_electrodes);
>  tmp_eeg = eeg_checkset(tmp_eeg);
>  % for each timept obtain interpolated value
>  data = reshape(tmp_eeg.data, tmp_eeg.nbchan, eeg.pnts*eeg.trials); %2D
>  % allocate matrix that will receive interpolated data
>  interp_data = zeros(n, eeg.pnts*eeg.trials);
>  for t=1:size(data,2)
>    tmp_data = squeeze(data(:,t));
>    for i=1:n
>      [h val]= topoplot(tmp_data,tmp_eeg.chanlocs,'noplot',[rad(i)
>      interp_data(i,t) = val;
>    end
>  end
>  % return eeg with bad electrode data replaced by interpolated data
>  eeg.data = reshape(eeg.data, eeg.nbchan, eeg.pnts*eeg.trials); %2D
>  eeg.data(bad_electrodes,:) = interp_data;
>  eeg = eeg_checkset(eeg); %3D

More information about the eeglablist mailing list