% janis_gui_main:
%   Graphical User Interface for
% JANIS - Just another Neuroimaging Software v2.1
function varargout = janis_gui_main(varargin)
% JANIS_GUI_MAIN M-file for janis_gui_main.fig
%      JANIS_GUI_MAIN, by itself, creates a new JANIS_GUI_MAIN or raises the existing
%      singleton*.
%
%      H = JANIS_GUI_MAIN returns the handle to a new JANIS_GUI_MAIN or the handle to
%      the existing singleton*.
%
%      JANIS_GUI_MAIN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in JANIS_GUI_MAIN.M with the given input arguments.
%
%      JANIS_GUI_MAIN('Property','Value',...) creates a new JANIS_GUI_MAIN or raises
%      the existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before janis_gui_main_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to janis_gui_main_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's tools_bar menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help janis_gui_main

% Last Modified by GUIDE v2.5 26-Mar-2013 16:14:33

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @janis_gui_main_OpeningFcn, ...
                   'gui_OutputFcn',  @janis_gui_main_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before janis_gui_main is made visible.
function janis_gui_main_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to janis_gui_main (see VARARGIN)
% Choose default command line output for janis_gui_main
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
initialize_gui(hObject, handles, false);
% set Title
set(handles.figure1,'Name',janis('getVersionString'));
% set default stuff
checkInstallation(hObject,eventdata,handles);
% set classifier
popupmenu_classifiers_Callback(hObject, eventdata, handles)
% set empty acc-window
ud = get(handles.figure1,'UserData');
set(handles.table_confusion,'Data',[NaN, NaN; NaN, NaN]);
set(handles.table_confusion,'ColumnName',{get(handles.edit_classname1,'String') ,get(handles.edit_classname2,'String') });
set(handles.table_confusion,'RowName',{get(handles.edit_classname1,'String') ,get(handles.edit_classname2,'String') });
options_tab_SelectionChangeFcn(hObject, eventdata, handles);
set(handles.listbox_fs,'String',{ud.default.preprocessors{:};ud.default.intravalidationPreprocessors{:}});

% on create set default values and params
function figure1_CreateFcn(hObject, eventdata, handles)

% set active and inactive, also default.



% Checks Installation:
%  * SPM is there an right version
%  * Matlab toolboxes  are there
%  * libsvm
%  * Gaussian Process
function checkInstallation(hObject,eventdata,handles)
msg = {};
ud = get(handles.figure1,'UserData');
[janis_path, ign] = fileparts(which('janis'));
ooPath = [janis_path filesep 'oo'];
% check feature options
% Fetch all classes which implement (pre)processors
[janis_path ign] = fileparts(which('janis'));
ooPath = [janis_path filesep 'oo'];
[preClass, preNames] = janisSubclasses(ooPath,'janis_preprocessor');
[proClass, proNames] = janisSubclasses(ooPath,'janis_processor');
[msg, preNames, preClass] = checkClasses(msg,preNames,preClass);
[msg, proNames, proClass] = checkClasses(msg,proNames,proClass);
% preprocessors map<'String','Preprocessor Object'>
ud.preMap = containers.Map(preNames,cellfun(@eval,preClass,'UniformOutput',false));
% processors map<'String','Processor Object'>
ud.proMap = containers.Map(proNames,cellfun(@eval,proClass,'UniformOutput',false));
% only set, if programm was just started
if ~strcmp(get(hObject,'tag'),'installCheck')
    ud.default = struct;
    ud.active = struct;
    % mask NaNs default, remove from available list
    ud.default.preprocessors = {'Mask NaNs'};
    preNames(~cellfun(@isempty,strfind(preNames,'Mask NaNs'))) = [];
    ud.default.available_pps = preNames;
    ud.default.intravalidationPreprocessors = {};
    ud.default.available_ips = proNames;
    ud.active.intravalidationPreprocessors = ud.default.intravalidationPreprocessors;
    ud.active.available_ips = ud.default.available_ips;
    ud.active.preprocessors = ud.default.preprocessors;
    ud.active.available_pps = ud.default.available_pps;
end
% check classifiers
[fNames, titles] = janisSubclasses(ooPath,'janis_classifier');
if exist('spm','file')
    if ~strcmp(spm('Ver'),'SPM8')
    msg{length(msg)+1} = ['SPM version found: ' spm('Ver') ' - JANIS has not been tested with this version. SPM8 is at least recommended!'];
    end
else
    msg{length(msg)+1} = '***Critical***: No SPM version found. JANIS needs SPM-routines (e.g. for loading files) and will not properly work without SPM!';
end
% for each classifier algorithm
[msg, titles, fNames] = checkClasses(msg,titles,fNames);
% classifier map<'String','Classifier'>
ud.classifierMap = containers.Map(titles,fNames);
set(handles.popupmenu_classifiers,'String',titles);
if ~isempty(msg)
    mStr = sprintf('Shortcommings of your setup: \n');
    for k=1:length(msg)
       mStr =  sprintf('%s\n%s\n',mStr,msg{k});
    end
    errordlg(mStr,'Installation Check')
elseif strcmp(get(hObject,'tag'),'installCheck')
    msgbox('Everything looks fine. All required and recommended packages are installed.','Check','help');
end
% set default
set(handles.figure1,'UserData',ud);

function [msg,availableTitles,availablefNames] =  checkClasses(msg,titles,fNames)
availableTitles = {};
availablefNames = {};
for k=1:numel(titles)
    [state, message] = eval([fNames{k} '.checkSetup']);
    if state
        % should classifier be listed?
        if eval([fNames{k} '.shouldBeVisible'])
            availableTitles{length(availableTitles)+1} = titles{k};
            availablefNames{length(availablefNames)+1} = fNames{k};
        end
    else
        msg{length(msg)+1} = message;
    end
end

% --- Outputs from this function are returned to the command line.
function varargout = janis_gui_main_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

initHelpBox(handles);
ud = get(handles.figure1,'UserData');
ud.default.reductionMethod = janis_fs_append;
ud.ensemble = {};
ud.classes = {{},{}};
ud.classNames = {'Class 1';'Class 2'};
set(handles.figure1,'UserData',ud);
set(hObject,'UserData', ud);


set(handles.figure1,'UserData',ud);
start(ud.helpTimer);
varargout{1} = handles.output;

function h = retrieveHandles
h = guihandles;


function initHelpBox(handles)
% Get default command line output from handles structure
ud = get(handles.figure1,'UserData');
statusBox_help = uicontrol(handles.figure1,'style','edit', 'max',5);
b = [0.0481    0.0148    0.8198    0.0913];
pause(0.01);
drawnow;
jScrollPane = findjobj(statusBox_help);
jViewPort = jScrollPane.getViewport;
jhelpBox = jViewPort.getComponent(0);
jhelpBox.setEditorKit(javax.swing.text.html.HTMLEditorKit);
htmlStr = ['<font color="green">Help Area</font>'];
jhelpBox.setText(htmlStr);
set(statusBox_help,'Units','normalized');
set(statusBox_help,'Position',b);
jhelpBox.setEditable(false);
hjhelpBox = handle(jhelpBox,'CallbackProperties');
set(hjhelpBox,'HyperlinkUpdateCallback',@linkCallbackFcn);
set(statusBox_help,'Tag','statusBox_help');
handles.statusBox_help = statusBox_help;
guidata(gcf,handles);
% Create and start timer to update help area
ud.helpTimer = timer('TimerFcn', {@janis_util_updateHelp,jhelpBox},'BusyMode','Queue', 'ExecutionMode','FixedRate','Period',0.33);
set(handles.figure1,'UserData',ud);


% Starts the validation and displays results then
function pushbutton_validation_Callback(hObject, eventdata, handles)
if strcmp(get(handles.pushbutton_apply,'Enable'),'on') && strcmp(get(hObject,'tag'),'pushbutton_validation')
    reply = questdlg('Data setup may have been changed. Do you want to reapply data setup and reload images?','Load images','Yes','No','Yes');
    if strcmp(reply,'Yes')
        pushbutton_apply_Callback(hObject, eventdata, handles)
    end
