function varargout = parametric_estimation(varargin)
%PARAMETRIC_ESTIMATION - GUI for selecting data segments and subspaces prior to estimation
% function varargout = parametric_estimation(varargin)
%    FIG = PARAMETRIC_ESTIMATION launch parametric_estimation GUI.
%    PARAMETRIC_ESTIMATION('callback_name', ...) invoke the named callback.
%
% Application Data in this GUI, handles.ParametricEstimation
%  StudySubject, standard structure
%  Data, standard structure as loaded from the disk
%  DataFile, fully qualified filename
%  USV, decomposition of selected data segment
%  hplot, handle to the vertical line the SVD plot

%<autobegin> ---------------------- 16-Jun-2004 16:50:24 -----------------------
% --------- Automatically Generated Comments Block Using AUTO_COMMENTS ---------
%
% CATEGORY: Inverse Modeling
%
% Alphabetical list of external functions (non-Matlab):
%   toolbox\aic_mdl.m
%   toolbox\bst_color_scheme.m
%   toolbox\bst_layout.m
%   toolbox\bst_message_window.m
%   toolbox\bst_static_taskbar.m
%   toolbox\data_manager.m
%   toolbox\dataplot_cb.m
%   toolbox\find_brainstorm_structure.m
%   toolbox\get_user_directory.m
%   toolbox\good_channel.m
%   toolbox\least_squares_parameters_cb.m
%   toolbox\load_brainstorm_file.m
%   toolbox\rap_music_parameters.m
%   toolbox\save_fieldnames.m
%   toolbox\svd0.m
%
% Subfunctions in this file, in order of occurrence in file:
%   reset_gui(h, eventdata, handles, varargin);
%   load_gui(h,eventdata,handles,varargin);
%   V = zoom_axis(h, eventdata, handles, varargin);
%   set_axis(h,eventdata,handles,varargin,V);
%   update_stats(h, eventdata, handles, varargin);
%   decompose(h,eventdata,handles,varargin);
%   plot_signalnoise(h,eventdata,handles,varargin);
%   GUI = start_gui_structure(h,eventdata,handles,varargin);
%   varargout = PopupSVD_Callback(h, eventdata, handles, varargin)
%   varargout = EditRank_Callback(h, eventdata, handles, varargin)
%   varargout = SliderRank_Callback(h, eventdata, handles, varargin)
%   varargout = EditMinTime_Callback(h, eventdata, handles, varargin)
%   varargout = EditMaxTime_Callback(h, eventdata, handles, varargin)
%   varargout = Data_Stats_Callback(h, eventdata, handles, varargin)
%   varargout = AxisStudy_ButtonDownFcn(h, eventdata, handles, varargin)
%   varargout = AxisSignalSubspace_ButtonDownFcn(h, eventdata, handles, varargin)
%   varargout = AxisNoiseSubspace_ButtonDownFcn(h, eventdata, handles, varargin)
%   varargout = AxisSVD_ButtonDownFcn(h, eventdata, handles, varargin)
%   varargout = Pushbutton_decompose_Callback(h, eventdata, handles, varargin)
%   varargout = DatabaseManager_Callback(h, eventdata, handles, varargin)
%   varargout = pushbutton_reload_data_Callback(h, eventdata, handles, varargin)
%   varargout = pushbutton_help_Callback(h, eventdata, handles, varargin)
%   varargout = button_grid_Callback(h, eventdata, handles, varargin)
%   varargout = Quit_Callback(h, eventdata, handles, varargin)
%   varargout = radiobutton_eeg_Callback(h, eventdata, handles, varargin)
%   varargout = radiobutton_meg_Callback(h, eventdata, handles, varargin)
%   varargout = EstimationTechnique_Callback(h, eventdata, handles, varargin)
%   varargout = togglebutton_zoom_Callback(h, eventdata, handles, varargin)
%   varargout = togglebutton_zoom_ButtonDownFcn(h, eventdata, handles, varargin)
%   varargout = popupmenu_domain_Callback(h, eventdata, handles, varargin)
%   varargout = uicontextmenu_selection_action_Callback(h, eventdata, handles, varargin)
%   varargout = uimenu_data_exclude_Callback(h, eventdata, handles, varargin)
%   varargout = uimenu_clear_data_exclusion_Callback(h, eventdata, handles, varargin)
%   varargout = uimenu_subspace_reject_Callback(h, eventdata, handles, varargin)
%   varargout = uimenu_clear_projector_Callback(h, eventdata, handles, varargin)
%   varargout = togglebutton_projector_detect_Callback(h, eventdata, handles, varargin)
%   varargout = uimenu_help_selection_action_Callback(h, eventdata, handles, varargin)
%
% Application data and their calls in this file:
%   'Data'
%   'DataFile'
%   'StudySubject'
%   'TileType'
%   'USV'
%   'hplot'
%   'hvertical_lines'
%   'rbbox_points'
%   
%   setappdata(fig,'Data',Data);
%   setappdata(fig,'DataFile',DataFile);
%   setappdata(fig,'StudySubject',StudySubject);
%   setappdata(fig,'TileType','T');
%   setappdata(fig,'USV',struct('U',U,'S',S,'V',V,'vSeS',[vS eS],...
%   setappdata(fig,'hplot',hplot);
%   setappdata(fig,'hvertical_lines',hvertical_lines);
%   setappdata(fig,'rbbox_points',[]);
%   setappdata(fig,'rbbox_points',[p1;p2]);
%   
%   Data = getappdata(fig,'Data');
%   DataFile = getappdata(fig,'DataFile');
%   StudySubject = getappdata(fig,'StudySubject');
%   USV = getappdata(fig,'USV');
%   data.Measures.NoiseModelParam.StudySubject = getappdata(fig,'StudySubject');
%   filename = getappdata(fig,'DataFile');
%   hplot = getappdata(fig,'hplot');
%   hvertical_lines = getappdata(fig,'hvertical_lines');
%   points = getappdata(fig,'rbbox_points');
%
% Figure Files opened by this function:
%   'dataplot.fig'
%   mfilename
%
%   Format of strings below: Type:Style:Tag, "String", CallBack Type and Call
%   <automatic> callback is <Tag>_Callback by Matlab default
%
% Callbacks by figure dataplot.fig
%   figure::DATAPLOT "" uses DeleteFcn for clear global data
%   uicontrol:edit:current_time "0" uses Callback for dataplot_cb set_current_time
%   uicontrol:edit:step "''" uses Callback for dataplot_cb set_time_step
%   uicontrol:edit:time_max "" uses Callback for dataplot_cb set_time_max
%   uicontrol:edit:time_min "" uses Callback for dataplot_cb set_time_min
%   uicontrol:popupmenu:ChangeUnits "MKS" uses Callback for
%     dataplot_cb('ChangeUnits','reset'),dataplot_cb ChangeUnits
%   uicontrol:popupmenu:DataViewingDataType "Original Data" uses Callback for
%     dataplot_cb DataViewingDataType
%   uicontrol:popupmenu:DataViewingSpatialDisplay "<No Scalp Topography>" uses Callback for
%     dataplot_cb('DataViewingSpatialDisplay', 'reset'), dataplot_cb DataViewingSpatialDisplay
%   uicontrol:popupmenu:DataViewingTimeDisplay "<No Time Display>" uses Callback for
%     dataplot_cb DataViewingTimeDisplay
%   uicontrol:popupmenu:SourceEstimationMethod "-------- IMAGING " uses Callback for
%     dataplot_cb SourceImaging
%   uicontrol:popupmenu:SourceViewingSpatialDisplay "<No Spatial Topography>" uses Callback for
%     dataplot_cb SourceViewingSpatialDisplay
%   uicontrol:popupmenu:SourceViewingTimeDisplay "<No Time Display>" uses Callback for
%     dataplot_cb SourceViewingTimeDisplay
%   uicontrol:pushbutton:HPlot "Plot" uses Callback for dataplot_cb('Plot','Measures')
%   uicontrol:pushbutton:HPlotTimeSeries "Plot" uses Callback for dataplot_cb('Plot','RESULTS')
%   uicontrol:pushbutton:HSetDataViewing "Set" uses Callback for dataplot_cb SetDataViewing
%   uicontrol:pushbutton:HSetSourceViewing "Set" uses Callback for dataplot_cb SetSourceViewing
%   uicontrol:pushbutton:MSIndexSwitch "ms/index" uses Callback for dataplot_cb MSIndexSwitch
%   uicontrol:pushbutton:NoiseModel "Noise Model" uses Callback for dataplot_cb CallDataSelector
%   uicontrol:pushbutton:pushbutton6 "Save" uses Callback for dataplot_cb saveas
%   uicontrol:pushbutton:SourceModel "Source Model" uses Callback for
%     dummy_dynamic_viewer('pushbutton11_Callback',gcbo,[],guidata(gcbo))
%   uicontrol:slider:TimeSlider "" uses Callback for dataplot_cb mapping_slider
%
% Callbacks by figure parametric_estimation.fig
%   axes::AxisNoiseSubspace "" uses ButtonDownFcn for <automatic>
%   axes::AxisSignalSubspace "" uses ButtonDownFcn for <automatic>
%   axes::AxisSVD "" uses ButtonDownFcn for <automatic>
%   uicontextmenu::uicontextmenu_selection_action "" uses Callback for <automatic>
%   uicontrol:checkbox:button_grid "Gridding" uses Callback for <automatic>
%   uicontrol:checkbox:PopupSVD "Log Y-Axis" uses Callback for <automatic>
%   uicontrol:edit:EditMaxTime "Max" uses Callback for <automatic>
%   uicontrol:edit:EditMinTime "Min" uses Callback for <automatic>
%   uicontrol:edit:EditRank "Rank" uses Callback for <automatic>
%   uicontrol:listbox:Data_Stats "Time Index:" uses Callback for <automatic>
%   uicontrol:popupmenu:EstimationTechnique "Select Method . . ." uses Callback for <automatic>
%   uicontrol:popupmenu:popupmenu_domain "Time" uses Callback for <automatic>
%   uicontrol:pushbutton:DatabaseManager "Data Manager" uses Callback for <automatic>
%   uicontrol:pushbutton:Pushbutton_decompose "Decompose" uses Callback for <automatic>
%   uicontrol:pushbutton:pushbutton_help "Help" uses Callback for <automatic>
%   uicontrol:pushbutton:pushbutton_reload_data "Reload Data" uses Callback for <automatic>
%   uicontrol:pushbutton:Quit "Done" uses Callback for <automatic>
%   uicontrol:radiobutton:radiobutton_eeg "EEG Data" uses Callback for <automatic>
%   uicontrol:radiobutton:radiobutton_meg "MEG Data" uses Callback for <automatic>
%   uicontrol:slider:SliderRank "" uses Callback for <automatic>
%   uicontrol:togglebutton:togglebutton_projector_detect "No Projector Detected" uses Callback for <automatic>
%   uicontrol:togglebutton:togglebutton_zoom "Zoom Mode" uses ButtonDownFcn for <automatic>
%   uicontrol:togglebutton:togglebutton_zoom "Zoom Mode" uses Callback for <automatic>
%   uimenu::uimenu_clear_data_exclusion "" uses Callback for <automatic>
%   uimenu::uimenu_clear_projector "" uses Callback for <automatic>
%   uimenu::uimenu_data_exclude "" uses Callback for <automatic>
%   uimenu::uimenu_help_selection_action "" uses Callback for <automatic>
%   uimenu::uimenu_subspace_reject "" uses Callback for <automatic>
%
% At Check-in: $Author: Mosher $  $Revision: 49 $  $Date: 6/16/04 3:16p $
%
% This software is part of BrainStorm Toolbox Version 2.0 (Alpha) 16-Jun-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> ------------------------ 16-Jun-2004 16:50:24 -----------------------



% Last Modified by GUIDE v2.0 10-Jul-2003 17:28:47

% ----------------------------------------------
% JCM spring 2002  development
% JCM 02-Jul-2002  detect if projector has the right number of rows, ignore if different
% JCM 31-Oct-2002  Comments editing, alteration of Estimation activation button
% SB  20-Nov-2002  Minor display enhancements
%                  Fixed issues related to data sets with both EEG and MEG data
% SB  11-Jul-2003  Made the link with the Viewer
% ----------------------------------------------

if nargin == 0  % LAUNCH GUI

    fig = openfig(mfilename,'reuse'); % SB | Just open it once

    % 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

   % custom routines
   bst_color_scheme(fig);
   set(handles.Data_Stats,'fontname','default'); % prettier than fixedwidth
   setappdata(fig,'TileType','T'); % a tile
   bst_layout('align',fig,1,1,1); % one big tile
   set(fig,'Visible','on')  
   
   % now initialize
   reset_gui(fig,[],handles,[]); % setup all uicontrols
   load_gui(fig,[],handles,[]); % load the current datamanager trial
   
   
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 ------------------------------
% ----------------------------- RESET GUI -------------------------------
function reset_gui(h, eventdata, handles, varargin);
% reset all of the uicontrols
% Reset all of the buttons to initial values, refresh the studies list
% Objects:  AxisStudy, AxisSignal, AxisNoise, AxisSVD
%  EditMinTime, EditMaxTime, EditRank, SliderRank, SliderCorr,
%  PopupSVD

fig = handles.ParametricEstimation; % handy shortcut

% set zoom default on
set(handles.togglebutton_zoom,'Val',1);
% set the color correctly
togglebutton_zoom_Callback(handles.togglebutton_zoom, eventdata, handles, varargin)


% clear the strings, enable
TAGS ={'EditMinTime', 'EditMaxTime', 'EditRank'}; 
for i = 1:length(TAGS),
   ht = getfield(handles,TAGS{i});
   set(ht,'Enable','On','String',' ');
end

% set the initial value to zero on the sliders, enable
TAGS = {'SliderRank'};
for i = 1:length(TAGS),
   ht = getfield(handles,TAGS{i});
   set(ht,'Enable','On','Min',0,'Max',1,'Value',0);
end
TAGS = {'EditRank'};
for i = 1:length(TAGS),
   ht = getfield(handles,TAGS{i});
   set(ht,'Enable','On','String',0);
end

% set the initial value of popups to one, enable
TAGS = {'PopupSVD'};  
for i = 1:length(TAGS),
   ht = getfield(handles,TAGS{i});
   set(ht,'Enable','On','Value',1);
end

% clear all of the axes
TAGS = {'AxisSignalSubspace', 'AxisNoiseSubspace', 'AxisSVD'};
for i = 1:length(TAGS),
   ht = getfield(handles,TAGS{i});
   set(fig,'CurrentAxes',ht);
   cla % do not use cla reset
   axis tight
   zoom off % don't want competition with our own zoom function
end

if(isappdata(fig,'Data')),
   rmappdata(fig,'Data'); % the current data set
end
if(isappdata(fig,'USV')),
   rmappdata(fig,'USV'); % it's decomposition
end
if(isappdata(fig,'SubjectStudy')),
   rmappdata(fig,'SubjectStudy'); % and the file information
end
if(isappdata(fig,'hplot')),
   rmappdata(fig,'hplot'); % the handle to the SVD vertical line
end

% the rubber band points for selecting a data region
if(~isappdata(fig,'rbbox_points'))
   setappdata(fig,'rbbox_points',[]); % initialize as empty
end

% can't do until decomposed:
set(handles.radiobutton_meg,'Enable','off');
set(handles.radiobutton_eeg,'Enable','off');
set(handles.SliderRank,'Enable','off');
set(handles.EditRank,'Enable','off');
set(handles.EstimationTechnique,'Enable','off');

% these uimenus are not yet ready for use:
set(handles.uimenu_data_exclude,'Enable','Off');
set(handles.uimenu_clear_data_exclusion,'Enable','Off');

% reset title of the main data graph
% set(handles.text_stdata,'string','Spatio-temporal Data');

if(0)
   % now set up custom actions for each important object. 
   % Should have been saved with the .fig,
   %  but caca pasa
   ht = findobj(hf,'Tag','AxisStudy');
   set(ht,'ButtonDownFcn','data_selector_cb(''set time'')');  
   
   ht = findobj(hf,'Tag','SliderRank');
   set(ht,'Value',0,'Min',0,'Max',1,'callback','data_selector_cb(''set sliderrank'')');
   ht = findobj(hf,'Tag','EditRank');
   set(ht,'String','0','callback','data_selector_cb(''set textrank'')');
   
   ht = findobj(hf,'Tag','EditMinTime');
   set(ht,'Callback','data_selector_cb(''set mintime'')');
   ht = findobj(hf,'Tag','EditMaxTime');
   set(ht,'Callback','data_selector_cb(''set maxtime'')');
   
   ht = findobj(hf,'Tag','Source Estimation');
   set(ht,'Enable','off'); % can't do estimation without data
   % end of reset
end





% -----------------------LOAD GUI WITH DATA FROM DATAMANAGER ---------------
function load_gui(h,eventdata,handles,varargin);

fig = handles.ParametricEstimation; % shortcut

% Get the current data and load into the axis
User = get_user_directory;
if 0 %~isfield(User,'CurrentData') | ~isfield(User.CurrentData,'DataFile')
    bst_message_window({'','Use Data Manager to select trial first'});
    data_manager
    return
end

% Filename = fullfile(User.STUDIES,User.CurrentData.StudyFile);
StudySubject = find_brainstorm_structure(User.CurrentData.StudyFile);


% two methods of acquiring the data, either from the files or from the
%  global variable
METHOD_FILE = 1;
METHOD_GLOBAL = 2;
METHOD = METHOD_GLOBAL;%METHOD_FILE; % hardwire

switch METHOD
case METHOD_FILE
   
   [PathStr,Name,Ext,Versn] = fileparts(User.CurrentData.StudyFile);
   DataFile = bst_static_taskbar('GET','DATA');
   DataFile = DataFile{1};
   Data = load_brainstorm_file(DataFile); % only the first one 
   Channel = load_brainstorm_file(StudySubject.Channel);
   Channel = Channel.Channel;
   
   % what time samples are desired
   try
      [ignore,timeNdx] = dataplot_cb('GET','TIME');
   catch
      % dataplot_cb may not have been open
      timeNdx = [1:size(Data.F,2)]; % assume all of the data
   end
   
   Data.F = Data.F(:,timeNdx);
   Data.Time = Data.Time(timeNdx);

   % [val,enable,h] = bst_static_taskbar('GET','MEG');
   % MEG = ~isempty(data.SelectedChannels{1}) & val ;
   % [val,enable,h] = bst_static_taskbar('GET','EEG');
   % EEG = ~isempty(data.SelectedChannels{2}) & val;
   % [val,enable,h] = bst_static_taskbar('GET','OTHER');
   % Other= ~isempty(data.SelectedChannels{3}) & val;
   % Test = [MEG,EEG,Other];
   % Label = {'MEG','EEG','OTHER'};
   %data.imod = find(Test);
   % if length(data.imod) > 1 % More than one modality selected
   %     errordlg('Please select only either MEG or EEG for noise modelling.')
   %     return
   % end
   % Sanity checks ----------DONE----------
   
   % Use Mosher Data structure: initialize and fill all fields
   
case METHOD_GLOBAL 
   
   global data % Get data from the Viewer's strcuture   
   if isempty(data)
      disp('No global data selected.')
      return
   end
   
   % reassign the data variables
   DataFile = data.Measures.Filename{1}; % consider only the first filename
   % Get current time window defined in Viewer
   Data.Time =  linspace(data.Display.Time(1), data.Display.Time(end),data.Display.NumberOfSamples);
   Data.F = data.Measures.F{1}; % and only the first data cell element
   Channel = data.Measures.Channel;
   Data.ChannelFlag = data.Measures.ChannelFlag;
   cd(User.STUDIES)
   
   % what time samples are desired
   try
      [ignore,timeNdx] = dataplot_cb('GET','TIME');
   catch
      % dataplot_cb may not have been open
      timeNdx = [1:size(Data.F,2)]; % assume all of the data
   end
   
   if 0, % deprecated code | SB 14-06-04 | Data.F and .Time now are trimmed to what is seen in Viewer
       Data.F = Data.F(:,timeNdx);
       Data.Time = Data.Time(timeNdx);
   end


end % which data loading method
   
% load the projector
Users = get_user_directory;
cd(Users.STUDIES)
tmp = load(DataFile,'Projector'); 
Data.Projector = tmp.Projector; 
clear tmp

% load the Noise Covariance (actually, square root)
tmp = load(DataFile,'NoiseCov'); % load the noise covariance sqrt
Data.NoiseCov = tmp.NoiseCov;
clear tmp
    
GoodChannelEEG = good_channel(Channel,Data.ChannelFlag,'EEG');
GoodChannelMEG = good_channel(Channel,Data.ChannelFlag,'MEG');
% CHEAT: What about the reference channels?

if(isempty(GoodChannelMEG) & isempty(GoodChannelEEG)),
   % both were empty!
   bst_message_window({'','No valid EEG or MEG data!'});
   return
else
    bst_message_window('wrap',...
        {...
            ' ',...
            'Current analysis consists of:',...
            sprintf('%d good EEG channels',length(GoodChannelEEG))...
            sprintf('%d good MEG channels',length(GoodChannelMEG)),...
        })
end


if 0, % deprecated code (was problematic when file contains both EEG and MEG). Read what user wants to look at from bst_static_taskbar 
    % activate radio buttons as available
    if(~isempty(GoodChannelMEG)),
        % meg data, enable and check the button on
        set(handles.radiobutton_meg,'enable','on');
    else
        % no MEG data, be sure the EEG the EEG button is on
        set(handles.radiobutton_meg,'val',0); % no meg
        set(handles.radiobutton_eeg,'val',1); % must be eeg
    end
    
    if(~isempty(GoodChannelEEG)),
        % eeg data, enable and check the button on
        set(handles.radiobutton_eeg,'enable','on');
    else
        % no EEG data, be sure the MEG button is on
        set(handles.radiobutton_meg,'val',1); % must be meg data
        set(handles.radiobutton_eeg,'val',0); % no eeg data
        
    end
end

% What does the user want to look at MEG? EEG? Both ? etc. 
% Get this information from checkboxes in Static Taskbar
[ValMEG,enable,hMEG] = bst_static_taskbar('GET','MEG');
[ValEEG,enable,hEEG] = bst_static_taskbar('GET','EEG');
[valOTHER,enable,hOTHER] = bst_static_taskbar('GET','OTHER');

if ValEEG & ValMEG
    valEEG = 0; % when both are available look at MEG only by default 
end

set(handles.radiobutton_meg,'val',ValMEG); 
set(handles.radiobutton_eeg,'val',ValEEG); 


% % what is the status of the data radio buttons
% ValEEG = get(handles.radiobutton_eeg,'val');
% ValMEG = get(handles.radiobutton_meg,'val');

% by the nature of those buttons, one of them has to be set.
GoodChannel = [];
if(ValEEG),
    imod = 2;
    GoodChannel = [GoodChannel GoodChannelEEG];
end
if(ValMEG),
    imod = 1;
    GoodChannel = [GoodChannel GoodChannelMEG];
end

if isempty(GoodChannel)
    errordlg('Please select either MEG, EEG or OTHER from static taskbar','Empty channel selection');
    return
end

Data.Selected_Channel = GoodChannel; %[GoodChannelMEG;GoodChannelEEG]; % SB 20-Nov-2002 : Fixing issues related to data sets with both EEG and MEG data

% is there a projector in the data?
Colors = bst_color_scheme;
if(~isempty(Data.Projector)), 
   if(size(Data.Projector,1) ~= length(Data.Selected_Channel)),
      % invalid projector for channels selected
      bst_message_window('wrap',['Projector has a different number of rows than the ' ...
            'the channels selected. Projector ignored.']);
      Data.Projector = [];
   end
end


% Apply the whitener, if any
if ~isempty(Data.NoiseCov),
   W = Data.NoiseCov(Data.Selected_Channel,:); % the portion of the data
   if any(isnan(W(:))),
      bst_message_window('NaNs in the noise covariance, re-estimate.')
   else
      Data.F(Data.Selected_Channel,:) = pinv(W)*Data.F(Data.Selected_Channel,:);
   end
end

% Apply the projector, if any
if ~isempty(Data.Projector),   
   Data.F(Data.Selected_Channel,:) = Data.F(Data.Selected_Channel,:) - ...
      Data.Projector*(Data.Projector'*Data.F(Data.Selected_Channel,:));
   set(handles.togglebutton_projector_detect,'value',1,'BackgroundColor',...
      Colors.ToggleOn,'ForegroundColor',[.5 .5 .5],'String',...
      'Projector Applied');
else
   % no projector data detected
   set(handles.togglebutton_projector_detect,'value',0,'BackgroundColor',...
      Colors.ToggleOff,'ForegroundColor',Colors.ButtonText,'String',...
      'No Projector Detected');
end


setappdata(fig,'StudySubject',StudySubject);
setappdata(fig,'Data',Data);
setappdata(fig,'DataFile',DataFile);

% now display in the AxisStudy

set(0,'CurrentFigure',fig);
set(fig,'CurrentAxes',handles.AxisSignalSubspace);
cla
hl=line(Data.Time*1000,Data.F(Data.Selected_Channel,:));
set(hl,'hittest','off'); % nothing happens when clicking on line
axis tight
xlabel('Time (ms)');
ylabel('Amplitude');

set(handles.AxisNoiseSubspace,'Xlim',xlim);

V = axis;
set(handles.EditMinTime,'String',sprintf('%.1f ms',V(1)));
set(handles.EditMaxTime,'String',sprintf('%.1f ms',V(2)));


update_stats(h,eventdata,handles,varargin);





% -------------------- CUSTOM ZOOMING FUNCTION --------------------------
function V = zoom_axis(h, eventdata, handles, varargin);
% Zoom the axis given by h if left click, reset zoom if right click
% Use only in buttondown functions for each of the axes
% Return the new axis settings

% Zoom control only works if the Zoom toggle button is selected
% If Zooming is off, then only gather the rubberband information
%  and store in the application data.
% Exception is if we are clicking on the SVD axis, for which zoom is always on
% 

fig = handles.ParametricEstimation; % shorthand

ZoomVal = get(handles.togglebutton_zoom,'Val');

if(h==handles.AxisSVD),
   ZoomVal = 1; % effectively zoom is always on for the SVD display
end

Type = get(fig,'selectiontype'); %what kind of click

% make the gcbo the current axes
set(fig,'CurrentAxes',h);

V = axis; % current settings 

switch Type
case 'normal' % left click
   point1 = get(h,'CurrentPoint');   % button down detected
   finalRect = rbbox;               % return figure units
   point2 = get(h,'CurrentPoint');    % button up detected
   % more useful is to use the starting and ending points of the button clicks:
   point1 = point1(1,1:2);             % extract x and y (z meaningless here)
   point2 = point2(1,1:2);
   p1 = min(point1,point2);   % calculate locations
   p2 = max(point1,point2);   % p1 is lower left, p2 is upper right of box
   
   if(ZoomVal), % zooming is on
      offset = abs(point1-point2);        % and dimensions
      V = axis; % current settings
      % if user only drew a box less than 5% (1/20th) in both directions,
      %  then ignore
      if(offset(1) > (V(2)-V(1))/20 | offset(2) > (V(4)-V(3))/20)
         % box greater than 5% in one direction, zoom to it
         V = [p1(1) p2(1) p1(2) p2(2)]; % return new settings
         axis(V)
      else
         % box too small in both dimensions, do nothing
      end

   else 
      % zooming is off, store rubberband information only
      setappdata(fig,'rbbox_points',[p1;p2]);
      
      % draw vertical lines, possibly deleting older ones
      if(isappdata(fig,'hvertical_lines')),
         hvertical_lines = getappdata(fig,'hvertical_lines');
         if(ishandle(hvertical_lines)),
            % could be older handles that no longer exist
            delete(hvertical_lines)
         end
      end
      
      hvertical_lines = line([p1(1) p2(1);p1(1) p2(1)],[V(3);V(4)]);
      set(hvertical_lines,'linewidth',4,'color','k');
 
      setappdata(fig,'hvertical_lines',hvertical_lines);
   end
   
otherwise
   % not a single left click
   if(ZoomVal),
      % zooming is on, so zoom out
      axis tight % "zoom out" to the full coordinates of the data
      V = axis; % return new settings
   else
      % zooming is off, do nothing. AxisStudy has a uicontextmenu that
      %  will popup in this case
   end
end





% ---------------------- MAKE ALL AXES HAVE SAME RANGE -------------------
function set_axis(h,eventdata,handles,varargin,V);
fig = handles.ParametricEstimation; % shorthand

% set(fig,'CurrentAxes',handles.AxisStudy);
% axis(V);
set(fig,'CurrentAxes',handles.AxisSignalSubspace);
axis(V);
set(fig,'CurrentAxes',handles.AxisNoiseSubspace);
axis(V);

set(handles.EditMinTime,'String',sprintf('%.1f ms',V(1)));
set(handles.EditMaxTime,'String',sprintf('%.1f ms',V(2)));




% ---------------------UPDATE STATISTICS IN LISTBOX --------------------
function update_stats(h, eventdata, handles, varargin);
fig = handles.ParametricEstimation; % shorthand

% update the Data_Stats listbox with information
% Is the SVD axis active?
Val = str2num(get(handles.EditRank,'string'));
if(Val), % non-zero, active
   Data = getappdata(fig,'Data');
   USV = getappdata(fig,'USV'); % decomposition
   S2 = full(diag(USV.S)).^2; % singular values squared
   E2 = USV.vSeS(:,2).^2; % estimated floor
   
   TotalVar = sum(S2);
   SignalVar = sum(S2(1:Val));
   NoiseVar = sum(S2((Val+1):end));
   ENoiseVar = sum(E2);
   msg_str = {...
         sprintf('%20s: %.0f of %.0f','Rank',Val,length(S2)),...
         sprintf('%20s: %5.1f%%','Signal Subspace',SignalVar/TotalVar*100),...
         sprintf('%20s: %5.1f%%','Noise Subspace',NoiseVar/TotalVar*100),...
         sprintf('%20s: %5.1f%%','Approximated Noise',ENoiseVar/TotalVar*100),...
         '',...
         sprintf('Time selected: %.1f ms, %.0f samples',...
         diff(USV.Time([1 end]))*1000,length(USV.Segment)),...
         sprintf('Interval selected: %.1f  to  %.1f ms',...
         USV.Time([1 end])*1000),...
         sprintf('Indices selected: %.0f to %.0f',USV.Segment([1 end])),...
         sprintf('Available: %.1f ms from %.1f to %.1f ms',...
         diff(Data.Time([1 end]))*1000,Data.Time([1 end])*1000),...
         sprintf('  %.0f samples at %.1f samples/sec',length(Data.Time),...
         length(Data.Time)/diff(Data.Time([1 end]))),...
         sprintf('Channels selected: %.0f of %.0f',...
         length(Data.Selected_Channel),length(Data.ChannelFlag)),...
         ''};
else
   msg_str = {'"Decompose" for Stats',''};
end

StudySubject = getappdata(fig,'StudySubject');
User = get_user_directory;

%sprintf('Subject Name: %s',User.CurrentData.SubjectName),... % SB- 10-Oct-2003 removed display of subject name because it's not
% straightfully available from User structure
User.CurrentData.DataFile = bst_static_taskbar('GET','DATA');
User.CurrentData.DataFile = User.CurrentData.DataFile{1};
msg_str = [msg_str, {...
         sprintf('Database: %s',User.Comment),...   
         sprintf('Data File: %s',User.CurrentData.DataFile),...
         sprintf(''),...
         sprintf('Subject: %s',StudySubject.Subject),...
         sprintf('Study: %s',StudySubject.Study),...
         sprintf('Channel: %s',StudySubject.Channel),...
         sprintf('HeadModel: %s',StudySubject.HeadModel)}];

set(handles.Data_Stats,'string',msg_str);

% update the title of the main graph
% what radio buttons are selected
ValE = get(handles.radiobutton_eeg,'val');
ValM = get(handles.radiobutton_meg,'val');

if(ValE & ~ValM),
   SUFFIX = 'EEG Data';
elseif(~ValE & ValM),
   SUFFIX = 'MEG Data';
elseif(ValE & ValM),
   SUFFIX = 'E/MEG Fusion';
else
   SUFFIX = 'Bogus Case';
end

%set(handles.text_stdata,'string',[User.CurrentData.DataFile ' ' SUFFIX]); SB





% ----------------- SVD THE DATA DISPLAYED IN THE TOP  DATA WINDOW ---------
function decompose(h,eventdata,handles,varargin);
% decompose the data and display
fig = handles.ParametricEstimation; % figure handle

set(handles.PopupSVD,'Value',1); % force a log state
% retrieve the state
iLogLin = get(handles.PopupSVD,'Value'); % 1 is log, 0 is linear
   
% generate and save decomposed data
Data = getappdata(fig,'Data'); %the current data

% what has the user selected
set(0,'CurrentFigure',fig);
%set(fig,'CurrentAxes',handles.AxisStudy); SB
set(fig,'CurrentAxes',handles.AxisSignalSubspace);
V = axis; % current limits

Time = Data.Time;
mni = min(find(Time*1000 >= V(1))); % time index is in ms, set in display_data
mxi = max(find(Time*1000 <= V(2)));
F = Data.F(Data.Selected_Channel,[mni:mxi]); % what user has selected % was mni:mxi | SB
Time = Data.Time([mni:mxi]);

% is this a really big data set?
BIG = prod(size(F)) > 1e5;
if(BIG),
   bst_message_window('Decomposing large set of selected data . . .');
end
set(fig,'pointer','watch'); % wait symbol

[U,S,V] = svd0(F); % economy SVD
S = sparse(S); % make sparse

% build noise estimate
nS = min(size(S)); % how many values
if(nS > 1),
   vS = full(diag(S)); % vector form of S
else
   vS = full(S);
end

% vS is a vector of singular values.
% Because of log plotting, don't want truly zero values
% Adjust to be at noise floor
vndx = find(vS < (eps*vS(1))); % less than epsilon
vS(vndx) = eps*vS(1); % set to noise floor

switch 2 % which method for estimating the noise floor   
case 1
   % old method of fitting linear line to smaller singular value
   midS = [1:round(nS/3)]'; % third the data
   midS = midS + round(nS/2); % centered on the half
   if(length(midS) >= 2), % need two points to define a line
      eS = polyval(polyfit(midS,vS(midS),1),[1:nS]'); % first order fit
   else
      % degenerate case, may be single time slice fitting
      eS = vS(end)+zeros(nS,1); % set to last value
   end
   ndx = find(eS <= 0); % negative values
   if(~isempty(ndx)), % some values
      eS(ndx) = eS(ndx(1)-1); % set to smallest positive value
   end
   
case 2
   % new method November 2003 using MDL
   vndx = find(vS < .005*vS(1)); % less than this, don't believe
   if ~isempty(vndx)
      % now synthesize new noise with vndx(1) as the noise level
      vSadjust = svd(F + (vS(vndx(1))*randn(size(F))) );
   else
      vSadjust = vS; % keep as is
   end
   dim = aic_mdl(vSadjust.^2, size(F,2));
   RANK = dim(2); % the MDL method
   eS = zeros(size(vS)) + sqrt(mean(vSadjust((RANK+1):end).^2)); % average of the noise
end
% result of above switch case is vector eS of estimated singular values
% [vS eS] is singular values and estimated noise values

% setappdata(fig,'USV',struct('U',U,'S',S,'V',V,'vSeS',[vS eS],...
%    'Time',Time(mni:mxi),'Segment',[mni:mxi]));
% Indices of the time samples in original data time window
% SB 18-Nov-2003 : get proper subset of time samples from original data
[tmp,TimeSegment] = dataplot_cb('GET','time');

setappdata(fig,'USV',struct('U',U,'S',S,'V',V,'vSeS',[vS eS],...
   'Time',Time,'Segment',TimeSegment));

% Now set an initial RANK for the data matrix
switch 3
case 1
   % set the initial rank display to be 10%
   RANK = max(floor(length(vS)/10),1); % at least unity
case 2
   % set the rank based on estimated noise floor
   cS2 = cumsum(vS.^2); % cumulative squared singular values
   eS2 = sum(eS.^2)/cS2(end); % total estimated noise power as fraction
   cS2 = cS2/cS2(end); % scale of 0 to 1 for power
   cN2 = 1-cS2; % relative power in noise-only subspace
   RANK = max(find(cN2 >= eS2))+1;
   if(isempty(RANK)),
      RANK = 1; % minimum
   end
   RANK = min(RANK,length(vS)); % don't exceed limit
case 3
   % was set above by the MDL method, do nothing
end

% setup the slider
set(handles.EditRank,'String',int2str(RANK)); % set the rank field
MaxSlider = max(2,length(vS)); % need a minimum of two
set(handles.SliderRank,'Min',1,'Max',MaxSlider,'Value',RANK,'Enable','On',...
   'SliderStep',[1/MaxSlider max(.1,2/MaxSlider)]); % want unity steps
   
% now plot
set(0,'CurrentFigure',fig);
set(fig,'CurrentAxes',handles.AxisSVD);
cla
h = line([1:length(S)]',[vS eS]);
set(h,'marker','*');

switch iLogLin % which plot
case 0 % linear
   set(handles.AxisSVD,'yscale','linear');
case 1 % log
   set(handles.AxisSVD,'yscale','log')
otherwise
   % what otherwise?
   msgbox(sprintf('Error in plotting SVD','Error','modal'))
   return
end

axis tight
V = axis(handles.AxisSVD);
% % But don't be ridiculous about tight
% V(3) = max(V(3),V(4)/1e3);
% axis(V);
V = axis;

vline_height = diff(V(3:4)); % height of line
% extend upward by 5% for better visual effect
vline_height = vline_height * 1.05;

% plot the vertical bar between signal and noise subspace
hplot = line([RANK;RANK]'+.5,[V(3); V(3)+vline_height]);
set(hplot,'linewidth',2,'color','b','erasemode','xor');
setappdata(fig,'hplot',hplot); % the handle to this line

% now recursively call to plot the signal and noise data
plot_signalnoise(fig,eventdata,handles,varargin);

% set scales to the displayed data
% set(fig,'CurrentAxes',handles.AxisStudy); SB
set(fig,'CurrentAxes',handles.AxisSignalSubspace); 
V = axis;
set_axis(h, eventdata, handles, varargin, V);

% set(handles.EstimationTechnique,'Enable','on'); % now can estimate


set(fig,'pointer','arrow'); % wait symbol done
if(BIG), % update message window
   bst_message_window('overwrite','Done Decomposing');
end

figure(fig) % bring to front

% can now do:
set(handles.SliderRank,'Enable','on');
set(handles.EditRank,'Enable','on');
% set(handles.EstimationTechnique,'Enable','on');




% ------------------- UPDATE THE SIGNAL AND NOISE SUBSPACE PLOTS ---------
function plot_signalnoise(h,eventdata,handles,varargin);
    
fig = handles.ParametricEstimation;
set(0,'CurrentFigure',fig);

RANK = get(handles.SliderRank,'Value'); % what is the rank

if(~isappdata(fig,'USV')), % no decomposition available
   decompose(fig,eventdata,handles,varargin);
   % which will recursively call this routine again
else
   USV = getappdata(fig,'USV'); % get the decomposition information

   set(fig,'CurrentAxes',handles.AxisSignalSubspace);
   cla
   hs = line(USV.Time*1000,USV.U(:,1:RANK)*(USV.S(1:RANK,1:RANK)*USV.V(:,1:RANK)'));
   set(hs,'hittest','off'); % easier zooming
   ylabel('Signal Subspace')
   
   set(fig,'CurrentAxes',handles.AxisNoiseSubspace);
   cla
   hn = line(USV.Time*1000,...
      USV.U(:,(RANK+1):end)*(USV.S((RANK+1):end,(RANK+1):end)*USV.V(:,(RANK+1):end)'));
   set(hn,'hittest','off');
   ylabel('Noise Subspace')

   update_stats(h, eventdata, handles, varargin);
   

end




% --------------- PREPARE THE GUI STRUCTURE FOR EXECUTION --------------
function GUI = start_gui_structure(h,eventdata,handles,varargin);
% begin the basic GUI parameter structure from this figure's appdata
fig = handles.ParametricEstimation;

DataFile = getappdata(fig,'DataFile'); % name
Data = getappdata(fig,'Data'); % data
USV = getappdata(fig,'USV'); % decomposition
User = get_user_directory; % database
RANK = get(handles.SliderRank,'val'); % selected rank
ChannelFlag = -ones(size(Data.ChannelFlag)); %zeros(size(Data.ChannelFlag)); % initialize
ChannelFlag(Data.Selected_Channel) = 1; % set desired flags on

%Data.ChannelFlag is the status of all channels
%GUI.ChannelFlag indicates which channels to process this run

GUI = struct('DataName',DataFile,'Segment',USV.Segment,'Rank',RANK,...
   'ChannelFlag',ChannelFlag);



% ----------------- The Uicontrol Callbacks -----------------


% ----------------------SWITCH BETWEEN LOG AND LINEAR ---------------
function varargout = PopupSVD_Callback(h, eventdata, handles, varargin)
% Switch between log and linear scaling on the SVD plot
switch get(h,'Val')
case 1
   set(handles.AxisSVD,'Yscale','log');
case 0
   set(handles.AxisSVD,'Yscale','linear');
end




% ------------------ TEXT ENTER RANK NUMBER ------------------------------
function varargout = EditRank_Callback(h, eventdata, handles, varargin)
% Convert string to new rank, integrity check, update subspace plots
fig = handles.ParametricEstimation;

RANK = str2num(get(h,'String'));
if(isempty(RANK)),
   % did not understand user's string input
   RANK = round(get(handles.SliderRank,'Val')); % what is slider set to
   set(handles.EditRank,'string',sprintf('%.0f',RANK)); % reset edit box
else
   % good number, check integrity
   RANK = max(1,round(RANK)); % must be a minimum of one
   RANK = min(RANK,get(handles.SliderRank,'Max')); % must be a max of dimension
   
   set(handles.EditRank,'string',sprintf('%.0f',RANK)); % feedback to edit box
   
   set(handles.SliderRank,'Val',RANK); % update the slider
   
   plot_signalnoise(h,eventdata,handles,varargin); % update the plots
   
   hplot = getappdata(fig,'hplot'); % the vertical line
   set(hplot,'Xdata',[1 1]*(RANK+.5)); % shift plot line to lie between integers
end




% --------------------------- USE SLIDER FOR RANK -------------------
function varargout = SliderRank_Callback(h, eventdata, handles, varargin)
fig = handles.ParametricEstimation;

RANK = get(h,'Value');
RANK = round(RANK);
RANK = max(1,RANK); % minimum
RANK = min(RANK,get(h,'Max')); % maximum

set(h,'Value',RANK); % set to integer

set(handles.EditRank,'String',sprintf('%.0f',RANK));
plot_signalnoise(h,eventdata,handles,varargin);

hplot = getappdata(fig,'hplot'); % the vertical line
set(hplot,'Xdata',[1 1]*(RANK+.5)); % shift plot line to lie between two integers




% --------------------- TEXT ENTER OF STARTING TIME OF DATA ----------------
function varargout = EditMinTime_Callback(h, eventdata, handles, varargin)
% user can use rubber band box, or enter time manually 
fig = handles.ParametricEstimation;


str = get(h,'string'); % time that user entered
set(0,'CurrentFigure',fig); %this figure
set(fig,'CurrentAxes',handles.AxisSignalSubspace); % the data
V = axis; % limits of existing plot
newmin = sscanf(str,'%g',1); % user might have entered '4.5 ms'
set_axis(h, eventdata, handles, varargin,[newmin V(2:end)]);

% Update data Viewer window
dataViewerfig = findobj(0,'Tag','DATAPLOT','type','figure');
if isempty(dataViewerfig) 
    errordlg('Please leave DataViewer open when running RAP-MUSIC estimation')
    return
end

% Update time window values
viewHandles = guihandles(dataViewerfig);
set(viewHandles.time_min,'String', newmin)
dataplot_cb('set_time_min')



decompose(h,eventdata,handles,varargin);


% --------------------- TEXT ENTER OF ENDING TIME -------------------------
function varargout = EditMaxTime_Callback(h, eventdata, handles, varargin)
fig = handles.ParametricEstimation;

str = get(h,'string'); % time that user entered
set(0,'CurrentFigure',fig); %this figure
set(fig,'CurrentAxes',handles.AxisSignalSubspace); % the data
V = axis; % limits of existing plot
newmax = sscanf(str,'%g',1); % user might have entered '4.5 ms'
set_axis(h, eventdata, handles, varargin,[V(1) newmax V(3:end)]); %was [V(1) newmax V(3:end)] but bugged | SB

% Update data Viewer window
dataViewerfig = findobj(0,'Tag','DATAPLOT','type','figure');
if isempty(dataViewerfig) 
    errordlg('Please leave DataViewer open when running RAP-MUSIC estimation')
    return
end

% Update time window values
viewHandles = guihandles(dataViewerfig);
set(viewHandles.time_max,'String', newmax)
dataplot_cb('set_time_max')




decompose(h,eventdata,handles,varargin);



% ------------------- LISTBOX CALLBACK -----------------------------------
function varargout = Data_Stats_Callback(h, eventdata, handles, varargin)
% the listbox of information, no action




% ------------------ BUTTONDOWN ON DATA TO ZOOM --------------------------
function varargout = AxisStudy_ButtonDownFcn(h, eventdata, handles, varargin)

V = zoom_axis(h,eventdata, handles, varargin);
% Make the other two plots have the same axis
set_axis(h,eventdata, handles, varargin,V);




% ------------------- BUTTONDOWN ON SUBSPACE TO ZOOM---------------------
function varargout = AxisSignalSubspace_ButtonDownFcn(h, eventdata, handles, varargin)

V = zoom_axis(h,eventdata, handles, varargin);
% Make the other two plots have the same axis
set_axis(h,eventdata, handles, varargin,V);




% ------------------- BUTTONDOWN ON NOISE SPACE TO ZOOM---------------------
function varargout = AxisNoiseSubspace_ButtonDownFcn(h, eventdata, handles, varargin)

V = zoom_axis(h,eventdata, handles, varargin);
% Make the other two plots have the same axis
set_axis(h,eventdata, handles, varargin,V);





% ------------------ BUTTONDOWN ON SVD PLOT TO ZOOM --------------------------
function varargout = AxisSVD_ButtonDownFcn(h, eventdata, handles, varargin)

V = zoom_axis(h,eventdata, handles, varargin);




% ------------------- DECOMPOSE THE SELECTED DATA ---------------------------
function varargout = Pushbutton_decompose_Callback(h, eventdata, handles, varargin)

decompose(h,eventdata,handles,varargin);




% ------------------- CALL THE DATABASE MANAGER ----------------------
function varargout = DatabaseManager_Callback(h, eventdata, handles, varargin)

figman = data_manager; % call the manager
uiwait(figman); % wait for him to be done

% now reload the data
pushbutton_reload_data_Callback(handles.pushbutton_reload_data,[],handles);





% ------------------- RELOAD THE CURRENT DATA IN THE DATAMANAGER -------------
function varargout = pushbutton_reload_data_Callback(h, eventdata, handles, varargin)
fig = handles.ParametricEstimation;

reset_gui(fig,[],handles,[]); % setup all uicontrols
load_gui(fig,[],handles,[]); % load the current datamanager trial




% ------------------- SEND HELP TO THE MESSAGE WINDOW -----------------------
function varargout = pushbutton_help_Callback(h, eventdata, handles, varargin)

% multiple paragraphs:
msg_str1 = ['Left click, drag, and release in any axis to zoom. ',...
      'Double-click or right-click in any axis to zoom out to "tight." ',...
      'Other windows will adjust to same axis.'];

msg_str2 = ['Zoom top data window to desired region, or type in data range (in ms) ',...
      'in the edit windows of the top graph. Press Decompose to perform a ',...
      'Singular Value Decomposition (SVD) of the selected data. ',...
      'Right-click each spatio-temporal window to examine chosen data more ',...
      'closely. '];

msg_str2b = ['Move Slider Rank or type in desired rank to change ',...
      'signal vs. noise-only subspaces. The green line in the SVD window ',...
      'is a crude guess as to the noise floor and is used to guess the ',...
      'percentage of noise in the data. Statistics window updates the percentage of ',...
      'variance in the signal and noise subspaces. Look for a rank that is either ',...
      'at a distinct drop in the singular values, or approximates the levels of ',...
      'noise.'];

msg_str3 = ['Select estimation method to provide ',...
      'input for remaining necessary parameters.'];

bst_message_window('wrap',{'Help for Parametric Estimation GUI','',...
      msg_str1,'',msg_str2,'',msg_str2b,'',msg_str3})




% --------------------- SWITCH GRID ON AND OFF -------------------------
function varargout = button_grid_Callback(h, eventdata, handles, varargin)

ha = [handles.AxisSignalSubspace;...
      handles.AxisNoiseSubspace;handles.AxisSVD];
switch get(h,'Val')
case 0
   set(ha,'Xgrid','off','Ygrid','off');
case 1
   set(ha,'Xgrid','on','Ygrid','on');
end




% ------------------- CLOSE THE WINDOW -------------------------------
function varargout = Quit_Callback(h, eventdata, handles, varargin)
fig = handles.ParametricEstimation; % shorthand

global data
data.Measures.NoiseModelParam = start_gui_structure(h,eventdata,handles,varargin); % Get noise parameters and save them in Viewer's structure
data.Measures.NoiseModelParam.StudySubject = getappdata(fig,'StudySubject');

DATAPLOT = openfig('dataplot.fig','reuse');
if isempty(DATAPLOT), return, end

DPhandles = guihandles(DATAPLOT);
set(DPhandles.NoiseModelTag,'string','set')

close(fig)





% ---------------- SELECT EEG OR MEG DATA -------------------------------
function varargout = radiobutton_eeg_Callback(h, eventdata, handles, varargin)
% Which data set to display, or both
%  radiobutton_meg calls this routine as well

Vale = get(handles.radiobutton_eeg,'Val'); % the eeg button
Valm = get(handles.radiobutton_meg,'Val'); % the meg button

% handles to all the radio buttons in this group
hall = [handles.radiobutton_eeg; handles.radiobutton_meg];
ndx = find(hall ~= h); % which buttons were not called

RESET = 1; % default, we need to reset the gui, with an exception below

% we can't have both buttons off
if(~Valm & ~Vale), % if both radio buttons are off
   % User has just turned off button h. See if the other button is enabled
   % what is the enable status of the other button
   switch lower(get(hall(ndx(1)),'Enable')) 
   case 'on'
      % the other button is available
      set(hall(ndx(1)),'Val',1); % then turn back on the other button not pressed
   otherwise
      set(h,'Val',1); % other button not enabled, force this button to stay on
      % in this case, there is only one data set. No need to reset the GUI
      RESET = 0;
   end
end
% otherwise, the other set is enabled and selected, 
%  let the user automatically toggle this button on or off


if(RESET), % is a reset of the GUI necessary?
   % Once the user has toggled the desired data, let him play with these
   %  buttons until he gets the combination he wants, b
   % But require him to manually reload the data
   % First, what is the current state of these two buttons
   EState = get(hall,'enable'); % enabled state of these buttons
   VState = get(hall,'Val'); % and their current values
   
   % reset the GUI.
   reset_gui(h, eventdata, handles, varargin);
   
   % put the data buttons back to their original state
   for i = 1:length(EState),
      set(hall(i),'Enable',EState{i},'Val',VState{i});
   end
   
   % user will need to reload the data
end



% ------------------- SELECT MEG BUTTON ----------------------------
function varargout = radiobutton_meg_Callback(h, eventdata, handles, varargin)
% works in cooperation with the eeg button
radiobutton_eeg_Callback(h, eventdata, handles, varargin);





% --------------------- SELECT ESTIMATION TECHNIQUE ---------------------
function varargout = EstimationTechnique_Callback(h, eventdata, handles, varargin)
% OBSOLETE: No longer used October 2003

fig = handles.ParametricEstimation; % shorthand
% Activate additional GUIs for particular parameters
Val = get(handles.EstimationTechnique,'Val'); % what is the popup at?

switch Val
case 1 % Do Nothing "Estimate . . ." teaser
   
case 2 % RAP-MUSIC
   % get the GUI parameters
   GUI = start_gui_structure(h,eventdata,handles,varargin);
   StudySubject = getappdata(fig,'StudySubject');
   
   hf = rap_music_parameters; % setup
   rap_music_parameters('load_parameters',hf,StudySubject,GUI);
   
case 3 % Least-squares
   % get the GUI parameters
   GUI = start_gui_structure(h,eventdata,handles,varargin);
   StudySubject = getappdata(fig,'StudySubject');
   hf = least_squares_parameters_cb; % setup
   
   least_squares_parameters_cb(StudySubject,GUI,hf); %set up the popup

otherwise
   bst_message_window(sprintf('Unknown estimation case'));
end

% now set the popup back to position 1, "Estimate . . ." teaser
% set(handles.EstimationTechnique,'Val',1);



% ---------------- ZOOM CONTROL ------------------------------------
function varargout = togglebutton_zoom_Callback(h, eventdata, handles, varargin)
% if on, then rubberband and right click control zooming.
% if off, then rubberband selects regions only and right click is uicontextmenu

Val = get(h,'Val');
Colors = bst_color_scheme; % current scheme

switch Val
case 0
   % it's off
   set(h,'BackGroundColor',Colors.ToggleOff,'ForegroundColor',Colors.ButtonText);
case 1
   % it's on
   set(h,'BackGroundColor',Colors.ToggleOn,'ForegroundColor',[.5 .5 .5]);
end





% --------------------------------------------------------------------
function varargout = togglebutton_zoom_ButtonDownFcn(h, eventdata, handles, varargin)

str1 = ['Toggle zoom off, then left click and pull on spatio-temporal data to select ',...
      'regions of the data. Then ',...   
      'right click on spatio-temporal data to select noise projectors.'];

bst_message_window('wrap',str1)





% ---------------- DOMAIN SELECTION ------------------------------------
function varargout = popupmenu_domain_Callback(h, eventdata, handles, varargin)
% future version will allow primary window to display time, frequency, or spectrogram





% --------------------------------------------------------------------
function varargout = uicontextmenu_selection_action_Callback(h, eventdata, handles, varargin)

hc = get(h,'children'); 

% what is the status of the toggle button for zooming?
Val = get(handles.togglebutton_zoom,'Val');

switch Val
case 0
   % user is NOT zooming, so show the uimenus
   for i = 1:length(hc),
      set(hc(i),'visible','on');
   end
case 1
   % user IS ZOOMING, so DO NOT show the uimenus
   for i = 1:length(hc),
      set(hc(i),'visible','off');
   end
end





% --------------------------------------------------------------------
function varargout = uimenu_data_exclude_Callback(h, eventdata, handles, varargin)





% --------------------------------------------------------------------
function varargout = uimenu_clear_data_exclusion_Callback(h, eventdata, handles, varargin)





% --------------------------------------------------------------------
function varargout = uimenu_subspace_reject_Callback(h, eventdata, handles, varargin)
% if varargin is set to 'clear', do so, otherwise set projector based on region
%  user selected with rubberband

User = get_user_directory;

fig = handles.ParametricEstimation; % shorthand

if(~exist('varargin')),
   varargin{1} = [];
end

if(isempty(varargin))
   MODE = 'set';
else
   MODE = varargin{1};
end

switch MODE
case 'clear'
   Projector = [];
case 'set'   
   Data = getappdata(fig,'Data'); % the current data
   
   points = getappdata(fig,'rbbox_points'); % the region selected
   
   Left = points(1,1); % left most x-axis
   Right = points(2,1); % right most x-axis, don't care about y
   % units are in ms, convert Data.Time
   iLeft = min(find(Data.Time*1000 >= Left)); % left most index
   iRight = max(find(Data.Time*1000 <= Right));
   
   Region = Data.F(Data.Selected_Channel,iLeft:iRight);
   
   [U,S,V] = svd(Region,0);
   
   % now display the singular values in the SVD plot
   if(length(S) > 1),
      S = diag(S); % make a vector
   end
   
   set(0,'CurrentFigure',fig);
   set(fig,'CurrentAxes',handles.AxisSVD);
   cla
   hl = line([1:length(S)]',S);
   
   set(hl,'hittest','off'); % nothing happens when clicking on line
   
   set(hl,'marker','*');
   
   iLogLin = get(handles.PopupSVD,'Value'); % 1 is log, 0 is linear
   switch iLogLin % which plot
   case 0 % linear
      set(handles.AxisSVD,'yscale','linear');
   case 1 % log
      set(handles.AxisSVD,'yscale','log')
   otherwise
      % what otherwise?
      msgbox(sprintf('Error in plotting SVD','Error','modal'))
      return
   end
   
   axis tight
   V = axis;
   V(2) = min(V(2),20); % don't want too many for display purposes
   V(3) = max(V(4)/100,V(3))
   axis(V);

   prompt={'Enter the rank of the subspace (see graph)'};
   def={'1'};
   dlgTitle='Input for Subspace Projector';
   lineNo=1;
   answer=inputdlg(prompt,dlgTitle,lineNo,def);
   
   if(isempty(answer)),
      % cancelled out
      r = 0;
   else
      r = round(str2num(answer{1}));
      r = max(r,1); % quality control
      r = min(r,size(U,2)); % quality control
   end
   
   Projector = U(:,1:r);   
end

% need to save this data in the data file itself
filename = getappdata(fig,'DataFile'); % referential name

cd(User.STUDIES);
Data = load(filename);

Data.Projector = Projector;

save_fieldnames(Data,fullfile(User.STUDIES,filename)); % save back

% and load the gui again
reset_gui(fig,eventdata,handles,varargin);
load_gui(fig,eventdata,handles,varargin);





% --------------------------------------------------------------------
function varargout = uimenu_clear_projector_Callback(h, eventdata, handles, varargin)

uimenu_subspace_reject_Callback(handles.uimenu_subspace_reject, ...
   eventdata, handles, 'clear')



% --------------------------------------------------------------------
function varargout = togglebutton_projector_detect_Callback(h, eventdata, handles, varargin)
% only used as a flag



% --------------------------------------------------------------------
function varargout = uimenu_help_selection_action_Callback(h, eventdata, handles, varargin)

str0 = ['Selection Action Help'];
str1 = ['Exclude Data: The region selected is removed from the data matrix and not ',...
      'processed.'];
str2 = ['Exclude Subspace: The region selected is decomposed and the data are ',...
      'projected AWAY from the subspace selected.'];
str3 = ['Clear Data Exclusion, Clear Projector: Removes the above exclusions and returns ',...
      'the data to its original state.'];

bst_message_window('wrap',{'',str0,'',str1,'',str2,'',str3})



