[Master Index]
[Index for Toolbox]
results_time_series
(Toolbox/results_time_series.m in BrainStorm 2.0 (Alpha))
Function Synopsis
varargout = results_time_series(varargin)
Help Text
RESULTS_TIME_SERIES - Application M-file for results_time_series.fig
function varargout = results_time_series(varargin)
FIG = RESULTS_TIME_SERIES launch results_time_series GUI.
RESULTS_TIME_SERIES('callback_name', ...) invoke the named callback.
Cross-Reference Information
This function calls
This function is called by
Listing of function C:\BrainStorm_2001\Toolbox\results_time_series.m
function varargout = results_time_series(varargin)
%RESULTS_TIME_SERIES - Application M-file for results_time_series.fig
% function varargout = results_time_series(varargin)
% FIG = RESULTS_TIME_SERIES launch results_time_series GUI.
% RESULTS_TIME_SERIES('callback_name', ...) invoke the named callback.
%<autobegin> ---------------------- 26-May-2004 11:34:15 -----------------------
% --------- Automatically Generated Comments Block Using AUTO_COMMENTS ---------
%
% CATEGORY: Visualization
%
% Alphabetical list of external functions (non-Matlab):
% toolbox\bst_color_scheme.m
% toolbox\bst_layout.m
% toolbox\bst_message_window.m
% toolbox\colnorm.m
% toolbox\dataplot_cb.m
% toolbox\fronorm.m
% toolbox\mri_read_tool.m
% toolbox\results_visualization.m
%
% Subfunctions in this file, in order of occurrence in file:
% varargout = update(fig,Data,Results);
% varargout = update_listbox(h,eventdata,handles);
% plot_time_series(h,eventdata,handles);
% varargout = listbox_sourceparam_Callback(h, eventdata, handles, varargin)
% varargout = pushbutton_results_spatial_Callback(h, eventdata, handles, varargin)
% varargout = pushbutton_help_Callback(h, eventdata, handles, varargin)
% varargout = pushbutton_quit_Callback(h, eventdata, handles, varargin)
% varargout = pushbutton_print_Callback(h, eventdata, handles, varargin)
% varargout = checkbox_scale_ButtonDownFcn(h, eventdata, handles, varargin)
% varargout = checkbox_scale_Callback(h, eventdata, handles, varargin)
% varargout = uimenu_flip_orientation_Callback(h, eventdata, handles, varargin)
%
% Application data and their calls in this file:
% 'Data'
% 'ListSourceNumber'
% 'Results'
% 'SourceNumber'
% 'TileType'
% 'UnscaledTime'
% 'htime_series'
% 'visfig'
%
% setappdata(fig,'Data',Data);
% setappdata(fig,'ListSourceNumber',ListSourceNumber);
% setappdata(fig,'Results',Results);
% setappdata(fig,'TileType','T');
% setappdata(fig,'UnscaledTime',UnscaledTime);
% setappdata(fig,'htime_series',htime_series);
% setappdata(fig,'visfig',visfig);
% setappdata(item1,'SourceNumber',i);
%
% Data = getappdata(fig,'Data');
% ListSourceNumber = getappdata(fig,'ListSourceNumber');
% Results = getappdata(fig,'Results');
% SourceNumber = getappdata(h,'SourceNumber');
% UnscaledTime = getappdata(fig,'UnscaledTime');
% htime_series = getappdata(fig,'htime_series');
% visfig = getappdata(fig,'visfig');
%
% Figure Files opened by this function:
% mfilename
%
% Format of strings below: Type:Style:Tag, "String", CallBack Type and Call
% <automatic> callback is <Tag>_Callback by Matlab default
%
% Callbacks by figure results_time_series.fig
% uicontextmenu::uicontext_flip_orientation "" uses Callback for <automatic>
% uicontrol:checkbox:checkbox_scale "Scale" uses ButtonDownFcn for <automatic>
% uicontrol:checkbox:checkbox_scale "Scale" uses Callback for <automatic>
% uicontrol:listbox:listbox_sourceparam "Source Parameters" uses Callback for <automatic>
% uicontrol:pushbutton:pushbutton_help "Help" uses Callback for <automatic>
% uicontrol:pushbutton:pushbutton_print "Print Menu ..." uses Callback for <automatic>
% uicontrol:pushbutton:pushbutton_quit "Quit" uses Callback for <automatic>
% uicontrol:pushbutton:pushbutton_results_spatial "Spatial Display" uses Callback for <automatic>
% uimenu::uimenu_flip_orientation "" uses Callback for <automatic>
%
% At Check-in: $Author: Mosher $ $Revision: 17 $ $Date: 5/26/04 10:02a $
%
% This software is part of BrainStorm Toolbox Version 2.0 (Alpha) 24-May-2004
%
% Principal Investigators and Developers:
% ** Richard M. Leahy, PhD, Signal & Image Processing Institute,
% University of Southern California, Los Angeles, CA
% ** John C. Mosher, PhD, Biophysics Group,
% Los Alamos National Laboratory, Los Alamos, NM
% ** Sylvain Baillet, PhD, Cognitive Neuroscience & Brain Imaging Laboratory,
% CNRS, Hopital de la Salpetriere, Paris, France
%
% See BrainStorm website at http://neuroimage.usc.edu for further information.
%
% Copyright (c) 2004 BrainStorm by the University of Southern California
% This software distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPL
% license can be found at http://www.gnu.org/copyleft/gpl.html .
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%<autoend> ------------------------ 26-May-2004 11:34:15 -----------------------
% Last Modified by GUIDE v2.0 16-May-2002 08:35:34
% ----------------------------- Script History ---------------------------------
% JCM May 2002 initial build from results_update and results_update_gui,
% the original BST 2000 versions
% JCM 31-Oct-2002 commenting, moving results up higher on screen
% SB 11-Jul-2003 linked to BST genneral Viewer
% 19-May-2004 JCM Comments Cleaning
% ----------------------------- Script History ---------------------------------
if nargin == 0 % LAUNCH GUI
fig = openfig(mfilename,'new');
% Generate a structure of handles to pass to callbacks, and store it.
handles = guihandles(fig);
guidata(fig, handles);
if nargout > 0
varargout{1} = fig;
end
% customizations
bst_color_scheme(fig);
% don't really need default width display:
set(handles.listbox_sourceparam,'fontname','default');
% movegui(fig,[10 110]); % get it up above the Message Window as best possible
% on a 1024 x 760 window
setappdata(fig,'TileType','T');
bst_layout('align',fig,2,1,2);
set(fig,'visible','on');
drawnow
elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK
try
if (nargout)
[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
else
feval(varargin{:}); % FEVAL switchyard
end
catch
disp(lasterr);
end
end
% ------------------ Local Functions -------------------------------
% ---------------- UPDATE THE GUI WITH NEW RESULTS -----------------
function varargout = update(fig,Data,Results);
% Outside program call to reload results into the GUI,
% called as results_time_series('update',fig,Data,Results);
% where fig = results_time_series; was the original creation
%
% Update of display the source parameters and residuals while RAP-MUSIC or LS is running.
% Must have the following fields in the BrainStorm structures Data and Results:
% Data: Structure containing information of the data
% Data.F: Spatio-temporal matrix of the original data
% Data.Time: Vector containing the time instants within the current time window of analysis for source localization
% Results: Results structure containing the source parameters
% Results.IndepTopo
% Results.TimeSeries
% Results.Time
% Results.SourceOrder
% Results.Comment;
% Results.Subject.Name;
% Results.Study.Name;
% Results.SourceCorrelation
% Results.SourceLoc
% Please refer to the BrainStorm ParameterDescription file for details regarding the structure of arguments passed to this function
% ----------------------------- Script History ---------------------------------
% Sylvain Baillet, Ph.D.
% John C. Mosher, Ph.D.
% 2/22/00 JCM altering minor window features
% 2/23/00 JCM adding time series display as well
% JCM 3/20/00 added orientation string, made sure was compatible with least-squares
% JCM 3/20/00 Each run now gets its own update window. Makes for easier comparison between
% solutions. Tag is based on output filename
% JCM 3/21/00 Switchable phrase between "correlation" and "variance explained", dependent on
% Results.Function. Also set listbox to black text on white background in the program code,
% so that hardcopy looks better.
% May 2002 major rewrite for MMII, see notes at beginning of this file
% 19-May-2004 JCM Comments Cleaning
% ----------------------------- Script History ---------------------------------
% filename being displayed
figure(fig); % bring to front
handles = guidata(fig); % get the handles for this gui
set(gcf,'Name',sprintf('Results %s %s %s',...
Results.Subject.Name, Results.Study.Name, Results.GUI.Results));
% Now Results.IndepTopo is the fixed orientation gain matrix
% Results.TimeSeries is actually associated with Anrm, such
% that the synthesized data is Anrm * TimeSeries'.
% The unscaled timeseries is
UnscaledTime = [pinv(Results.IndepTopo)*Data.F]';
Model = Results.IndepTopo*UnscaledTime'; % synthesized data
Residual = Data.F - Model; % unexplained
% percent variance explained each part
PowModel = (fronorm(Model)/fronorm(Data.F))^2 *100;
PowResidual = (fronorm(Residual)/fronorm(Data.F))^2 *100;
setappdata(fig,'Data',Data);
setappdata(fig,'Results',Results);
setappdata(fig,'UnscaledTime',UnscaledTime);
if(0), % don't flip anymore, let user do the flipping
% for plot niceties, lets flip polarity of time series as needed.
FLIP = zeros(1,length(Results.SourceOrientation)); % should be one per topo column
for i= 1:length(FLIP),
[mx,mxi] = max(abs(Results.SourceOrientation{i}(:)));
FLIP(i) = sign(Results.SourceOrientation{i}(mxi));
end
Results.IndepTopo = Results.IndepTopo .* FLIP(ones(1,size(Results.IndepTopo,1)),:);
Results.TimeSeries = Results.TimeSeries .* FLIP(ones(1,size(Results.TimeSeries,1)),:);
end
update_listbox(fig,[],handles);
set(handles.checkbox_scale, 'Val',1); % scaling on
plot_time_series(fig,[],handles); % just the source time series
if 0 % deprecated code | following time series are plotted in Viewer's general timeseries figure
% Plot the data
axes(handles.axes_data)
cla
line(Data.Time(Results.Time),Data.F');
set(gca,'YGrid','on');
ylabel('Data','color','w');
axis tight;
Vaxis = axis; % so what are the axis settings?
% Plotting Modelled Sensor Time Series
axes(handles.axes_model)
cla
line(Data.Time(Results.Time),Model');
set(gca,'YGrid','on');
axis tight;
ylabel('Model','color','w');
axis(Vaxis); % set to the same as the data
% Plotting Residuals
axes(handles.axes_residuals)
cla
line(Data.Time(Results.Time),Residual');
set(gca,'YGrid','on');
axis(Vaxis); % set to the same as the data
ylabel('Residual','color','w');
xlabel(...
sprintf('Model: %.1f%% Explained, Residual: %.1f%% Unexplained',...
PowModel,PowResidual),'color','w');
else
global data % Get data structure from active Viewer
% Fill time series arrays - get prepared for viewer
for ifname = [1:3]
data.Fmax{ifname} = zeros(1,3);
for mod=data.imod
if ~isempty(data.SelectedChannels{mod})
switch ifname
case 1
data.F{ifname}(data.SelectedChannels{mod},:) = Data.F;
case 2
data.F{ifname}(data.SelectedChannels{mod},:) = Model;
case 3
data.F{ifname}(data.SelectedChannels{mod},:) = Residual;
end
data.Fmax{ifname}(mod) = max(max(abs(data.F{ifname}(data.SelectedChannels{mod},:))));
end
end
end
data.FileName = {'data','model','residuals'};
dataplot_cb('TimeSeries')
end
% -------------------- UPDATE THE LISTBOX DISPLAY -------------
function varargout = update_listbox(h,eventdata,handles);
fig = handles.figure_time_series;
Results = getappdata(fig,'Results');
%Update the listbox display
if(0), % optional look
% since there is no "inverthardcopy" for list boxes, make black text
% on white background, for better hardcopies
%set(handles.listbox_sourceparam,'BackgroundColor','w');
%set(handles.listbox_sourceparam,'ForegroundColor','k');
end
ListSourceNumber = zeros(1000,1); % initialize, will trim below
% ListSourceNumber(i) gives the number of the associated source
% for each line in the list box. As the user clicks on lines in the
% listbox, the corresponding source is noted. A zero indicates no source
% Some Header Information
String{1} = 'BrainStorm MMII'; % let the world know who did this
String{end+1} = datestr(now);
String{end+1} = Results.Subject.Name;
String{end+1} = Results.Study.Name;
String{end+1} = Results.Comment;
String{end+1} = ' ';
for k = 1:length(Results.SourceLoc), % for each source
String{end+1} = ['Source ',int2str(k),' :'];
ListSourceNumber(length(String)) = k; % line assigned to source
switch(Results.SourceOrder(k))
case -1
Type = 'Current Dipole';
case 0
Type = 'Magnetic Dipole';
case 1
Type = '1st-Order Multipole';
case 2
Type = 'Dipole Synchronous Pair';
case 3
Type = 'Magnetic Dipole Synchronous Pair';
case 4
Type = '1st-Order Multipole Synchronous Pair';
otherwise
Type = 'Unknown??';
end
String{end+1} = Type;
ListSourceNumber(length(String)) = k;
if ~isempty(Results.SourceCorrelation(k))
switch lower(deblank(Results.Function))
case 'least_squares_fit'
String{end+1} = sprintf('%.1f%% variance explained',...
100*Results.SourceCorrelation(k));
ListSourceNumber(length(String)) = k;
case 'rapmusic_gui'
String{end+1} = sprintf('%.1f%% correlation',...
100*Results.SourceCorrelation(k));
ListSourceNumber(length(String)) = k;
otherwise
String{end+1} = sprintf('%.1f%% unknown units',...
100*Results.SourceCorrelation(k));
ListSourceNumber(length(String)) = k;
end
end
Locs = Results.SourceLoc{k};
Orients = Results.SourceOrientation{k};
% one column per source
Orients = reshape(Orients,length(Orients)/size(Locs,2),size(Locs,2));
% In a synchronous source, each column is not unity norm, rather it
% represents the portion of energy in each location
[OPower,nOrients] = colnorm(Orients);
OPower = OPower.^2; % percent energy for each location
% normalization has no effect for asynchronous case
for j = 1:size(Locs,2)
switch size(Locs,2)
case 1
String{end+1} = ['Location: ',...
num2str(Locs(:,j)'*1000,'%6.1f ') 'mm'];
ListSourceNumber(length(String)) = k;
case 2 % two source
String{end+1} = [sprintf('Location %.0f: ',j), ...
num2str(Locs(1:3,j)'*1000,'%6.1f ') 'mm'];
ListSourceNumber([-1:0]+length(String)) = k;
end
switch length(Orients(:,j))
case 3
String{end+1} = ['Dipole: ',num2str(nOrients(:,j)','%5.2f ')];
ListSourceNumber(length(String)) = k;
case 12
String{end+1} = ['Dipole: ',num2str(nOrients(1:3,j)','%5.2f ')];
String{end+1} = ['Quadrupole: ',num2str(nOrients(4:12,j)','%5.2f ')];
ListSourceNumber([-1:0]+length(String)) = k;
end
if(size(Locs,2) > 1), % more than one location
String{end+1} = sprintf('Percent contribution: %.1f%%',...
OPower(j)*100);
ListSourceNumber(length(String)) = k;
end
if ( (size(Locs,2) > 1) & (j < size(Locs,2)) ),
% inside multiple source loop
% pretty print
String{end+1} = ' ';
ListSourceNumber(length(String)) = k;
end
end % for each location in a source
String{end+1} = ' ';
end
set(handles.listbox_sourceparam,'String',String);
setappdata(fig,'ListSourceNumber',ListSourceNumber);
% ----------------------- Plot the Time Series ----------------------
function plot_time_series(h,eventdata,handles);
% called by other routines to redo the time series, don't depend on h
fig = handles.figure_time_series;
Data = getappdata(fig,'Data');
Results = getappdata(fig,'Results');
UnscaledTime = getappdata(fig,'UnscaledTime');
% Plotting Solution Time Series
set(fig,'currentaxes',handles.axes_timeseries);
cla
if(get(handles.checkbox_scale,'Val')),
htime_series = line(Data.Time(Results.Time)*1000,Results.TimeSeries);
else
htime_series = line(Data.Time(Results.Time)*1000,UnscaledTime);
end
set(gca,'YGrid','on');
htitle = title(sprintf('%s',Results.GUI.Results),'color','w','interpreter','none');
ylabel('Solution Time Series','color','w')
xlabel('Time (ms)','color','w')
axis tight;
if(0)
% give it a legend
legstr = cell(1,size(Results.TimeSeries,2)); % number of solutions
for i = 1:length(legstr),
legstr{i} = sprintf('Source %.0f',i);
end
hleg = legend(legstr,0);
hstr= findobj(hleg,'Type','Text'); % find the text strings
set(hstr,'color','w');
end
% setup a uicontextmenu for each plot
for i = 1:length(htime_series),
cmenu = uicontextmenu;
% second item actually can flip the orientation
item1 = uimenu(cmenu,'Label',sprintf('Source %02.0f Flip Orientation',i),...
'Callback',...
'results_time_series(''uimenu_flip_orientation_Callback'',gcbo,[],guidata(gcbo))');
set(htime_series(i),'UiContextMenu',cmenu);
setappdata(item1,'SourceNumber',i); % to retrieve which source this is
end
setappdata(fig,'htime_series',htime_series);
% update the highlighted source
listbox_sourceparam_Callback(handles.listbox_sourceparam,[],handles);
% ----------------- UICONTROL CALLBACKS ------------------------------
% --------------------------------------------------------------------
function varargout = listbox_sourceparam_Callback(h, eventdata, handles, varargin)
fig = handles.figure_time_series;
ListSourceNumber = getappdata(fig,'ListSourceNumber');
% Results = getappdata(fig,'Results');
htime_series = getappdata(fig,'htime_series');
Val = get(h,'Val'); % what line is the user on?
Val = Val(1); % just in case multiple lines were somehow selected
ThisSource = ListSourceNumber(Val); % corresponding source
% set all lines back to normal width
set(htime_series,'LineWidth',1);
if(ThisSource), % non-zero correspondence
% set this line to width of 2, set rest to 1
set(htime_series(ThisSource),'Linewidth',2);
end
% --------------------------------------------------------------------
function varargout = pushbutton_results_spatial_Callback(h, eventdata, handles, varargin)
fig = handles.figure_time_series;
Results = getappdata(fig,'Results');
% link in an MRI view of this data
% code testing here, which of Alex's routines to call
switch 2
case 1
mrifig = mri_read_tool; % invoke a new copy
mrihandles = guidata(mrifig); % and it's handles
mri_read_tool('readbs_Callback',mrifig, eventdata, mrihandles,...
Results.Subject.Anatomy);
case 2
visfig = getappdata(fig,'visfig');
if(isempty(visfig) | ~ishandle(visfig)), % not created or gone
visfig = results_visualization;
setappdata(fig,'visfig',visfig); % save it to prevent duplication
end
vishandles = guidata(visfig);
results_visualization('loadparametric_Callback',...
vishandles.loadparametric, eventdata, vishandles, Results.GUI.Results);
end
% --------------------------------------------------------------------
function varargout = pushbutton_help_Callback(h, eventdata, handles, varargin)
par1 = ['Top graph is the time series for each source. Lower three ',...
'are the subspace data, the model synthesized using the sources ',...
'and time series, and the residual between data and model. The ',...
'locations and orientations of the sources are given in the ',...
'listbox. '];
par2 = ['Left-Click on any line in the listbox to see the ',...
'corresponding time series highlighted.'];
par3 = ['Right-click on any line in the top time series window to ',...
'see the corresponding source number. Select the "flip ',...
'orientation" item to reverse the polarity of the time ',...
'series and corresponding moment orientation.'];
par4 = ['Synchronous sources: The location and moment are listed ',...
'for each source, followed by the percent variance of each ',...
'source. In other words, 50% indicates that each source ',...
'uses 50% of the "energy" of the corresponding time series. ',...
'It does not necessarily equate to the energy contribution ',...
'of that source to the model. Similarly, 2% may indicate ',...
'a spurious second dipole in the model.'];
bst_message_window('wrap',{'','DRAFT: Help for the Time Series Results',...
'',par1,'',par2,'',par3,'',par4,''});
% --------------------------------------------------------------------
function varargout = pushbutton_quit_Callback(h, eventdata, handles, varargin)
close(handles.figure_time_series)
% --------------------------------------------------------------------
function varargout = pushbutton_print_Callback(h, eventdata, handles, varargin)
% we want to look reasonably pretty for possible publication
fig = handles.figure_time_series;
figure(fig);
set(fig,'menubar','figure'); % make the standard menu bar available
% force the listbox to be black and white for pretty print
set(handles.listbox_sourceparam,'foregroundcolor','k','backgroundcolor','w');
% black/white the checkbox too
set(handles.checkbox_scale,'foregroundcolor','k','backgroundcolor','w');
printpreview(handles.figure_time_series)
% --------------------------------------------------------------------
function varargout = checkbox_scale_ButtonDownFcn(h, eventdata, handles, varargin)
bst_message_window('wrap',{'','DRAFT HELP on meaning of scale'});
% --------------------------------------------------------------------
function varargout = checkbox_scale_Callback(h, eventdata, handles, varargin)
plot_time_series(h,eventdata,handles);
% --------------------------------------------------------------------
function varargout = uimenu_flip_orientation_Callback(h, eventdata, handles, varargin)
% flip the time series and associated orientation of the source
SourceNumber = getappdata(h,'SourceNumber'); % which source has been clicked on
fig = handles.figure_time_series;
Results = getappdata(fig,'Results');
UnscaledTime = getappdata(fig,'UnscaledTime');
Results.TimeSeries(:,SourceNumber) = -Results.TimeSeries(:,SourceNumber);
Results.SourceOrientation{SourceNumber} = -Results.SourceOrientation{SourceNumber};
UnscaledTime(:,SourceNumber) = -UnscaledTime(:,SourceNumber);
setappdata(fig,'Results',Results);
setappdata(fig,'UnscaledTime',UnscaledTime);
update_listbox(h,eventdata,handles);
plot_time_series(h,eventdata,handles);
Produced by color_mat2html, a customized BrainStorm 2.0 (Alpha) version of mat2html on Tue Oct 12 12:05:14 2004
Cross-Directory links are: ON