end
set(handles.sig_panel,'Visible','off');
set(handles.edit_pval,'String','N/A');
set(handles.edit_permcount,'String','N/A');
ud = get(handles.figure1,'UserData');
validator = initClassifier(handles,ud.class_collection);
if isempty(validator); return; end
% handle progressbar & run
wb = janis_gui_RespondToCycle(validator);
try
    validator.runValidation;
catch exp
    errordlg({'Error during classification:';exp.message},'Classification Exception')
    rethrow(exp);
end
delete(wb);
set(handles.panel_results,'Visible','On');
ud.classPerformance = validator.classPerformance;
set(handles.figure1,'UserData',ud);
handleGraph(validator.classPerformance,handles);
handleConfusion(ud.class_collection,validator.classPerformance,handles);
ud.validator = validator;
ud.classifier = ud.validator.classifier;
set(handles.save_classifier,'Enable','on');
set(handles.permutationTest,'Enable','on');
set(handles.view_featureSelection,'Enable','on');
set(handles.figure1,'UserData',ud);
set(handles.extract_map,'Enable','on');
set(handles.pushbutton_fromComputed,'Enable','on');

% inits the classifier
%  * validation method
%  * classifier
%  * parser
function validator = initClassifier(handles, classCollection)
ud = get(handles.figure1,'UserData');
parser = janis_simpleParser(classCollection);
parser = handlePreprocessors(ud.active, parser,handles);
try
    parser.init;
catch excep
    errordlg(excep.message);
    rethrow(excep);
    return
end
classifier = ud.classifier;
validators = get(handles.popupmenu_validator,'String');
active_validator = validators(get(handles.popupmenu_validator,'Value'));
switch active_validator{:}
    case 'Leave One Out Crossvalidation'
        validator = janis_validatorLeaveOneOut(classCollection, classifier, parser);
    case 'Leave One Out per Group (Matched)'
        if ~classCollection.isBalanced
            msgbox({'Groups are not balanced!','Matched Crossvalidation is only possible, if all groups have the same amount of subjects.','Use simple LOOCV, or fix the amount of subjects in the groups.'},'Unsupported operation','warn');
            validator = [];
            return
        end
        validator = janis_validatorMatched(classCollection, classifier, parser);
    case  'Test Groups'
        testIdx = cellfun(@(x) get(x,'Value'),ud.panelVal(end,:));
        classCollection = classCollection.setTestGroups(testIdx);
        if sum(testIdx)>=length(classCollection.classes)
           msgbox({'You did not check any groups to use in training?','No problem I will just make a wild guess...','Uhm *think*','Okay, I would say every subject is group 42'},'Okay buddy...','warn');
           validator = [];
           return
        end
        if sum(testIdx)==0
             msgbox({'You did not check any groups to test?','Then the answer is easy...','','I predict nothing.'},'Okay buddy...','warn');
             validator = [];
           return
        end
        validator = janis_validatorTestGroup(classCollection, classifier, parser);
    otherwise
        error('Unkown validator???');
end

% set results in Confusion Matrix
function handleConfusion(jcc,cp,handles)
set(handles.table_confusion,'Data',cp.CountingMatrix(1:end-1,:));
p = vertcat(jcc.classes{:});
set(handles.table_confusion,'ColumnName',{p.name});
set(handles.table_confusion,'RowName',{p.name});

% handle the Accuray-Graph
function handleGraph(cp, handles)
barh(handles.accGraphic,100*[cp.Specificity cp.Sensitivity cp.CorrectRate]);
text('Position',[0.2 1],'string',[num2str(cp.Specificity*100) '%'],'BackgroundColor',[.7 .9 .7]);
text('Position',[0.2 2],'string',[num2str(cp.Sensitivity*100) '%'],'BackgroundColor',[.7 .9 .7]);
text('Position',[0.2 3],'string',[num2str(cp.CorrectRate*100) '%'],'BackgroundColor',[.7 .9 .7]);
set(handles.accGraphic,'xlim',[0 100]);
for i=0:10
    xtic{i+1}=[num2str(i*10) '%'];
end
set(handles.accGraphic,'YTickLabel',{'Specificity';'Sensitivity';'Accuracy'});
set(handles.accGraphic,'XTickLabel',xtic);
set(handles.accGraphic,'Tag','accGraphic');

% handles Feature Selection from selected methods in the GUI
function parser = handlePreprocessors(active,parser,handles)
ud = get(handles.figure1,'UserData');
pro = active.preprocessors;
intra = active.intravalidationPreprocessors;
% methods, that apply before validation
if ~isempty(pro)
    for k=1:numel(pro)
          preproc = copy(ud.preMap(pro{k}));
          preproc.setPreviousOperations(parser.preprocessors);
          parser.addPreprocessors(preproc);
    end
end
% methods, that apply during validation
if ~isempty(intra)
    for k=1:numel(intra)
          preproc = copy(ud.proMap(intra{k}));
          parser.addIntraValidationProcessors(preproc);
    end
end

% --------------------------------------------------------------------
function initialize_gui(fig_handle, handles, isreset)
% If the metricdata field is present and the pushbutton_validation flag is false, it means
% we are we are just re-initializing a GUI by calling it from the cmd line
% while it is up. So, bail out as we dont want to pushbutton_validation the data.
if isfield(handles, 'metricdata') && ~isreset
    return;
end
% Update handles structure
guidata(handles.figure1, handles);


% asks for modus, if selection according to directories or image by image
% then setup everything.
function new_class_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
Modus = questdlg('Do You want to specify subjects by directories and/or SPM.mat-Files or just specify image by image?', 'Modus Question','Use Directories','All images in one folder', 'Use Directories');
worked = false;
switch Modus
    case 'Use Directories'
        baseDir = uigetdir(pwd, 'Select Basedirectory of study');
        if isstr(baseDir)
            varargout = pathchooser({baseDir},'dirs');
            if isnumeric(varargout) && varargout == 0; return; end
            set(handles.popupmenu_imgType,'Visible','on');
            set(handles.edit_spm_file,'Visible','on');
            set(handles.edit_spm_file,'String','');
            set(handles.pushbutton_specify_spm,'Visible','on');
            set(handles.pushbutton_apply,'Enable','off');
            worked = true;
        else errordlg('Could not determine base directory!');
        end
    case 'All images in one folder'
        baseDir = uigetdir(pwd, 'Select image directory');
        if isstr(baseDir)
            varargout = pathchooser({baseDir},'files');
            if isnumeric(varargout) && varargout == 0; return; end
            ud.spm = false;
            set(handles.popupmenu_imgType,'Visible','off');
            set(handles.edit_spm_file,'Visible','off');
            set(handles.pushbutton_specify_spm,'Visible','off');
            set(handles.pushbutton_apply,'Enable','on');
            worked = true;
        else errordlg('Could not determine base directory!');
        end
end
if worked
        ud.baseDir = varargout{3};
        close(varargout{5}.pathchooser);
        classes = varargout{1};
        classNames = varargout{2};
        set(handles.listbox_members_c1,'String',classes{1});
        set(handles.listbox_members_c2,'String',classes{2});
        ud.classes = classes;
        ud.classNames = classNames;
        ud.dirModus = varargout{4};
        set(handles.edit_classname1,'String',classNames);
        set(handles.edit_classname2,'String',classNames);
        set(handles.pushbutton_editClassMembers,'Enable','on');
        set(handles.edit_classes_members,'Enable','on');
        set(handles.edit_spm_file,'String','');
        set(handles.listbox_members_c1,'Enable','on');
        set(handles.listbox_members_c2,'Enable','on');
        set(handles.pushbutton_editClassMembers,'Enable','on');
        set(handles.edit_classname1,'Value',1);
        set(handles.edit_classname2,'Value',2);
        set(handles.figure1,'UserData',ud);
end
resetView(handles);
popupmenu_classifiers_Callback(hObject, eventdata, handles);

% Resets the view, so that program can start over -
%  should then be very similar to the beginning.
function resetView(handles)
set(handles.conditionWindow,'Visible','off');
set(handles.pushbutton_validation,'Enable','off');
set(handles.panel_results,'Visible','off');
set(handles.popupmenu_classifiers,'Value',1);
set(handles.popupmenu_validator,'Value',1);
set(handles.toggle_ensembles,'Enable','off');
set(handles.popupmenu_imgType,'Value',1);
set(handles.panel_regExp,'Visible','off');
set(handles.view_featureSelection,'Enable','off');

