📄 gui_topo_animate.m
字号:
function [p] = gui_topo_animate(command,p)
% GUI_TOPO_ANIMATE - GUI controls for animating topography
%
% Useage: p = gui_topo_animate(command,[p])
%
% command - either 'init' or 'animate'
%
% p is the eeg_toolbox struct
%
% This function adds controls to the current figure.
% It assumes this figure has been created with a topographic
% map patch and the userdata contains the p struct for the
% data of the patch.
%
% $Revision: 1.5 $ $Date: 2003/04/08 01:42:38 $
% Licence: GNU GPL, no express or implied warranties
% History: 05/2002, Darren.Weber@flinders.edu.au
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ~exist('command','var'), command = 'init'; end
switch command,
case 'init',
if exist('p','var'),
if ~isempty(p),
ANIM = INIT(p);
end
else
ANIM = INIT;
end
case 'animate',
ANIM = get(gcbf,'Userdata');
if isempty(ANIM),
ANIM = get(gcf,'Userdata');
end
% Obtain the current view from mouse_rotate, which
% can be used in eeg_save_graphics
views = get(ANIM.View,'String');
ANIM.p.topoView = lower(char(views(get(ANIM.View,'Value'))));
% --- First get patch handle (Hp) ---
axsibs = get(ANIM.axis,'Children');
for i=1:length(axsibs),
type = get(axsibs(i),'Type');
if isequal(type,'patch'),
ANIM.Hp = axsibs(i);
end
end
% Animation setup
ANIM = toggle_visible(ANIM);
set(ANIM.Hp,'EraseMode','normal');
figure(ANIM.gui);
% --- Get the animation parameters (msec) ---
start_msec = str2num(get(ANIM.Start,'string'));
finish_msec = str2num(get(ANIM.Finish,'string'));
step_msec = str2num(get(ANIM.Step,'string'));
% --- get data from p struct ---
[ SampleRate, timeArray ] = extract_data(ANIM);
% --- Check step parameter ---
step = step_msec/SampleRate;
stepREM = step - fix(step);
if stepREM,
nointerp = 0;
% have not yet implemented interpolation
warning('GUI_TOPO_ANIMATE: Cannot interpolate for steps ~= sample rate\n');
step = 1;
set(ANIM.Step,'string',sprintf('%7.2f',SampleRate));
else
nointerp = 1;
end
% --- Convert start/finish to data rows ---
[ index, point ] = NearestXYArrayPoint( timeArray, start_msec, 'exact' );
if isempty(index),
[ index, point ] = NearestXYArrayPoint( timeArray, start_msec );
end
start_index = index;
start_point = point;
[ index, point ] = NearestXYArrayPoint( timeArray, finish_msec, 'exact' );
if isempty(index),
[ index, point ] = NearestXYArrayPoint( timeArray, finish_msec );
end
finish_index = index;
finish_point = point;
set(ANIM.Start,'value',start_point);
set(ANIM.Start,'string',sprintf('%7.2f',start_point));
set(ANIM.Finish,'value',finish_point);
set(ANIM.Finish,'string',sprintf('%7.2f',finish_point));
% --- Verify start/finish values ---
if isequal(start_index,finish_index),
% Given start == finish, update topo for that time
% set voltage scale limits
ANIM = voltage_scale(ANIM,start_index,finish_index);
caxis([ANIM.p.minimumIntensity ANIM.p.maximumIntensity]);
colorbar
t = start_index;
ANIM = update_topo(ANIM,t,step);
ANIM = toggle_visible(ANIM);
p = ANIM.p;
return;
elseif start_index > finish_index,
ANIM = toggle_visible(ANIM);
error('GUI_TOPO_ANIMATE: Finish < Start!\n');
end
% Define movie region as figure size
if get(ANIM.Movie,'value'),
rect = get(ANIM.gui,'Position');
rect(1:2) = [0 0];
end
% --- Run the animation ---
% Update voltage scale limits
ANIM = voltage_scale(ANIM,start_index,finish_index);
caxis([ANIM.p.minimumIntensity ANIM.p.maximumIntensity]);
colorbar
for t=start_index : step : finish_index,
ANIM = update_topo(ANIM,t,step);
% Capture movie frame
if get(ANIM.Movie,'value'),
M(t-(start_index-1)) = getframe(ANIM.gui,rect);
end
end
ANIM = toggle_visible(ANIM);
if get(ANIM.Movie,'value'),
% Play movie in another figure
playtimes = 10; fps = 10;
figure('NumberTitle','off','Name','Movie Playback (10 FPS, 10 LOOPS)',...
'PaperType','A4','PaperUnits','centimeters');
axis off; movie(gcf,M,playtimes,fps,rect);
% Save movie to AVI file
movie2avi(M,'topo_movie.avi','quality',100);
filename = strcat(pwd,filesep,'topo_movie.avi');
fprintf('Saved movie to %s\n',filename);
end
p = ANIM.p;
otherwise,
end
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ SampleRate, timeArray, Cdata ] = extract_data(ANIM),
% Unlike most of the eeg_toolbox, this function requires
% the potential data to be electrodes in rows, voltage in columns;
% this is especially so for using this data as Cdata in the patch
% function and facilitates storage and handling of very large
% patch Cdata, such as cortical patches
if ANIM.p.mesh.current & ~isempty(ANIM.p.mesh.data),
if ANIM.p.mesh.current > length(ANIM.p.mesh.data.meshtype),
% assume we are plotting the p.volt.data with the electrodes
SampleRate = ANIM.p.volt.sampleMsec;
timeArray = ANIM.p.volt.timeArray(:,1);
Cdata = ANIM.p.volt.data';
return
end
meshtype = lower(ANIM.p.mesh.data.meshtype{ANIM.p.mesh.current});
switch meshtype,
case 'elec',
% assume we are plotting the p.volt.data with the electrodes
SampleRate = ANIM.p.volt.sampleMsec;
timeArray = ANIM.p.volt.timeArray(:,1);
Cdata = ANIM.p.volt.data';
case 'scalp',
% assume we are plotting the p.volt.data on the scalp
SampleRate = ANIM.p.volt.sampleMsec;
timeArray = ANIM.p.volt.timeArray(:,1);
% check for vertices in rows (default) or columns
nvert = size(ANIM.p.mesh.data.vertices{ANIM.p.mesh.current},1);
[s1,s2] = size(ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current});
if isequal(nvert,s1), % vertices in rows, timepoints in columns
Cdata = ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current};
else, % vertices in columns, timeseries in rows
% try to rotate it, but it may exceed memory for detailed surfaces
Cdata = ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current}';
end
otherwise
% assume the data is in p.mesh.data.Cdata, with a
% timeseries in p.mesh.data.timeseries
SampleRate = ANIM.p.mesh.data.timeseries{ANIM.p.mesh.current}(2) - ANIM.p.mesh.data.timeseries{ANIM.p.mesh.current}(1);
timeArray = ANIM.p.mesh.data.timeseries{ANIM.p.mesh.current};
% get number of vertices
nvert = size(ANIM.p.mesh.data.vertices{ANIM.p.mesh.current},1);
% Assume more vertices than time points
[s1,s2] = size(ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current});
if isequal(nvert,s1), % vertices in rows, timepoints in columns
Cdata = ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current};
else, % vertices in columns, timeseries in rows
% try to rotate it, but it may exceed memory
Cdata = ANIM.p.mesh.data.Cdata{ANIM.p.mesh.current}';
end
end
else
% assume we are plotting the p.volt.data with the electrodes
SampleRate = ANIM.p.volt.sampleMsec;
timeArray = ANIM.p.volt.timeArray(:,1);
Cdata = ANIM.p.volt.data';
end
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ ANIM ] = update_topo(ANIM,t,step),
[ SampleRate, timeArray, Cdata ] = extract_data(ANIM);
% Do we need to average?
if step > 1,
Cdata = Cdata(:,t-(step-1):t);
V = mean(Cdata,2);
else
V = Cdata(:,t);
end
clear Tmp;
set(ANIM.Hp,'FaceVertexCdata',V);
%ANIM.p.timePoint = t;
switch ANIM.p.mesh.data.meshtype{ANIM.p.mesh.current},
case {'scalp','elec'},
ANIM.p.volt.samplePoint = t;
otherwise
ANIM.p.mesh.samplePoint = t;
end
if (ANIM.p.contour.plot3D == 1),
ANIM.p = eeg_plot_surf_contours(ANIM.p);
end
drawnow;
% Update the figure name (title)
ANIM.p.volt.sampleTime = timeArray(t);
name = sprintf('Surface: %s @ %8.2f msec',ANIM.p.volt.file, ANIM.p.volt.sampleTime);
set(ANIM.gui,'Name',name);
% Save the new figure to a graphics file
if get(ANIM.Save,'Value'),
types = get(ANIM.Type,'String');
type = char(types(get(ANIM.Type,'Value')));
eeg_save_graphics(ANIM.gui,type,ANIM.p,0);
end
set(ANIM.gui,'Userdata',ANIM);
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ ANIM ] = voltage_scale(ANIM,start,finish),
[ SampleRate, timeArray, Cdata ] = extract_data(ANIM);
yset = 0;
if isfield(ANIM,'Yset'),
if get(ANIM.Yset,'value'),
ANIM.p.minimumIntensity = get(ANIM.Ymin,'value');
ANIM.p.maximumIntensity = get(ANIM.Ymax,'value');
yset = 1;
end
end
if ~yset,
% For very large Cdata matrices, it is more memory
% efficient to use max(Cdata) that first use abs(Cdata)
Cmax = max(max(Cdata(:,start:finish)));
Cmin = min(min(Cdata(:,start:finish)));
absmax = max([Cmax abs(Cmin)]);
ANIM.p.minimumIntensity = -absmax;
ANIM.p.maximumIntensity = absmax;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -