[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
A
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
>course.
>
>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
>resolution.
>
>Cheers,
>Natasha
>
>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>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
>interpolated
>% 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)
>theta(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