% clean up evrything, that might have been changed or edited.
function reset_Callback(hObject, eventdata, handles)
resetView(handles);
set(handles.pushbutton_editClassMembers,'Enable','on');
set(handles.pushbutton_editClassMembers,'Enable','off');
set(handles.popupmenu_imgType,'Visible','off');
set(handles.edit_spm_file,'Visible','off');
set(handles.pushbutton_specify_spm,'Visible','off');
set(handles.listbox_members_c1,'String','');
set(handles.listbox_members_c2,'String','');
set(handles.listbox_members_c1,'Enable','off');
set(handles.listbox_members_c2,'Enable','off');
set(handles.edit_classname1,'Value',1);
set(handles.edit_classname2,'Value',1);
set(handles.edit_classname1,'String','class#1');
set(handles.edit_classname2,'String','class#2');
eventdata.OldValue = handles.toggle_members;
options_tab_SelectionChangeFcn(hObject,eventdata, handles)
ud.spm = false;


% Function to load a saved classifier.
function load_Callback(hObject, eventdata, handles)
[figName, pathname] = uigetfile('*.sav','Pick a saved file');
if isnumeric(figName); return; end
splitted = strsplit('.',figName);
datName =  [splitted{1} '.dat'];
if ~exist([pathname figName], 'file')
    errordlg('Could not load: Saved setup is missing','Load Problem');
    return;
end
if  ~exist([pathname datName], 'file')
    errordlg('Could not load: data file is missing','Load Problem');
    return;
end
try
    oldFig = gcbf;
    wb = busyBar(get(oldFig,'Position'));
    set(oldFig,'Visible','off');
    loaded = load([pathname datName],'-mat');
    s = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
    t = warning('off','MATLAB:hg:uicontrol:ParameterValuesMustBeValid');
    newFig = hgload([pathname figName]);
    set(newFig,'Visible','off');
    warning(s); warning(t);
    pause(0.05);
    drawnow;
    set(newFig,'UserData',loaded.ud);
    h2 = guihandles(newFig);
    set(newFig,'Visible','on');
    initHelpBox(h2);
    ud2 = get(newFig,'UserData');
    pause(0.05);
    drawnow;
    start(ud2.helpTimer);
    ud = get(handles.figure1,'UserData');
    stop(ud.helpTimer);
    delete(ud.helpTimer);
    close(oldFig);
    pause(0.05);
    close(wb);
    onLoad_Callback(h2.figure1,[],h2);
catch exp
    errordlg('Could not load save-files.','Load Problem');
    set(oldFig,'Visible','on');
    close(wb);
    rethrow(exp);
end

% perform on load various checks
function onLoad_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
if ~ud.class_collection.isValid
    pos = get(handles.figure1,'Position');
    ButtonName = questdlg('Setup loaded. Do you want to reload image data?','Load images','Yes','No','Yes');
    switch ButtonName
        case 'Yes'
            try
                wb = busyBar(get(handles.figure1,'Position'));
                ud.class_collection.init;
                close(wb);
            catch exp
                close(wb);
                rethrow(exp);
            end
        otherwise
            % disable stuff...
            set(handles.pushbutton_validation,'Enable','off');
            set(handles.pushbutton_apply,'Enable','on');
    end
end


% Function to save a classifier as file.
%  Note: This file might get very big, because it saves (need to save) the
%  patterns, too.
function save_classifier_Callback(hObject, eventdata, handles)
currentFig = gcf;
ud = get(handles.figure1,'UserData');

saveMod = questdlg({'Save - if only the Current setup is saved',...
                        'data of images have to reloaded - therefore it is required',...
                        'that image data is still available and in the same place.'...
                        'It is also possible to save the complete entire data. Howerver,',...
                        'this might cost a lot space on hard disk.',...
                        'Save...'}, ...
                         'Save Options', ...
                         'Current Setup', 'Everything','Current Setup');
[figName, pathname] = uiputfile('*.sav', 'Save as');
if ~isnumeric(figName)
    splitted = strsplit('.',figName);
    datName = [splitted{1} '.dat'];
    if exist([pathname figName], 'file') || exist([pathname datName], 'file')
        overWrite =  questdlg('File exists - overwrite?', ...
                         'Overwrite?', ...
                         'Yes', 'Cancel', 'Yes');
                     if ~strcmp('Yes',overWrite);
                         return
                     end

    end
    wb = busyBar(get(handles.figure1,'Position'));
    try
        stop(ud.helpTimer);
        delete(ud.helpTimer);
        ud = rmfield(ud,'helpTimer');
        delete(handles.statusBox_help);
    end
    set(handles.figure1,'UserData',[]);
    s = warning('off','MATLAB:Java:ConvertFromOpaque');
    if strcmp(saveMod,'Current Setup')
        if isfield(ud,'validator')
            validator = ud.validator;
            ud = rmfield(ud,'validator');
        end
        if isfield(ud,'class_collection')
           origCollection = ud.class_collection;
           ud = rmfield(ud,'class_collection');
           ud.class_collection = origCollection.copy;
           ud.class_collection.clearData;
        end
    end
    save([pathname datName],'ud');
    warning (s);
    hgsave(currentFig,[pathname figName]);
    if exist('validator','var')
        ud.validator = validator;
    end
    if exist('origCollection','var')
        ud.class_collection = origCollection;
    end
    set(handles.figure1,'UserData',ud);
    initHelpBox(handles);
    ud = get(handles.figure1,'UserData');
    start(ud.helpTimer);
    close(wb);
if exist([pathname figName], 'file') && exist([pathname datName], 'file')
    msgbox('Data has been saved.','Saved');
else
    errordlg('Data was not stored!','Error');
end
end

function p = busyBar(varargin)
p = figure(...
    'BusyAction', 'queue', ...
    'Resize','off', ...
    'MenuBar', 'none', ...
    'Interruptible', 'off', ...
    'DockControls', 'off', ...
    'numbertitle','off',...
    'name','Please wait...',...
    'Visible','off');
if nargin==1
    figPos = varargin{1};
    pos = [figPos(1)+20 figPos(2)+figPos(3)-20];
else
    pos = get(p,'Position');
end
set(p,'Position',[pos(1:2), 260,50]);
jProgressBar = javacomponent('javax.swing.JProgressBar',[10,10,240,30], p);
jProgressBar.setIndeterminate(1)
set(p,'Visible','on');


% closes the programm after prompt
function quit_Callback(hObject, eventdata, handles)
bn = questdlg('Uhm, are you really sure, exit now?!?','Option', 'Well, I want to remain a bit','Nah, I''m going to drink beer, now. Bye','Well, I want to remain a bit');
switch bn
    case  'Nah, I''m going to drink beer, now. Bye'
    try
        stop(ud.helpTimer);
        delete(ud.helpTimer);
        delete(handles.statusBox_help);
    end
        close(handles.figure1);
end



% Manual for command line
function help_commandLine_Callback(hObject, eventdata, handles)
disp('Not implemented yet');

