% EEGMOVIE - Compile and view a Matlab movie.
% Uses scripts EEGPLOTOLD and TOPOPLOT.
% Use SEEMOVIE to display the movie.
% Usage:
% >> [Movie,Colormap] = eegmovie(data,srate,elec_locs, 'key', val, ...);
%
% Or legacy call
% >> [Movie,Colormap] = eegmovie(data,srate,elec_locs,title,movieframes,minmax,startsec,...);
%
% Inputs:
% data = (chans,frames) EEG data set to plot
% srate = sampling rate in Hz
% elec_locs = electrode locations structure or file
%
% Optional inputs:
% 'mode' = ['2D'|'3D'] plot in 2D using topoplot or in 3D using
% headplot. Default is 2D.
% 'headplotopt' = [cell] optional inputs for headplot. Default is none.
% 'topoplotopt' = [cell] optional inputs for topoplot. Default is none.
% 'title' = plot title. Default is none.
% 'movieframes' = vector of frames indices to animate. Default is all.
% 'minmax' = [blue_lower_bound, red_upper_bound]. Default is
% +/-abs max of data.
% 'startsec' = starting time in seconds. Default is 0.
% 'timecourse' = ['on'|'off'] show time course for all electrodes. Default is 'on'.
% 'framenum' = ['on'|'off'] show frame number. Default is 'on'.
% 'time' = ['on'|'off'] show time in ms. Default is 'off'.
% 'vert' = [float] plot vertical lines at given latencies. Default is none.
% 'camerapath' = [az_start az_step el_start el_step] {default [-127 0 30 0]}
% Setting all four non-0 creates a spiral camera path
% Subsequent rows [movieframe az_step 0 el_step] adapt step
% sizes allowing starts/stops, panning back and forth, etc.
%
% Legacy inputs:
% data = (chans,frames) EEG data set to plot
% srate = sampling rate in Hz {0 -> 256 Hz}
% elec_locs = ascii file of electrode locations {0 -> 'chan_file'}
% title = 'plot title' {0 -> none}
% movieframes = vector of frames to animate {0 -> all}
% minmax = [blue_lower_bound, red_upper_bound]
% {0 -> +/-abs max of data}
% startsec = starting time in seconds {0 -> 0.0}
% additional options from topoplot are allowed
%
% Author: Arnaud Delorme, Colin Humphries & Scott Makeig, CNL, Salk Institute, La Jolla, 3/97
%
% Example of usage for 3D movie: see https://github.com/amisepa/eegmovie_topo3d
%
% See also: SEEMOVIE, EEGPLOTOLD, TOPOPLOT
% Copyright (C) 6/4/97 Colin Humphries & Scott Makeig, CNL / Salk Institute / La Jolla CA
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
% 6/6/97 added movieframes arg -sm
% 6/12/97 removed old 'startframes' var., fixed vertical line frame selection -sm
% 6/27/97 debugged vertical line position -sm
% 10/4/97 clarified order of srate and eloc_locs -sm
% 3/18/97 changed eegplots -> eegplot('noui') -sm
% 10/10/99 added newlines to frame print at suggestion of Ian Lee, Singapore -sm
% 01/05/01 debugged plot details -sm
% 01/24/02 updated eegplot to eegplotold -ad
% 01-25-02 reformated help & license, added links -ad
function [Movie, Colormap] = eegmovie(data,srate,eloc_locs,varargin);
%titl,movieframes,minmax,startsec,varargin)
if nargin<1
help eegmovie
return
end
clf
[chans,frames] = size(data);
icadefs; % read DEFAULT_SRATE;
if nargin <2
srate = 0;
end
if nargin <3
eloc_locs = 0;
end
if nargin > 5 && ~ischar(varargin{3}) || nargin == 4 && ~ischar(varargin{2})
% legacy mode
options = {};
if nargin>=8, options = { options{:} 'topoplotopt' varargin(5:end) }; end
if nargin>=7, options = { options{:} 'startsec' varargin{4} }; end
if nargin>=6, options = { options{:} 'minmax' varargin{3} }; end
if nargin>=5, options = { options{:} 'movieframes' varargin{2} }; end
if nargin>=4, options = { options{:} 'title' varargin{1} }; end
else
options = varargin;
end
opt = finputcheck(options, { 'startsec' 'real' {} 0;
'minmax' 'real' {} 0;
'movieframes' 'integer' {} 0;
'title' 'string' {} '';
'vert' 'real' {} [];
'mode' 'string' { '2D' '3D' } '2D';
'timecourse' 'string' { 'on' 'off' } 'on';
'framenum' 'string' { 'on' 'off' } 'on';
'camerapath' 'real' [] 0;
'time' 'string' { 'on' 'off' } 'off';
'topoplotopt' 'cell' {} {};
'headplotopt' 'cell' {} {} }, 'eegmovie');
if ischar(opt), error(opt); end
if opt.minmax ==0,
datamin = min(min(data));
datamax = max(max(data));
absmax = max([abs(datamin), abs(datamax)]);
fudge = 0.05*(datamax-datamin); % allow for slight extrapolation
datamin = -absmax-fudge;
datamax = absmax+fudge;
opt.minmax = [datamin datamax];
end
if opt.movieframes == 0
opt.movieframes = 1:frames;
end
if opt.movieframes(1) < 1 || opt.movieframes(length(opt.movieframes))>frames
fprintf('eegmovie(): specified movieframes not in data!\n');
return
end
if srate ==0,
srate = DEFAULT_SRATE;
end
if strcmpi(opt.time, 'on'), opt.framenum = 'off'; end
mframes = length(opt.movieframes);
fprintf('Making a movie of %d frames\n',mframes)
Movie = moviein(mframes,gcf);
%%%%%%%%%%%%%%%%%%%%% EEGPLOT of data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if strcmpi(opt.timecourse, 'on')
axeegplot = axes('Units','Normalized','Position',[.75 .05 .2 .9]);
% >> eegplotold('noui',data,srate,spacing,eloc_file,startsec,color)
if isstruct(eloc_locs)
fid = fopen('tmp_file.loc', 'w');
adddots = '...';
for iChan = 1:length(eloc_locs)
fprintf(fid, '0 0 0 %s\n', [ eloc_locs(iChan).labels adddots(length(eloc_locs(iChan).labels):end) ]);
end
fclose(fid);
eegplotold('noui',-data,srate,0,'tmp_file.loc',opt.startsec,'r');
else
eegplotold('noui',-data,srate,0,eloc_locs,opt.startsec,'r');
end
% set(axeegplot,'XTick',[]) %%CJH
% plot negative up
limits = get(axeegplot,'Ylim'); % list channel numbers only
set(axeegplot,'GridLineStyle','none')
set(axeegplot,'Xgrid','off')
set(axeegplot,'Ygrid','on')
for ind = 1:length(opt.vert)
frameind = (opt.vert(ind)-opt.startsec)*srate+1;
line([frameind frameind],limits,'color','k'); % draw vertical line at map timepoint
set(axeegplot,'Xtick',frameind,'XtickLabel',num2str(opt.vert(ind),'%4.3f'));
end
end
%%%%%%%%%%%%%%%%%%%%% topoplot/headplot axis %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
axcolor = get(gcf,'Color');
axtopoplot = axes('Units','Normalized','Position',[0 .1 .72 .8],'Color',axcolor);
TPAXCOLOR = get(axtopoplot,'Color'); %%CJH
icadefs;
cmap = feval(DEFAULT_COLORMAP, 64);
Colormap = [cmap;TPAXCOLOR];
fprintf('Warning: do not resize plot window during movie creation ...\n ');
h = textsc(opt.title, 'title'); set(h,'FontSize',16)
%%%%%%%%%%%%%%%%%%%%% headplot setup %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if strcmpi(opt.mode, '3d')
headplot('setup',eloc_locs, 'tmp.spl', opt.headplotopt{:});
if isequal(opt.camerapath, 0)
opt.camerapath = [-127 0 30 0];
fprintf('Using default view [-127 0 30 0].');
end
if size(opt.camerapath,2)~=4
error('Camerapath parameter must have exact 4 columns');
end
newpan = length(opt.movieframes)+1;
posrow = 2;
if size(opt.camerapath,1) > 1
newpan = opt.camerapath(posrow,1); % pick up next frame to change camerapos step values
end
azimuth = opt.camerapath(1,1); % initial camerapath variables
az_step = opt.camerapath(1,2);
elevation = opt.camerapath(1,3);
el_step = opt.camerapath(1,4);
end
%%%%%%%%%%%%%%%%%%%%%%%%% "Roll'em!" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for f = 1:length(opt.movieframes) % make the movie, frame by frame
indFrame = opt.movieframes(f);
% show time course
if strcmpi(opt.timecourse, 'on')
axes(axeegplot)
x1 = opt.startsec+(indFrame-1)/srate;
l1 = line([indFrame indFrame],limits,'color','b'); % draw vertical line at map timepoint
set(axeegplot,'Xtick',indFrame,'XtickLabel',num2str(x1,'%4.3f'));
end
% plot headplot or topoplot
axes(axtopoplot)
cla
set(axtopoplot,'Color',axcolor);
if strcmpi(opt.mode, '2d')
topoplot(data(:,indFrame),eloc_locs,'maplimits',opt.minmax, opt.topoplotopt{:});
else
headplot(data(:,indFrame),'tmp.spl','view',[azimuth elevation], opt.headplotopt{:});
% adapt camerapath step sizes
if indFrame == newpan
az_step = opt.camerapath(posrow,2);
el_step = opt.camerapath(posrow,4);
posrow = posrow+1;
if size(opt.camerapath,1)>=posrow
newpan = opt.camerapath(posrow,1);
else
newpan = length(opt.movieframes)+1;
end
end
% update camera position
azimuth = azimuth+az_step;
elevation = elevation+el_step;
if elevation>=90
fprintf('headplot(): warning -- elevation out of range!\n');
elevation = 89.99;
end
if elevation<=-90
fprintf('headplot(): warning -- elevation out of range!\n');
elevation = -89.99;
end
set(axtopoplot,'Units','pixels',...
'CameraViewAngleMode','manual',...
'YTickMode','manual','ZTickMode','manual',...
'PlotBoxAspectRatioMode','manual',...
'DataAspectRatioMode','manual'); % keep camera distance constant
end
% show frame number
if strcmpi(opt.framenum, 'on')
txt = [ int2str(f)];
text(-0.5,-0.5,txt,'FontSize',14);
elseif strcmpi(opt.time, 'on')
txt = sprintf('%3.3f s', opt.startsec+(indFrame-1)/srate);
text(-0.5,-0.5,txt,'FontSize',14);
end
Movie(:,f) = getframe(gcf);
drawnow
if strcmpi(opt.timecourse, 'on')
delete(l1)
end
% print advancement
fprintf('.',f);
if rem(indFrame,10) == 0, fprintf('%d',f); end
if rem(indFrame,50) == 0, fprintf('\n'); end
end
fprintf('\nDone\n');