% About dialog with license
function about_Callback(hObject, eventdata, handles)
% hObject    handle to about (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%Message = {'Janis - Just Another Neuro-Imaging Software' ; 'Version 2.1 (2012)'; ..
%''; 'by Dominik Grotegerd'; 'Cognitive and Affective Neuroimaging Group - UK Muenster'; 'Check out http://uni-muenster.de/neuroimage for more information.'; ''; 'This software is published under GNU General Public License Version 3 (http://www.gnu.org/licenses/gpl.html). Any other usage is not permitted without an explicit authorization by the author.'};
lic = janis('getLicenseString');
Message = [{'Janis - Just Another Neuro-Imaging Software'; ...
    janis('getVersionString'); ''; ...
    ['by ' janis('getAuthor')]; ...
    janis('group'); ...
    ['Check out ' janis('www') ' for more information.']; '';''; ...
    '============== Copyright Notice =============='}; ...
    lic{:}];
h = msgbox(Message,'About Janis','Help');


% if wfu_pickatlas is in matlab path, enable the options in following menu.
% else let it unchanged.
function tools_bar_Callback(hObject, eventdata, handles)
if (exist('wfu_pickatlas') == 2);
    set(handles.wfu_new_mask,'Enable','on');
end

% extract discriminative map from specified test-set
function extract_map_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
if strcmp(class(ud.validator.classifier),'janis_matlabSVM') ||  strcmp(class(ud.validator.classifier),'janis_libSVM')
    performances = ud.validator.GetPerformanceList;
    for j=1:size(performances,1)
        impStr{j} = sprintf('Leave out #%d (%3.1f %%)', j, performances(j)*100);
    end
    [s,ign] = listdlg('PromptString','Select a validation classifier',...
                    'SelectionMode','single',...
                    'ListString',impStr);
    toExtractFrom = ud.validator.getClassifierForSubject(s);
    dmap = extractDiscriminativeMap (toExtractFrom, ud.validator.patternParser);
    example = spm_vol(spm_vol(ud.class_collection.classes{1}.members{1}.imgFiles{1}));
    [file,path] = uiputfile('sv_map.img','Save preprocessed images');
    if ischar(file) && ischar(path)
        toSave.dim = example.dim;
        toSave.dt = example.dt;
        toSave.mat = example.mat;
        if (size(dmap,4)) > 1
            for j=1:size(dmap,4)
                toSave.fname = [path file(1:end-4) sprintf('%04d', j) file(end-3:end)];
                spm_write_vol(toSave,dmap(:,:,:,j));
            end
        else
            toSave.fname = [path file];
            spm_write_vol(toSave,dmap);
        end
    end
else
    msgbox('This classifier is not supported yet for extraction of Discriminative Maps. Sorry. Try the Bioinfo-SVM.','Not Supported','help');
end

% handles results of pulldown menu
function popupmenu_imgType_Callback(hObject, eventdata, handles)
if ~isempty(get(handles.edit_spm_file,'String')) && (get(handles.popupmenu_imgType,'Value') < 3);
    update_spm(handles);
    set(handles.pushbutton_apply,'Enable','on');
    ud = get(handles.figure1,'UserData');
    ud.spm = true;
    set(handles.figure1,'UserData',ud);
elseif get(handles.popupmenu_imgType,'Value') == 4
    update_spm(handles);
    set(handles.pushbutton_apply,'Enable','on');
    ud = get(handles.figure1,'UserData');
    ud.spm = true;
    set(handles.figure1,'UserData',ud);
else
    set(handles.conditionWindow,'Visible','off');
end
    if get(handles.popupmenu_imgType,'Value') > 2
        set(handles.pushbutton_specify_spm,'Visible','off');
        set(handles.edit_spm_file,'Visible','off');
        if get(handles.popupmenu_imgType,'Value') == 3
            set(handles.panel_regExp,'Visible','on');
        end
    else
        set(handles.pushbutton_specify_spm,'Visible','on');
        set(handles.edit_spm_file,'Visible','on');
        set(handles.panel_regExp,'Visible','off');
    end

% function to select and specify SPM.mat
function pushbutton_specify_spm_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
bd = ud.baseDir;
c1 = get(handles.listbox_members_c1,'String');
sub1 = [bd filesep c1{1,1} filesep ];
[filename, pathname, filterindex] = uigetfile({'*.mat','SPM.mat'}, 'Select an example SPM.mat',[sub1]);
set(handles.edit_spm_file,'String',[pathname filename]);
update_spm(handles);
ud.spm = true;
tmp = [pathname filename];
ud.spm_subpath = tmp(size(sub1,2)+1:end);
set(handles.figure1,'UserData',ud);
set(handles.pushbutton_apply,'Enable','on');

% function to update the displayed information about SPM, when selected
% image type changes.
function update_spm(handles)
spm_file = get(handles.edit_spm_file,'String');
load(spm_file);
switch get(handles.popupmenu_imgType,'Value')
    % case beta
    case 1
        beta = {SPM.Vbeta.descrip}';
        set(handles.listbox_trials,'String',beta);
        set(handles.conditionWindow,'Visible','on');
        set(handles.pushbutton_specify_spm,'Visible','on');
        set(handles.edit_spm_file,'Visible','on');
    % case con
    case 2
        con =  {SPM.xCon};
        con = horzcat(con{:}.Vcon);
        con = vertcat({con.descrip})';
        set(handles.listbox_trials,'String',con);
        set(handles.conditionWindow,'Visible','on');
        set(handles.pushbutton_specify_spm,'Visible','on');
        set(handles.edit_spm_file,'Visible','on');
    % otherwise no spm stuff, dont show this
    case 4
        timeseries = horzcat(SPM.Sess.U.name)';
        set(handles.listbox_trials,'String',timeseries);
        set(handles.conditionWindow,'Visible','on');
        set(handles.pushbutton_specify_spm,'Visible','on');
        set(handles.edit_spm_file,'Visible','on');
    otherwise
        set(handles.conditionWindow,'Visible','off');
        set(handles.pushbutton_specify_spm,'Visible','off');
        set(handles.edit_spm_file,'Visible','off');
        ud = get(handles.figure1,'UserData');
        ud.spm = false;
        set(handles.figure1,'UserData',ud);
end

% If anything changes here, patterns have to be loaded again, maybe.
% Therefore: Enable the apply-button
function listbox_trials_Callback(hObject, eventdata, handles)
set(handles.pushbutton_apply,'Enable','on');

% --- Executes on button press in pushbutton_editClassMembers.
function pushbutton_editClassMembers_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
baseDir = ud.baseDir;
classes = ud.classes;
classNames = ud.classNames;
modus = ud.dirModus;
varargout = pathchooser({baseDir}, modus, classes, classNames);
try
    close(varargout{5}.pathchooser);
    ud.classes = varargout{1};
    ud.classNames = varargout{2};
    set(handles.listbox_members_c1,'String',ud.classes{1});
    set(handles.listbox_members_c2,'String',ud.classes{2});
    ud.baseDir = varargout{3};
    ud.dirModus = varargout{4};
    set(handles.edit_classname1,'String',ud.classNames);
    set(handles.edit_classname2,'String',ud.classNames);
    set(handles.edit_classname1,'Value',1);
    set(handles.edit_classname2,'Value',2);
    set(handles.pushbutton_editClassMembers,'Enable','on');
    set(handles.pushbutton_apply,'Enable','on');
    set(handles.figure1,'UserData',ud);
end

% --- Executes on selection change in popupmenu_classifiers.
% generates new classifier from specified...
function popupmenu_classifiers_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
classifiers = get(handles.popupmenu_classifiers,'String');
active_classifier = classifiers(get(handles.popupmenu_classifiers,'Value'));
ud.classifier = eval(ud.classifierMap(active_classifier{:}));
set(handles.figure1,'UserData',ud);



% The extensive Search
function extensiveSearch_Callback(hObject, eventdata, handles)
% hObject    handle to extensiveSearch (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
varargout = janis_metaSearch_gui;
nodes = varargout{1}.nodes;
logPath = varargout{2};
close(varargout{3}.figure1);
firstNode = nodes{1};
for m=1:size(nodes,2)
   nodes{m}.setFigureParent(handles);
   firstNode.addNode(nodes{m});
end
firstNode.lastNode.init;
firstNode.compute;
firstNode.lastNode.exitNode;

% Get files according to a regular expression
function pushbutton_regExp_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
bd = ud.baseDir;
c1 = get(handles.listbox_members_c1,'String');
sub1 = [bd filesep c1{1,1} filesep ];
out = janis_gui_regExp(sub1);
close(out{3}.figure1);
regExp = out{2};
absPath = out{1};
subPath = absPath(size(sub1,2)+1:end);
example = spm_select('List',[sub1 subPath],regExp);
set(handles.listbox_regExp,'String',example);
ud.regExpSubDir = subPath;
ud.regExp = regExp;
ud.spm = false;
set(handles.figure1,'UserData',ud);
set(handles.pushbutton_apply,'Enable','on');

% Apply Button Press:
%   Loads all the images and defines classes and members.
function pushbutton_apply_Callback(hObject, eventdata, handles)
tic;
subcounter = 0;
h = waitbar(0, '1', 'Name', 'Creating Classes & Members');
ccollection = janis_classCollection;
ud = get(handles.figure1,'UserData');
imgType = get(handles.popupmenu_imgType,'Value');
for ccount=1:length(ud.classes)
   jc{ccount} = janis_class(ud.classNames{ccount});
   c_ids{ccount} = ud.classes{ccount};
end
if isfield(ud,'regression') && ud.regression
    regressands =get(handles.listbox_members_c2,'String');
end
% if we use a SPM.mat and imgType is CON or Beta
if ((isfield(ud,'spm') && ud.spm && imgType < 3) || (isfield(ud,'spm') && ud.spm && imgType == 4))
   baseDir = ud.baseDir;
   spm_path = ud.spm_subpath;
   for k=1:size(c_ids,2)
       c_path{k} = cell(size(c_ids{k},1));
   end
   subjectCount = size(vertcat(c_ids{:}),1);
   trial_cond = get(handles.listbox_trials,'String');
   trial_Idx = get(handles.listbox_trials,'Value');
   trial =  {trial_cond{trial_Idx}};
   for c=1:size(c_ids,2)
     for sc=1:size(c_ids{c},1)
         tmp_path = c_path{c};
           tmp_path{sc} =  [baseDir filesep cell2mat(c_ids{c}(sc)) filesep spm_path];
           if imgType == 1
               try
                    newPattern = janis_patternBeta(tmp_path{sc},trial');
                    newPattern.setFeatureSelection(ud.default.reductionMethod);
               catch excep
                   errordlg(excep.message);
                   close(h);
                   rethrow(excep);
               end
           elseif imgType == 2
               try
                        newPattern = janis_patternCon(tmp_path{sc},trial');
                        newPattern.setFeatureSelection(ud.default.reductionMethod);
                  catch excep
                   errordlg(excep.message);
                   close(h);
                   rethrow(excep);
               end
           elseif imgType == 4
                newPattern = janis_patternTimeSeries(tmp_path{sc},trial');
           end
           newPattern.description = c_ids{c}(sc);
           if isfield(ud,'regression') && ud.regression
                newPattern.setRegressand(str2double(regressands(sc,:)));
           end
           newPattern.generatePattern;
           jc{c} = jc{c}.addMember(newPattern);
           subcounter = subcounter + 1;
           updateWaitbar(h,subcounter,subjectCount);
      end

   end
       close(h);
       spmFile = newPattern.SPMfile;
       endIdx = findstr('/',spmFile);
       pattPath = spmFile(1:endIdx(end));
       imgs = newPattern.imgFiles;

% if we use not SPM.mat
elseif strcmp(ud.dirModus,'files')
       imgs = ud.classes;
       subjectCount = size(vertcat(imgs{:}),1);
       for c=1:size(imgs,2)
           for si=1:size(imgs{c},1)
              imgsTmp =  strcat([ud.baseDir filesep],ud.classes{c});
              newPattern = janis_patternSimple(imgsTmp(si,1));
              newPattern.description = imgsTmp(si,1);
              newPattern.setFeatureSelection(ud.default.reductionMethod);
              newPattern.generatePattern;
              jc{c} = jc{c}.addMember(newPattern);
              subcounter = subcounter + 1;
              updateWaitbar(h,subcounter,subjectCount);
           end
       end
       close(h);
    % if we use Regular Expressions!
elseif imgType == 3 && ~isempty(get(handles.listbox_regExp,'String'))
         baseDir    = ud.baseDir;
         subDir     = ud.regExpSubDir;
         regExp     = ud.regExp;
         subjectCount = size(vertcat(c_ids{:}),1);
         for c=1:size(c_ids,2)
             c_path{c}    = cell(size(c_ids{c},1));
             tmpPath = c_path{c};
             tmpId = c_ids{c};
             for sc=1:size(tmpId,1)
               tmpPath{sc} =  [baseDir filesep tmpId{sc} filesep subDir];
               imgs = spm_select('List',tmpPath{sc}, regExp);
               fullImages = cell(size(imgs,1));
               for k=1:size(imgs,1)
                   fullImages{k} = [tmpPath{sc} filesep imgs(k,:)];
               end
               try
                   if strcmpi(fullImages{1}(end-2:end),'mat')
                       newPattern = janis_patternMat(fullImages);
                   else
                       newPattern = janis_patternSimple(fullImages);
                   end
               catch
                  error('blub');
               end
               newPattern.description = tmpId{sc};
               newPattern.setFeatureSelection(ud.default.reductionMethod);
               newPattern.generatePattern;
               jc{c} = jc{c}.addMember(newPattern);
               subcounter = subcounter + 1;
               updateWaitbar(h,subcounter,subjectCount);
             end
         end
         close(h);
else
    error('Unkown method for pattern generation???');
end
% add classes
for h=1:size(jc,2)
    ccollection.addClass(jc{h});
end
%ccollection.addClass(jc2);
potential_dupes = ccollection.checkDuplicates;
if ~isempty(potential_dupes)
    tmp = arrayfun(@(x) [x{:}], potential_dupes, 'UniformOutput', false);
    warndlg({'Some references to image files have been detected multiple times.';'This might refer to duplicate subjects. Be aware of this issue!';'';'Duplicate files:';'';strvcat(tmp{:})},'Potential duplicates!');
end
ud.class_collection = ccollection;
% set header of figure, enable buttons
try
    set(handles.text_header,'String',sprintf('%d classes, %d subjects, %d voxels per sub., type %s, %d condtion(s)    [%s]', ...
                                            ud.class_collection.size, ...
                                            ud.class_collection.patternCount, ...
                                            ud.class_collection.classes{1}.voxelsPerSub, ...
                                            ud.class_collection.get(1).members{1}.ImgType, ...
                                            size(ud.class_collection.get(1).members{1}.imgFiles,2),datestr(now,'HH:MM:SS')));
catch
    set(handles.text_header,'String','Currently no information available');
end
set(handles.figure1,'UserData',ud);
set(handles.pushbutton_apply,'Enable','off');
set(handles.review_classes,'Enable','on');
set(handles.pushbutton_validation,'Enable','on');
setup_val_panel(hObject,eventdata,handles);

function setup_val_panel(hObject,eventdata,handles)
ud = get(handles.figure1,'UserData');
if isfield(ud,'panelVal')
    try
    cellfun(@(x) delete(x),ud.panelVal);
    end
    rmfield(ud,'panelVal');
end
panel = handles.validation_panel;
for k=1:length(ud.classes)
    bgroup{1,k} = uicontrol(panel,'Style','text','String',ud.classNames{k},'Tag','valOpt_string');
    set(bgroup{1,k},'Position', [0 140-20*k 150 20]);
    bgroup{2,k} = uicontrol(panel,'Style','radiobutton','String','train','Value',1,'Tag','valOpt_train');
    set(bgroup{2,k},'Position', [140 145-20*k 60 20]);
    bgroup{3,k} = uicontrol(panel,'Style','radiobutton','String','test','callback',{@rad_call,bgroup{2,k}},'Tag','valOpt_test');
    set(bgroup{2,k},'callback',{@rad_call, bgroup{3,k}});
    set(bgroup{3,k},'Position', [240 145-20*k 60 20]);
end
ud.panelVal=bgroup;
set(handles.figure1,'UserData',ud);

function rad_call(varargin)
set(varargin{3},'Value',~get(varargin{1},'Value'));

function updateWaitbar(h,subcounter,subjectCount)
           g = toc;
           waitbar(subcounter/subjectCount, h, ...
           sprintf('subject %d (%d)\n Time Remaining: %4.1f sec. - Elapsed: %3.1f sec.', ...
           subcounter, subjectCount, (g/subcounter)*(subjectCount-subcounter), g));

% display information about class collection
function collection_review_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
msg = evalc('ud.class_collection.show');
msgbox(msg, ['type: ' class(ud.class_collection)]);

% display information about class1
function review_class1_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
msg = evalc('ud.class_collection.get(1).show');
msgbox(msg, ['class: ' class(ud.class_collection.get(1))]);

% display information about class2
function review_class2_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
msg = evalc('ud.class_collection.get(2).show');
msgbox(msg, ['class: ' class(ud.class_collection.get(2))]);



% Feature Selection / Expert Options
function pushbutton_fs_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
varargout = janis_gui_feature_options(ud.active, ud.default, ud.preMap, ud.proMap);
if length(varargout) > 1
    pre =               varargout{1};
    intra =             varargout{2};
    pre_inactive =      varargout{4};
    intra_inactive =    varargout{5};
    preMap =            varargout{6};
    proMap =            varargout{7};
    ud.active.preprocessors = pre;
    ud.active.intravalidationPreprocessors = intra;
    ud.active.available_ips = intra_inactive;
    ud.active.available_pps = pre_inactive;
    ud.preMap = preMap;
    ud.proMap = proMap;
    set(handles.listbox_fs,'String',{ud.active.preprocessors{:},ud.active.intravalidationPreprocessors{:}});
    set(handles.figure1,'UserData',ud);
    close(varargout{8}.figure1);
end

function listROIs(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
pro = ud.active.preprocessors;
preproc = copy(ud.preMap(pro{1}));
b = vertcat(preproc.regions{:});
strvcat(b.name)


% set header for table
function table_confusion_CreateFcn(hObject, eventdata, handles)
set(hObject,'RowName',{'true';'false'});


% Permutation Test: runs validation for n times on shuffeld class
% collections
function permutationTest_Callback(hObject, eventdata, handles)
varargout = janis_permutation;
permCount = varargout{1};
close(varargout{2}.figure1);
ud = get(handles.figure1,'UserData');
results = zeros(permCount,1);
cp = ud.classPerformance;
results(1,1) = cp.CorrectRate;
wb = janis_gui_RespondToPermutation(permCount, cp.CorrectRate);
for iter=2:permCount
    permCollection = ud.class_collection.shuffledCopy;
    validator = initClassifier(handles,permCollection);
    wb.listenTo(validator);
    validator.runValidation;
    results(iter,1) = validator.classPerformance.CorrectRate;
    pval = sum(results(1:iter,1) >= cp.CorrectRate)/iter;
    wb.updateRound(pval, results(iter,1));
end
delete(wb);
set(handles.edit_pval,'String',num2str(pval));
set(handles.edit_permcount,'String',num2str(permCount));
set(handles.sig_panel,'Visible','on');

% --------------------------------------------------------------------
function load4ensemble_Callback(hObject, eventdata, handles)
% hObject    handle to load4ensemble (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
try
    [fname, fdir] = uigetfile('*.dat','Pick a saved file');
    loaded = load([fdir fname],'-mat');
    if isfield(loaded.ud,'validator')
        setEnsemble(handles,loaded.ud.validator);
    else
        errordlg('Could not load: Please select a fully saved classifier','No valid classifier found');
    end
catch
    errordlg('Could not load classifier','Load Problem');
end

function setEnsemble(handles,validator)
ud = get(handles.figure1,'UserData');
answer=inputdlg('Name the classifier','Name for classifier',1,{'untitled'});
validator.setClassifierName(answer);
ensembleList = get(handles.listbox_ensembleList,'String');
ensembleList{size(ensembleList,1)+1} = answer{:};
ud.ensemble{size(ud.ensemble,2)+1} = ud.validator;
set(handles.listbox_ensembleList,'String',ensembleList);
set(handles.toggle_ensembles,'Enable','on');
set(handles.figure1,'UserData',ud);
set(handles.pushbutton_validation,'Enable','off');


% add a classifier to the ensemble.
function addClassifierToEnsemble_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
setEnsemble(handles,ud.validator);
set(handles.pushbutton_fromComputed,'Enable','off');
set(handles.pushbutton_validation,'Enable','off');

function EnsembleValidator = generateEnsemble(class_collection,validators)
jemv = janis_ensemble_majorityVote;
ensParser = janis_ensembleParser(class_collection);
for k = 1:size(validators,2)
    if ~isempty(validators{k})
       validators{k}.resetClassPerformance;
       ensParser = ensParser.addValidatorToEnsemble(validators{k});
    end
end
valiFunc = str2func(class(validators{1}));
EnsembleValidator = valiFunc(class_collection, jemv, ensParser);


% calculate majority vote of ensemble
function pushbutton_ensembleRun_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
ensemble = generateEnsemble(ud.class_collection,ud.ensemble);
wb = janis_gui_RespondToEnsemble(ensemble);
try
    ensemble.runValidation;
    delete(wb);
    set(handles.panel_results,'Visible','on');
    handleGraph(ensemble.classPerformance, handles);
    handleConfusion(ud.class_collection,ensemble.classPerformance,handles);
    singlePerfs = '';
    for k=1:size(ensemble.classifier.classifierStruct.trainPatterns,2)
            disp(size(sprintf('%5.1f %% ',ensemble.classifier.classifierStruct.trainPatterns{k}.classPerformance.CorrectRate*100)));
            disp(sprintf('%5.1f %% ',ensemble.classifier.classifierStruct.trainPatterns{k}.classPerformance.CorrectRate*100));
            singlePerfs(k,:) = sprintf(' %5.1f %% ',ensemble.classifier.classifierStruct.trainPatterns{k}.classPerformance.CorrectRate*100);
    end

catch exp1
    if strcmp(exp1.identifier,'janis:MajorityPattSituation')
        errordlg( ...
            'Majority vote patt situation has occured. You should consider using an odd number of classifiers for the ensemble to circumvent this problem.', ...
            'Patt Situation');
        delete(wb);
        dummy = classperf([0 1],[1 0]);
        uiwait(gcf);
        handleGraph(dummy,handles);
        handleConfusion(ud.class_collection,dummy,handles);
        singlePerfs = 'N/A';
    else
        rethrow(exp1)
    end
end
set(handles.listbox_ensPerf,'String',singlePerfs);

% remove classifier from ensemble
function pushbutton_removeFromEnsemble_Callback(hObject, eventdata, handles)
ensembleList = get(handles.listbox_ensembleList,'String');
toRemoveIdx  = get(handles.listbox_ensembleList,'Value');
ud = get(handles.figure1,'UserData');
ensembleList(toRemoveIdx,:) = [];
set(handles.listbox_ensembleList,'Value',max(get(handles.listbox_ensembleList,'Value')-1,1));
set(handles.listbox_ensembleList,'String',ensembleList);
ud.ensemble{toRemoveIdx} = [];
set(handles.figure1,'UserData',ud);

% reset ensemble, clear alls lists, and camouflages the panel
function pushbutton_resetEnsemble_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
ud.ensemble = {};
set(handles.toggle_ensembles,'Enable','off');
set(handles.listbox_ensembleList,'String',[]);
set(handles.listbox_ensPerf,'String',[]);
set(handles.listbox_ensPerf,'Value',1);
set(handles.figure1,'UserData',ud);
set(handles.listbox_ensembleList,'Value',1);

% shows parameters of the currently active classifier
function pushbutton_classifier_settings_view_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
msg = evalc('ud.classifier.show');
msgbox(msg);

% edit a classifiers paramters
function pushbutton_change_classifier_settings_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
changedClassifier = ud.classifier.uiconfigure;
ud.classifier = changedClassifier;
set(handles.figure1,'UserData',ud);


% --------------------------------------------------------------------
function autoEnsemble_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
imgType = get(handles.popupmenu_imgType,'Value');
if ~((isfield(ud,'spm') && ud.spm && imgType < 3) || (isfield(ud,'spm') && ud.spm && imgType == 4))
    errordlg({'Error during classification:';'This method is only supported with condition specified by SPM'},'Classification Exception')
    throw(MException('janis:MissingComputedClassifier', 'This method is only supported with condition specified by SPM'));
end
conditions = get(handles.listbox_trials,'String');
condVals = get(handles.listbox_trials,'Value');
set(handles.panel_results,'Visible','off');
for c=1:size(condVals,2)
    set(handles.listbox_trials,'Value',condVals(c));
    pushbutton_apply_Callback(hObject,eventdata,handles);
    pushbutton_validation_Callback(hObject, eventdata, handles);
    ud = get(handles.figure1,'UserData');
    ud.validator.setClassifierName(conditions(c));
    ensembleList = get(handles.listbox_ensembleList,'String');
    ensembleList{size(ensembleList,1)+1} = conditions{c};
    ud.ensemble{size(ud.ensemble,2)+1} = ud.validator;
    set(handles.listbox_ensembleList,'String',ensembleList);
    set(handles.toggle_ensembles,'Enable','on');
    set(handles.figure1,'UserData',ud);
    set(handles.pushbutton_fromComputed,'Enable','off');
    set(handles.panel_results,'Visible','off');
    set(handles.pushbutton_validation,'Enable','off');
end
set(handles.listbox_trials,'Value',condVals);


% --------------------------------------------------------------------
function Debugging_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
keyboard


% --------------------------------------------------------------------
function new_regress_Callback(hObject, eventdata, handles)
% hObject    handle to new_regress (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
ud = get(handles.figure1,'UserData');
baseDir = uigetdir(pwd, 'Select Basedirectory of study');
 [filename, pathname, filterindex] = uigetfile({'*.xls;*.csv'}, 'Pick an Excel or CSV File');
%  if strcmp(filename(end-2:end),'csv')
%     [x y] = textread([pathname filename],'%s%s','whitespace',',');
%     b = [x y];
%  elseif strcmp(filename(end-2:end),'xls')
    [regressand descriptor] = xlsread([pathname filename]);
%  else
%      error('Unknown Fileformat');
%  end
ud.regression = true;
ud.baseDir = baseDir;
set(handles.listbox_members_c1,'String',descriptor);
set(handles.listbox_members_c2,'String',regressand);
set(handles.edit_classname1,'String','class');
set(handles.edit_classname2,'String','regressand');
set(handles.pushbutton_editClassMembers,'Enable','off');
set(handles.edit_classes_members,'Enable','off');
set(handles.popupmenu_imgType,'Visible','on');
set(handles.edit_spm_file,'Visible','on');
set(handles.edit_spm_file,'String','');
set(handles.pushbutton_specify_spm,'Visible','on');
set(handles.listbox_members_c1,'Enable','on');
set(handles.listbox_members_c2,'Enable','on');
set(handles.pushbutton_editClassMembers,'Enable','on');
set(handles.figure1,'UserData',ud);
resetView(handles);


% --------------------------------------------------------------------
function add_more_images_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
tic;
subcounter = 0;
h = waitbar(0, '1', 'Name', 'Creating Classes & Members');
ccollection = ud.class_collection;
imgType = get(handles.popupmenu_imgType,'Value');
jc{1} = janis_class(get(handles.edit_classname1,'String'));
c_ids{1} = get(handles.listbox_members_c1,'String');
if ~isfield(ud,'regression') || ~ud.regression
    jc{2} = janis_class(get(handles.edit_classname2,'String'));
    c_ids{2} = get(handles.listbox_members_c2,'String');
else
    regressands =get(handles.listbox_members_c2,'String');
end

% if we use a SPM.mat and imgType is CON or Beta
if ((isfield(ud,'spm') && ud.spm && imgType < 3) || (isfield(ud,'spm') && ud.spm && imgType == 4))
   baseDir = ud.baseDir;
   spm_path = ud.spm_subpath;

   for k=size(c_ids,2)
       c_path{k} = cell(size(c_ids{k},1));
   end
   %%%%%%%%%%%%%%%%%%%%%%%%%%
   trial_cond = get(handles.listbox_trials,'String');
   trial_Idx = get(handles.listbox_trials,'Value');
   trial =  {trial_cond{trial_Idx}};
   for c=1:size(c_ids,2)
     for sc=1:size(c_ids{c},1)
           newpath =  [baseDir filesep cell2mat(c_ids{c}(sc)) filesep spm_path];
           if strcmp(ud.class_collection.classes{c}.members{sc}.description, c_ids{c}(sc))
                ud.class_collection.classes{c}.members{sc}.addCondition(newpath, trial');
                ud.class_collection.classes{c}.members{sc}.generatePattern;
           else
                error('Members do not match!');
           end
           subcounter = subcounter + 1;
           updateWaitbar(h,subcounter,ud.class_collection.patternCount);
      end
   end
       close(h);
    else
        error('Unkown method for pattern generation???');
end
ud.class_collection = ccollection;
% set header of figure, enable buttons
try
    set(handles.text_header,'String',sprintf('%d subjects, %d voxels per sub., type %s, %d condtion(s)    [%s]', ...
                                            ud.class_collection.patternCount, ...
                                            ud.class_collection.classes{1}.voxelsPerSub, ...
                                            ud.class_collection.get(1).members{1}.ImgType, ...
                                            size(ud.class_collection.get(1).members{1}.imgFiles,2),datestr(now,'HH:MM:SS')));
catch
    set(handles.text_header,'String','Currently no information available');
end
set(handles.figure1,'UserData',ud);
set(handles.pushbutton_apply,'Enable','off');
set(handles.review_classes,'Enable','on');
set(handles.pushbutton_validation,'Enable','on');


% --------------------------------------------------------------------
function auto_randomSubSpace_Callback(hObject, eventdata, handles)
numFeatures = str2double(inputdlg({'Number',},'Number of features',1,{'200'}));
numClassifiers = str2double(inputdlg({'Number',},'Number of Classifiers',1,{'5'}));
customSeed =  str2double(inputdlg({'Number',},'Seed for Random masks',1,{'0'}));
randStreams = RandStream.create('mrg32k3a','NumStreams',numClassifiers,'CellOutput',true,'Seed',customSeed);
rss = cell(numClassifiers,1);
ud = get(handles.figure1,'UserData');
if ~isfield(ud,'validator')
    errordlg({'Error during classification:';'Please compute raw classifier first!'},'Classification Exception')
    throw(MException('janis:MissingComputedClassifier', 'Please compute raw classifier first!'));
end
wb = busyBar(get(handles.figure1,'Position'));
for k=1:numClassifiers
    rss{k} = janis_pro_randomMask;
    rss{k} = rss{k}.setNFeatures(numFeatures);
    rss{k} = rss{k}.setRandomStream(randStreams{k});
    validator = ud.validator.copy;
    validator.setClassifierName(['random subspace ' num2str(k) ' (' num2str(numClassifiers) ')']);
    validator.patternParser.addIntraValidationProcessors(rss{k});
    ensembleList = get(handles.listbox_ensembleList,'String');
    ensembleList{size(ensembleList,1)+1} = ['random subspace ' num2str(k)] ;
    ud.ensemble{size(ud.ensemble,2)+1} = validator;
    set(handles.listbox_ensembleList,'String',ensembleList);
    %set(handles.uipanel_ensemble,'Visible','on');
    set(handles.toggle_ensembles,'Enable','on');
    set(handles.figure1,'UserData',ud);
    set(handles.pushbutton_fromComputed,'Enable','off');
end
close(wb);


% --------------------------------------------------------------------
function plotroc_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
if isfield(ud,'validator')
    if length(ud.validator.classPerformance.classLabels) == 2
        decFactors = ud.validator.decFactors;
        if isfield(decFactors(1),'decVals')
            decVals = vertcat(decFactors.decVals);
            decLabels = vertcat(decFactors.label);
            [X Y thre auc] = perfcurve(decLabels,decVals,0);
            figure;
            plot(X,Y);
            xlabel('False Positive');
            ylabel('True Positive');
            line([0 1], [0 1], 'Color', 'yellow');
            title(['ROC - Area under curve (AUC): ' num2str(auc)])
        else
            % ErrorMsg Classifier does not support
            errordlg('Roc Plot is not supported for the actual classificaton algorithm.','Unsupported classifier');
        end
    else
        errordlg('Roc Plot is only supported for two classes.','Unsupported Setup');
    end
else
    errordlg('Setup and calculate classification first!','No classifier available');
end


% --------------------------------------------------------------------
function loadTestImages_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
subcounter = 0;
jc = janis_class('testImages');
imgPerSub = inputdlg('How many images per subject?','Test Group',1,{'1'});
count = str2num(imgPerSub{:});
for k =1:count
    [testImages{k} ignore] = spm_select(inf,'image',['select image #' num2str(k) 'for each subject'],{});
end
subjectCount = size(testImages{1},1);
h = waitbar(0, '1', 'Name', 'Adding new testImages');
           for idx=1:subjectCount;
              for u=1:size(testImages,2)
                  imgsTmp{u} = testImages{u}(idx,:);
              end
                  newPattern = janis_patternSimple(imgsTmp);
                  newPattern.description = imgsTmp(1);
                  newPattern.setFeatureSelection(ud.default.reductionMethod);
                  newPattern.generatePattern;
                  jc = jc.addMember(newPattern);
                  subcounter = subcounter + 1;
                  updateWaitbar(h,subcounter,subjectCount);
                  subcounter = subcounter + 1;
           end
close(h);
ud.class_collection.addClass(jc);
set(handles.figure1,'UserData',ud);


% --- Executes on selection change in edit_classname1.
function edit_classname1_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
set(handles.listbox_members_c1,'Value',1);
set(handles.listbox_members_c1,'String',ud.classes{get(handles.edit_classname1,'Value')});


% --- Executes on selection change in edit_classname2.
function edit_classname2_Callback(hObject, eventdata, handles)
ud = get(handles.figure1,'UserData');
set(handles.listbox_members_c2,'Value',1);
set(handles.listbox_members_c2,'String',ud.classes{get(handles.edit_classname2,'Value')});

% --- Executes on selection change in popupmenu_validator.
function popupmenu_validator_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu_validator (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
if get(hObject,'Value') == 3
    set(handles.toggle_validationOptions,'Enable','on');
    %set(handles.validation_panel,'Visible','on');
else
    %set(handles.validation_panel,'Visible','off');
    set(handles.toggle_validationOptions,'Enable','off');
end


% --- Executes when selected object is changed in options_tab.
function options_tab_SelectionChangeFcn(hObject, eventdata, handles)
% hObject    handle to the selected object in options_tab
% eventdata  structure with the following fields (see UIBUTTONGROUP)
%	EventName: string 'SelectionChanged' (read only)
%	OldValue: handle of the previously selected object or empty if none was selected
%	NewValue: handle of the currently selected object
% handles    structure with handles and user data (see GUIDATA)

% set all invisible
set(handles.uipanel_memberView,'Visible','off');
set(handles.uipanel_training,'Visible','off');
set(handles.uipanel_ensemble,'Visible','off');
set(handles.validation_panel,'Visible','off');
set(handles.uipanel_validationResults,'Visible','off');
set(handles.uipanel_dataMod,'Visible','off');
if isfield(eventdata,'NewValue')
    switch get(eventdata.NewValue,'Tag')
        case 'toggle_members'
            set(handles.uipanel_memberView,'Visible','on');
            % Code for when togglebutton2 is selected.
            % Continue with more cases as necessary.
        case 'toggle_modality'
            set(handles.uipanel_dataMod,'Visible','on');
        case 'toggle_training'
            set(handles.uipanel_training,'Visible','on');
        case 'toggle_ensembles'
            set(handles.uipanel_ensemble,'Visible','on');
        case 'toggle_validationOptions'
            set(handles.validation_panel,'Visible','on');
        case 'toggle_validation'
            set(handles.uipanel_validationResults,'Visible','on');
        otherwise
            %error handle code!!!!!
            % Code for when there is no match.
    end
else
    set(handles.uipanel_memberView,'Visible','on');
end



function edit_helpBox_Callback(hObject, eventdata, handles)
% hObject    handle to edit_helpBox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_helpBox as text
%        str2double(get(hObject,'String')) returns contents of edit_helpBox as a double


% --- Executes during object creation, after setting all properties.
function edit_helpBox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_helpBox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on selection change in listbox_statusBar.
function listbox_statusBar_Callback(hObject, eventdata, handles)
% hObject    handle to listbox_statusBar (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns listbox_statusBar contents as cell array
%        contents{get(hObject,'Value')} returns selected item from listbox_statusBar


% --- Executes during object creation, after setting all properties.
function listbox_statusBar_CreateFcn(hObject, eventdata, handles)
% hObject    handle to listbox_statusBar (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --------------------------------------------------------------------
function Test_Context_Menu_Callback(hObject, eventdata, handles)
msgbox('Test');
% hObject    handle to Test_Context_Menu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --------------------------------------------------------------------
function Untitled_7_Callback(hObject, eventdata, handles)
% hObject    handle to Untitled_7 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
units = get(gcbf,'units');
set(gcbf,'units', 'pixels');
obj_han = overobj('axes')
set(gcbf, 'units', units);
msgbox('Test');

function linkCallbackFcn(src,eventData)
   url = eventData.getURL.toString;      % a java.net.URL object
   %description = eventData.getDescription; % URL string
   %jEditbox = eventData.getSource;
   switch char(eventData.getEventType)
      case char(eventData.getEventType.ACTIVATED)
          web(char(url.toString));
   end

function msg = getFeatureSelectionReport(pro,intra)
msg = {'Feature Selection Methods used:' ' ' ' '};
msg = [msg '------- Before Crossvalidation: --------', ...
           '========================================' ' ' ' '];
if isempty(pro);
    msg = [msg ' - None -' ' ' ' '];
else
    for k=1:length(pro)
        tmp = pro{k};
        msg = [msg ['* ' num2str(k) '.'] evalc('tmp.viewSettings')];
        msg = [msg '--------------------------------------------'];
    end
    msg = [msg ' '];
end
msg = [msg '------ Embedded Crossvalidation: -------', ...
           '========================================' ' ' ' '];
if isempty(intra);
    msg = [msg ' - None -' ' ' ' '];
else
    for k=1:length(intra)
        tmp = intra{k};
        msg = [msg ['* ' num2str(k) '.'] evalc('tmp.viewSettings')];
        msg = [msg '--------------------------------------------'];
    end
    msg = [msg ' '];
end


% --------------------------------------------------------------------
function view_featureSelection_Callback(hObject, eventdata, handles)
% hObject    handle to view_featureSelection (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%s = num2str((1:1000)');
ud = get(handles.figure1,'UserData');
msg = [];
if isfield(ud,'ensemble') && ~isempty(ud.ensemble)
    for k=1:length(ud.ensemble)
        pro=ud.ensemble{k}.patternParser.preprocessors;
        intra=ud.ensemble{k}.patternParser.intraValidationProcessors;
        msg = [msg strcat( {'****** Classifier '},num2str(k),{': '},ud.ensemble{k}.classifier.title,{' *************'}),getFeatureSelectionReport(pro,intra)];
    end
    msg = ['ENSEMBLE CLASSIFICATION --' msg];
else
    pro = ud.validator.patternParser.preprocessors;
    intra = ud.validator.patternParser.intraValidationProcessors;
    msg = getFeatureSelectionReport(pro,intra);
end
h = figure('MenuBar', 'none', ...
    'name','Feature Selection Methods', ...
    'numbertitle','off');
uicontrol('Parent',h,...
    'Units','normalized',...
    'Position',[0.05,0.15,0.9,0.8],...
    'Style','edit',...
    'Max',100,...
    'Enable','inactive',...
    'HorizontalAlignment','left',...
    'BackgroundColor',[1 1 1],...
    'String',msg);
uicontrol('Parent',h,...
    'Style','Pushbutton',...
    'String','Close',...
    'units','normalized',...
    'Position',[0.43 ,0.01, 0.14,0.07],...
    'Callback', 'close');


% --------------------------------------------------------------------
function view_fs_plain_Callback(hObject, eventdata, handles)
% hObject    handle to view_fs_plain (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
ud = get(handles.figure1,'UserData');
classCollection = janis_classCollection;
parser = janis_simpleParser(classCollection);
parser = handlePreprocessors(ud.active, parser,handles);
pro = parser.preprocessors;
intra = parser.intraValidationProcessors;
msg = getFeatureSelectionReport(pro,intra);
h = figure('MenuBar', 'none', ...
    'name','Feature Selection Methods', ...
    'numbertitle','off');
uicontrol('Parent',h,...
    'Units','normalized',...
    'Position',[0.05,0.15,0.9,0.8],...
    'Style','edit',...
    'Max',100,...
    'Enable','inactive',...
    'HorizontalAlignment','left',...
    'BackgroundColor',[1 1 1],...
    'String',msg);
uicontrol('Parent',h,...
    'Style','Pushbutton',...
    'String','Close',...
    'units','normalized',...
    'Position',[0.43 ,0.01, 0.14,0.07],...
    'Callback', 'close');


% --- Executes on button press in pushbutton_viewClassifierSettings.
function pushbutton_viewClassifierSettings_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_viewClassifierSettings (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)