classdef GUIvisualize < handle
    % Class to compare two model objects
    %
    %
    % PROPERTIES
    %
    % figureHandle:         Property contains the handle to the figure in
    %                       which the comparison takes place
    %
    %
    % SYMBOLS AND ABBREVIATIONS:
    %
    % LM:  Local model
    %
    % p:   Number of inputs (physical inputs)
    % q:   Number of outputs
    % N:   Number of data samples
    % M:   Number of LMs
    % nx:  Number of regressors (x)
    % nz:  Number of regressors (z)
    % nc:  Maximum model complexity
    
    % Julian Belz, 20-March-2011
    % Institut für Mess- und Regelungstechnik, Universität Siegen, Deutschland
    % Institute of Measurement and Control, University of Siegen, Germany
    % Copyright (c) 2011 by Oliver Nelles
    
    properties
        figureHandle % Property contains the handle to the figure in which the comparison takes place
    end
    
    methods
        function fh = GUIvisualize(varargin)
            % Graphical user interface to compare two models
            %
            %
            % figureHandle = compareModels(LMN1,LMN2,...)
            %
            %
            % INPUT
            %
            % LMN1:                             Local model network object.
            %
            %
            % OUTPUT
            %
            % figureHandle:         (1 x 1)     Handle to the figure containing the
            %                                   GUI. Eventually neccessary to close
            %                                   figure from outside the GUI.
            
            % Set global variables
            % model:            (numberOfmodels x 4)    The first colum contains the
            %                                           LMN object, the net 3 colums
            %                                           contain matrices that are
            %                                           needed for the plots. 2nd colum
            %                                           contains the x-axis values, 3rd
            %                                           colum contains the y-axis
            %                                           values and the 4th colum
            %                                           contains the z-axis values.
            % sbBars:           (numberOfScrollbarsx1)  Handles to all existing
            %                                           scrollbars
            % sbTolEdit:        (numberOfScrollbarsx1)  Handles to all existing
            %                                           tolerance edits
            % sbBezText         (numberOfScrollbarsx1)  Handles to all existing
            %                                           input scrollbars descriptions
            % sbTolText         (numberOfScrollbarsx1)  Handles to all existing
            %                                           tolerance text
            % sbValEdit         (numberOfScrollbarsx1)  Handles to all existing
            %                                           value edit fields of the
            %                                           scrollbars
            % sbWertText        (numberOfScrollbarsx1)  Handles to all existing
            %                                           value texts
            if size(varargin,2) > 0
                % Check if the passed arguments possess a dataSet class,
                % which is absolutely necessary for this GUI to work
                helpMeCount = 1;
                for kk = 1:size(varargin,2)
                    if isa(varargin{1,kk},'dataSet')
                        model{helpMeCount,1} = varargin{1,kk}; %#ok<AGROW>
                        helpMeCount = helpMeCount + 1;
                    else
                        fprintf('\n%d. input argument is either no model object or the model object has not been trained.\n',kk);
                    end
                end
                %                 model           = cell(size(varargin,2),2);
                %                 model(:,1)      = varargin';
            else
                model           = cell(0,2);
            end
            numberOfmodels      = size(model,1);
            
            sbBars     = cell(1,1);
            sbTolEdit  = sbBars;
            sbBezText  = sbBars;
            sbTolText  = sbBars;
            sbValEdit  = sbBars;
            sbWertText = sbBars;
            
            % Definitions of the figure containing all GUI components
            width           = 1195;
            height          = 700;
            scrsize         = get(0,'screensize');
            windowPosition  = [(scrsize(3) - width)/2, ...
                (scrsize(4) - height)/2, width, height];
            backgroundcolor = [.7 .7 .7];
            backgroundcolor2= [1 1 1];
            
            % Definitions for the plots
            linewidth       = 2;
            linestyle       = 'none';
            marker          = 'o';
            markersize      = 8;
            fontname        = 'Times New Roman';
            fontsize        = 11;
            
            fh.figureHandle    = figure('Position',windowPosition,'Visible','off',...
                'MenuBar','none','Toolbar','figure','color',backgroundcolor,...
                'KeyReleaseFcn',@reposElements);
            
            %% Definition of the GUI components
            
            % Load positions of GUI components
            positionen = [];
            load('positionenCompareModels.mat');
            
            % Panel for settings, that affect both model panels
            
            hPanelBothModels = uipanel('Parent',fh.figureHandle,...
                'Title','Common settings',...
                'Units','pixels',...
                'Position',positionen.panelBothModels,...
                'Tag','panelBothModels');
            
            hModelReadInText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.ModelReadInText,...
                'String','Add model to popup menus:',...
                'Tag','ModelReadInText');
            
            hEditModel = uicontrol('Parent',hPanelBothModels,...
                'Style','edit',...
                'String','',...
                'Callback',@editBrowse,...
                'Position',positionen.modelEdit,...
                'Tag','modelEdit');
            
            hBrowseModel = uicontrol('Parent',hPanelBothModels,...
                'Style','Pushbutton',...
                'String','Browse',...
                'Callback',@editBrowse,...
                'Position',positionen.brwoseModel,...
                'Tag','brwoseModel');
            
            hViewConstrain = uicontrol('Parent',hPanelBothModels,...
                'Style','checkbox',...
                'String','Constrain model views',...
                'Value',1,...
                'Enable','off',...
                'Position',positionen.viewConstrain,...
                'Callback',@constrainView,...
                'Tag','viewConstrain');
            
            hGridResolutionText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.gridResolutionText,...
                'String','Grid resolution:',...
                'Tag','gridResolutionText');
            
            hGridResolutionEdit = uicontrol('Parent',hPanelBothModels,...
                'Style','edit',...
                'String','20',...
                'Enable','off',...
                'Callback',@updatePlotScrollBars,...
                'Position',positionen.gridResolutionEdit,...
                'Tag','gridResolutionEdit');
            
            hInputDimText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.inputDimText,...
                'String','Input space:',...
                'Tag','inputDimText');
            
            hPopupInputDim = uicontrol('Parent',hPanelBothModels,...
                'Style','popupmenu',...
                'Value',2,...
                'String',{'1D','2D'},...
                'Enable','off',...
                'Position',positionen.popupInputDim,...
                'Callback',@updatePlot,...
                'Tag','popupInputDim');
            
            hIllustrationText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.illustrationText,...
                'String','Illustration:',...
                'Tag','illustrationText');
            
            hPopupIllustration = uicontrol('Parent',hPanelBothModels,...
                'Style','popupmenu',...
                'Value',1,...
                'Enable','off',...
                'String',{'surf','mesh','plot3'},...
                'Position',positionen.popupIllustration,...
                'Callback',@changeIllustrationStyle,...
                'Tag','popupIllustration');
            
            hXaxisText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.xAxisText,...
                'String','x-axis:',...
                'Tag','xAxisText');
            
            hPopupXaxis = uicontrol('Parent',hPanelBothModels,...
                'Style','popupmenu',...
                'Value',1,...
                'Enable','off',...
                'String',{'u1','u2','u3'},...
                'Position',positionen.popupXaxis,...
                'Callback',@updatePlot,...
                'Tag','popupXaxis');
            
            hYaxisText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.yAxisText,...
                'String','y-axis:',...
                'Tag','yAxisText');
            
            hPopupYaxis = uicontrol('Parent',hPanelBothModels,...
                'Style','popupmenu',...
                'Value',1,...
                'Enable','off',...
                'String',{'u1','u2','u3'},...
                'Position',positionen.popupYaxis,...
                'Callback',@updatePlot,...
                'Tag','popupYaxis');
            
            hZaxisText = uicontrol('Parent',hPanelBothModels,...
                'Style','text',...
                'Position',positionen.zAxisText,...
                'String','z-axis:',...
                'Tag','zAxisText');
            
            hPopupZaxis = uicontrol('Parent',hPanelBothModels,...
                'Style','popupmenu',...
                'Value',1,...
                'Enable','off',...
                'String',{'y1','y2','y3'},...
                'Position',positionen.popupZaxis,...
                'Callback',@updatePlot,...
                'Tag','popupZaxis');
            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            
            hTextDesiredPoints = uicontrol('Parent',hPanelBothModels,...
                'Style','checkbox',...
                'Position',positionen.textDesiredPoints,...
                'Value',1,...
                'Enable','off',...
                'Callback',@updatePlotScrollBars,...
                'String','Set number of points, that should be displayed:',...
                'Tag','textDesiredPoints');
            
            hSbDesiredPoints = uicontrol('Parent',hPanelBothModels,...
                'Style','slider',...
                'Position',positionen.sbDesiredPoints,...
                'Min',0,'Max',2,...
                'Value',1,...
                'Callback',@updatePlotScrollBars,...
                'Enable','off',...
                'Tag','sbDesiredPoints');
            addlistener(hSbDesiredPoints,...
                'ContinuousValueChange',@updatePlotScrollBars);
            
            hEditDesiredPoints = uicontrol('Parent',hPanelBothModels,...
                'Style','edit',...
                'Position',positionen.editDesiredPoints,...
                'String',num2str(1),...
                'Callback',@setDesiredNumberOfPoints,...
                'Enable','off',...
                'Tag','editDesiredPoints');
            
            hPushbuttonExport = uicontrol('Parent',hPanelBothModels,...
                'Style','Pushbutton',...
                'String','Export figures',...
                'Enable','off',...
                'Callback',@exportFigures,...
                'Position',positionen.pushbuttonExport,...
                'Tag','pushbuttonExport');
            
            % Panel for first model
            
            hPanelModel1 = uipanel('Parent',fh.figureHandle,...
                'Title','Model 1',...
                'Units','pixels',...
                'Position',positionen.panelModel1,...
                'Tag','panelModel1');
            
            hPopupModel = uicontrol('Parent',hPanelModel1,...
                'Style','popupmenu',...
                'Value',1,...
                'String',{'No models available yet.'},...
                'Position',positionen.popupModel,...
                'Callback',@chooseModel,...
                'Tag','popupModel');
            
            hEditModelLeft = uicontrol('Parent',hPanelModel1,...
                'Style','Pushbutton',...
                'String','Edit',...
                'Enable','off',...
                'Callback',@editModel,...
                'Position',positionen.editModel,...
                'Tag','editModel');
            
            hSaveModelLeft = uicontrol('Parent',hPanelModel1,...
                'Style','Pushbutton',...
                'String','Save',...
                'Enable','off',...
                'Callback',@saveModel,...
                'Position',positionen.saveModel,...
                'Tag','saveModel');
            
            hDeleteModelLeft = uicontrol('Parent',hPanelModel1,...
                'Style','Pushbutton',...
                'String','Delete',...
                'Enable','off',...
                'Callback',@deleteModel,...
                'Position',positionen.deleteModelLeft,...
                'Tag','deleteModelLeft');
            
            hAxesLeft = axes('Units','pixels',...
                'Parent',hPanelModel1,...
                'Position',positionen.axesLeft,...
                'Tag','axesLeft');
            
            hSmoothnessTextLeft = uicontrol('Parent',hPanelModel1,...
                'Style','text',...
                'Position',positionen.smoothnessTextLeft,...
                'String','Smoothness:',...
                'HorizontalAlignment','left',...
                'Tag','smoothnessTextLeft');
            
            hSmoothnessEditLeft = uicontrol('Parent',hPanelModel1,...
                'Style','edit',...
                'Position',positionen.smoothnessEditLeft,...
                'String',num2str(1),...
                'Callback',@changeSmoothnessLeft,...
                'Enable','off',...
                'Tag','smoothnessEditLeft');
            
            hSmoothnessSliderLeft = uicontrol('Parent',hPanelModel1,...
                'Style','slider',...
                'Position',positionen.smoothnessSliderLeft,...
                'Min',0.1,'Max',3,...
                'Value',1,...
                'Callback',@changeSmoothnessLeft,...
                'Enable','off',...
                'Tag','smoothnessSliderLeft');
            addlistener(hSmoothnessSliderLeft,...
                'ContinuousValueChange',@changeSmoothnessLeft);
            
            hModelComplexityTextLeft = uicontrol('Parent',hPanelModel1,...
                'Style','text',...
                'Position',positionen.modelComplexityTextLeft,...
                'String','Model complexity:',...
                'HorizontalAlignment','left',...
                'Tag','modelComplexityTextLeft');
            
            hModelComplexityEditLeft = uicontrol('Parent',hPanelModel1,...
                'Style','edit',...
                'Position',positionen.modelComplexityEditLeft,...
                'String',num2str(1),...
                'Callback',@changeModelComplexityLeft,...
                'Enable','off',...
                'Tag','modelComplexityEditLeft');
            
            hModelComplexitySliderLeft = uicontrol('Parent',hPanelModel1,...
                'Style','slider',...
                'Position',positionen.modelComplexitySliderLeft,...
                'Min',1,'Max',10,...
                'Value',1,...
                'Enable','off',...
                'Callback',@changeModelComplexityLeft,...
                'Tag','modelComplexitySliderLeft');
            addlistener(hModelComplexitySliderLeft,...
                'ContinuousValueChange',@changeModelComplexityLeft);
            
            hCheckBoxTrainDataLeft = uicontrol('Parent',hPanelModel1,...
                'Style','checkbox',...
                'String','Show train data',...
                'Value',1,...
                'Enable','off',...
                'Position',positionen.checkBoxTrainDataLeft,...
                'Callback',@updatePlotScrollBars,...
                'Tag','checkBoxTrainDataLeft');
            
            hCheckBoxTestDataLeft = uicontrol('Parent',hPanelModel1,...
                'Style','checkbox',...
                'String','Show test data',...
                'Value',1,...
                'Enable','off',...
                'Position',positionen.checkBoxTestDataLeft,...
                'Callback',@updatePlotScrollBars,...
                'Tag','checkBoxTestDataLeft');
            
            hShowPartitioningLeft = uicontrol('Parent',hPanelModel1,...
                'Style','Pushbutton',...
                'String','Show partitioning',...
                'Enable','off',...
                'Callback',@showPartitioning,...
                'Position',positionen.showPartitioning,...
                'Tag','showPartitioning');
            
            % Panel for second model
            
            % Get position of hPanelModel2 from the save mat-file, but the width and
            % height from hPanelModel1
            positionPanel2          = positionen.panelModel2;
            positionPanel2(3:4)     = positionen.panelModel1(3:4);
            hPanelModel2 = uipanel('Parent',fh.figureHandle,...
                'Title','Model 2',...
                'Units','pixels',...
                'Position',positionPanel2,...
                'Tag','panelModel2');
            
            hPopupModelRight = uicontrol('Parent',hPanelModel2,...
                'Style','popupmenu',...
                'Value',1,...
                'String',{'No models available yet.'},...
                'Position',positionen.popupModel,...
                'Callback',@chooseModel);
            
            hEditModelRight = uicontrol('Parent',hPanelModel2,...
                'Style','Pushbutton',...
                'String','Edit',...
                'Enable','off',...
                'Callback',@editModel,...
                'Position',positionen.editModel);
            
            hSaveModelRight = uicontrol('Parent',hPanelModel2,...
                'Style','Pushbutton',...
                'String','Save',...
                'Enable','off',...
                'Callback',@saveModel,...
                'Position',positionen.saveModel);
            
            hDeleteModelRight = uicontrol('Parent',hPanelModel2,...
                'Style','Pushbutton',...
                'String','Delete',...
                'Enable','off',...
                'Callback',@deleteModel,...
                'Position',positionen.deleteModelLeft);
            
            hAxesRight = axes('Units','pixels',...
                'Parent',hPanelModel2,...
                'Position',positionen.axesLeft);
            
            hSmoothnessTextRight = uicontrol('Parent',hPanelModel2,...
                'Style','text',...
                'Position',positionen.smoothnessTextLeft,...
                'String','Smoothness:',...
                'HorizontalAlignment','left');
            
            hSmoothnessEditRight = uicontrol('Parent',hPanelModel2,...
                'Style','edit',...
                'Position',positionen.smoothnessEditLeft,...
                'String',num2str(1),...
                'Enable','off',...
                'Callback',@changeSmoothnessRight);
            
            hSmoothnessSliderRight = uicontrol('Parent',hPanelModel2,...
                'Style','slider',...
                'Position',positionen.smoothnessSliderLeft,...
                'Min',0.1,'Max',3,...
                'Value',1,...
                'Enable','off',...
                'Callback',@changeSmoothnessRight);
            addlistener(hSmoothnessSliderRight,...
                'ContinuousValueChange',@changeSmoothnessRight);
            
            hModelComplexityTextRight = uicontrol('Parent',hPanelModel2,...
                'Style','text',...
                'Position',positionen.modelComplexityTextLeft,...
                'String','Model complexity:',...
                'HorizontalAlignment','left');
            
            hModelComplexityEditRight = uicontrol('Parent',hPanelModel2,...
                'Style','edit',...
                'Position',positionen.modelComplexityEditLeft,...
                'String',num2str(1),...
                'Enable','off',...
                'Callback',@changeModelComplexityRight);
            
            hModelComplexitySliderRight = uicontrol('Parent',hPanelModel2,...
                'Style','slider',...
                'Position',positionen.modelComplexitySliderLeft,...
                'Min',1,'Max',10,...
                'Value',1,...
                'Enable','off',...
                'Callback',@changeModelComplexityRight);
            addlistener(hModelComplexitySliderRight,...
                'ContinuousValueChange',@changeModelComplexityRight);
            
            hCheckBoxTrainDataRight = uicontrol('Parent',hPanelModel2,...
                'Style','checkbox',...
                'String','Show train data',...
                'Value',1,...
                'Enable','off',...
                'Position',positionen.checkBoxTrainDataLeft,...
                'Callback',@updatePlotScrollBars);
            
            hCheckBoxTestDataRight = uicontrol('Parent',hPanelModel2,...
                'Style','checkbox',...
                'String','Show test data',...
                'Value',1,...
                'Enable','off',...
                'Position',positionen.checkBoxTestDataLeft,...
                'Callback',@updatePlotScrollBars);
            
            hShowPartitioningRight = uicontrol('Parent',hPanelModel2,...
                'Style','Pushbutton',...
                'String','Show partitioning',...
                'Enable','off',...
                'Callback',@showPartitioning,...
                'Position',positionen.showPartitioning);
            
            % Panel to set operating point of both models
            
            hPanelOperationPoint = uipanel('Parent',fh.figureHandle,...
                'Title','Operating point',...
                'Units','pixels',...
                'Position',positionen.panelOperationPoint,...
                'Tag','panelOperationPoint');
            
            
            % Make figure visible
            set(fh.figureHandle,'Visible','on');
            
            % Initialize GUI
            
            % Predefine variables that can contain handles to listeners
            angleListenerLeft   = [];
            angleListenerRight  = [];
            zoomListenerLeft    = [];
            zoomListenerRight   = [];
            
            % Predefine variables that contain the plot data for the left and right
            % model
            modelDataLeft       = cell(1,3);
            modelDataRight      = cell(1,3);
            distances           = [];
            
            if numberOfmodels > 0
                flag = checkModelClass(hPopupModel,hPopupModelRight);
                if sum(flag(:,1)) == 2
                    setModelComplexityAndSmoothness(hPopupModel);
                end
                if sum(flag(:,2)) == 2
                    setModelComplexityAndSmoothness(hPopupModelRight);
                end
                updatePopup;
                updateBedienelemente;
                updateDataToBePlotted(hPopupModel,hPopupModelRight);
                makePlot(hPopupModel,hPopupModelRight);
                %     setModelComplexityAndSmoothness(hPopupModel,hPopupModelRight);
            end
            
            %% Functions
            
            function updateLeft(hObject,eventdata,varargin)
                size(eventdata);
                size(hObject);
                
                % Get information about source axes
                viewAngles          = get(hAxesRight,'View');
                cameraViewAngle     = get(hAxesRight,'CameraViewAngle');
                cameraPosition      = get(hAxesRight,'CameraPosition');
                
                % Adopt all settings from the source
                set(hAxesLeft,'View',viewAngles,...
                    'CameraViewAngle',cameraViewAngle,...
                    'CameraPosition',cameraPosition);
                
            end
            
            function updateRight(hObject,eventdata,varargin)
                size(eventdata);
                size(hObject);
                
                % Get information about source axes
                viewAngles          = get(hAxesLeft,'View');
                cameraViewAngle     = get(hAxesLeft,'CameraViewAngle');
                cameraPosition      = get(hAxesLeft,'CameraPosition');
                
                % Adopt all settings from the source
                set(hAxesRight,'View',viewAngles,...
                    'CameraViewAngle',cameraViewAngle,...
                    'CameraPosition',cameraPosition);
                
            end
            
            function updatePopup()
                % Update popup menus
                [names model]       = searchDEL(numberOfmodels,model);
                numberOfmodels      = size(names,1);
                setPopupMenu(names,hPopupModel,numberOfmodels,hSaveModelLeft,...
                    hSaveModelRight,hEditModelLeft,hEditModelRight,...
                    hDeleteModelLeft,hDeleteModelRight,hSmoothnessSliderLeft,...
                    hSmoothnessEditLeft,hModelComplexitySliderLeft,...
                    hModelComplexityEditLeft);
                setPopupMenu(names,hPopupModelRight,numberOfmodels,...
                    hSaveModelLeft,...
                    hSaveModelRight,hEditModelLeft,hEditModelRight,...
                    hDeleteModelLeft,hDeleteModelRight,hSmoothnessSliderRight,...
                    hSmoothnessEditRight,hModelComplexitySliderRight,...
                    hModelComplexityEditRight,hGridResolutionEdit,...
                    hPopupInputDim,hPopupIllustration,hPopupXaxis,hPopupYaxis,...
                    hPopupZaxis,hPushbuttonExport,hCheckBoxTrainDataRight,...
                    hCheckBoxTrainDataLeft,hViewConstrain,...
                    hShowPartitioningRight,hShowPartitioningLeft,hCheckBoxTestDataRight,...
                    hCheckBoxTestDataLeft,hTextDesiredPoints,hEditDesiredPoints,...
                    hSbDesiredPoints);
                
                function [namesNew dataNew] = searchDEL(noElements,data)
                    % Determines all names of the currently available models
                    namesNew = cell(noElements,1);
                    idx      = true(size(namesNew));
                    for ii = 1:noElements
                        if ~isempty(data{ii,1})
                            namesNew{ii,1} = data{ii,1}.info.dataSetDescription;
                        else
                            idx(ii) = false;
                        end
                    end
                    dataNew  = data(idx,:);
                    namesNew = namesNew(idx,:);
                end % end searchDEL
                
                function setPopupMenu(names,hpopup,noElements,varargin)
                    % Puts all names of the available models in the popup menus
                    if isempty(names)
                        names = 'No model available.';
                        set([varargin{:}],'Enable','off');
                    else
                        set([varargin{:}],'Enable','on');
                        DSno = get(hpopup,'Value');
                        if DSno > noElements
                            set(hpopup,'Value',noElements);
                        end
                    end
                    set(hpopup,'String',names);
                end % end setPopupMenu
            end % end updatePopup
            
            function editBrowse(hObject,eventdata)
                % Function reads in LMNs and adds them to the popup menus
                size(eventdata);
                info = get(hObject,'Style');
                % Get the string which contains the path and filename to the
                % mat-file, that is about to be loaded
                if strcmp(info,'edit')
                    text = get(hObject,'String');
                    if isempty(strfind(text,'.'))
                        text = [text,'.mat'];
                    end
                else
                    [file,filepath] = uigetfile('*.mat');
                    if file
                        text = [filepath,file];
                    else
                        % If the user selected no mat-file
                        return;
                    end
                end
                
                % Increase the numberOfmodels
                numberOfmodels = numberOfmodels + 1;
                
                % Save model to the cell-array, which contains all LMNs
                tmp                     = load(text);
                model{numberOfmodels,1} = tmp.model;
                
                
                % Set the model popup menus to the currently read in model
                set([hPopupModel,hPopupModelRight],'Value',numberOfmodels);
                
                % Get the smoothness value as well as the currently chosen number
                % of local models
                flag1 = checkModelClass(hPopupModel,hPopupModelRight);
                if sum(flag1(:,1)) == 2
                    setModelComplexityAndSmoothness(hPopupModel);
                end
                if sum(flag1(:,2)) == 2
                    setModelComplexityAndSmoothness(hPopupModelRight);
                end
                
                
                % Add the chosen model to the popup menus
                updatePopup;
                updateBedienelemente;
                updateDataToBePlotted(hPopupModel,hPopupModelRight);
                makePlot(hPopupModel,hPopupModelRight);
                
            end % end editBrowse
            
            function flag = checkModelClass(varargin)
                % This function checks the seleted model(s) for some
                % properties. Depending on which properties are available,
                % some visualization options of the GUI are activated or
                % deactivated
                %
                % checkModelClass(hPopupmenu1,hPoputmenu2)
                %
                % INPUTS
                %
                % hPopupmenu1:  Handle of one popupmenu that is used to
                %               select a model
                % Up to two handles can be passed.
                %
                % OUTPUTS
                %
                % flag:     [2 x size(varargin,2)] Indicates whether the
                %           the model has the property "smoothness"
                %           (first line of flag is 1) and/or the prperty
                %           "leafModels" (the second line of flag is 1)
                
                % Set Flag to true
                flag = true(2,size(varargin,2));
                
                for jj=1:size(varargin,2)
                    % Determine which Model should be checked (the one in
                    % the left or the one in the right window?)
                    if varargin{jj} == hPopupModel
                        hSmSlider       = hSmoothnessSliderLeft;
                        hSmEdit         = hSmoothnessEditLeft;
                        hMcSlider       = hModelComplexitySliderLeft;
                        hMcEdit         = hModelComplexityEditLeft;
                        hPartitioningButton = hShowPartitioningLeft;
                    else
                        hSmSlider       = hSmoothnessSliderRight;
                        hSmEdit         = hSmoothnessEditRight;
                        hMcSlider       = hModelComplexitySliderRight;
                        hMcEdit         = hModelComplexityEditRight;
                        hPartitioningButton = hShowPartitioningRight;
                    end
                    
                    % Make a temporary copy of the chosen model
                    modelIdx    = get(varargin{jj},'Value');
                    tmpModel    = model{modelIdx,1};
                    
                    % Check the temporary saved model for the property
                    % "smoothness"
                    if isprop(tmpModel,'smoothness')
                        set([hSmSlider,hSmEdit,hPartitioningButton],'Enable','on');
                    else
                        set([hSmSlider,hSmEdit,hPartitioningButton],'Enable','off');
                        flag(1,jj) = false;
                    end
                    
                    % Check temporary saved model for property "leafModels"
                    if isprop(tmpModel,'leafModels')
                        set([hMcSlider,hMcEdit,hPartitioningButton],'Enable','on');
                    else
                        set([hMcSlider,hMcEdit,hPartitioningButton],'Enable','off');
                        flag(2,jj) = false;
                    end
                    
                end
                
            end % end checkModelClass
            
            function setModelComplexityAndSmoothness(varargin)
                % Get the smoothness value as well as the currently chosen number
                % of local models
                %
                %
                % setModelComplexityAndSmoothness(hPopupmenu1,hPopupmenu2,...)
                %
                %
                % INPUT
                %
                % hPopupmenu#:  Handle to popup menu of model 1, 2 or model 1 and 2
                
                
                
                for jj = 1:size(varargin,2)
                    % Determine if smoothness and model complexity should be set
                    % for model 1 or 2
                    if varargin{jj} == hPopupModel
                        hSmSlider       = hSmoothnessSliderLeft;
                        hSmEdit         = hSmoothnessEditLeft;
                        hMcSlider       = hModelComplexitySliderLeft;
                        hMcEdit         = hModelComplexityEditLeft;
                    else
                        hSmSlider       = hSmoothnessSliderRight;
                        hSmEdit         = hSmoothnessEditRight;
                        hMcSlider       = hModelComplexitySliderRight;
                        hMcEdit         = hModelComplexityEditRight;
                    end
                    
                    % Aquire information about the model
                    modelIdx    = get(varargin{jj},'Value');
                    SMvalue     = model{modelIdx,1}.smoothness;
                    MC          = sum(model{modelIdx,1}.leafModels);
                    lmn         = model{modelIdx,1};
                    maxMC       = sum(lmn.history.leafModelIter{end});
                    minMC       = sum(lmn.history.leafModelIter{1});
                    
                    if maxMC == minMC
                        % There is only one global model
                        % A change of the model smoothness will have no
                        % effect to the model, so the element is turned off
                        set([hMcSlider,hSmSlider],'Visible','off','Enable','off');
                    else
                        % There is more than one possible model complexity
                        set(hMcSlider,'Min',minMC,'Max',maxMC,...
                            'SliderStep',[1/size(lmn.history.leafModelIter,2),...
                            3/size(lmn.history.leafModelIter,2)]);
                        set(hMcSlider,'Value',MC,'Enable','on','Visible','on');
                        set(hSmSlider,'Value',SMvalue,'Enable','on','Visible','on');
                    end
                    
                    % Set smoothness and model complexity options
                    set(hSmEdit,'String',num2str(SMvalue),'Enable','on');
                    set(hMcEdit,'String',num2str(MC),'Enable','on');
                end
                
            end % end setModelComplexityAndSmoothness
            
            function updateBedienelemente(hObject,eventdata)
                if nargin > 0
                    size(hObject);
                    size(eventdata);
                else
                    hObject   = [];
                    eventdata = [];
                end
                
                if isempty(model)
                    return;
                end
                value   = get(hPopupModel,'Value');
                input   = model{value,1}.input;
                output  = model{value,1}.output;
                
                % Enable or disable GUI components, that are only enabled, if the
                % input dimensionality is set to 2
                chooseDIM(hObject,eventdata);
                
                % Fill the popup menus, where you can choose the in- and outputs
                % for the x-, y- and z-axis of the plots
                set([hPopupXaxis,hPopupYaxis],'String',...
                    model{value,1}.info.inputDescription);
                set(hPopupZaxis,'String',...
                    model{value,1}.info.outputDescription);
                
                % Check if popup menu values are not greater than the number of
                % inputs respective the number of outputs
                %                 popupvaluesIN  = [get(hPopupXaxis,'Value'),...
                %                     get(hPopupYaxis,'Value');hPopupXaxis,hPopupYaxis];
                %                 popupvaluesOUT = [get(hPopupZaxis,'Value');hPopupZaxis];
                %                 for jj = popupvaluesIN
                %                     if jj(1) > size(input,2)
                %                         set(jj(2),'Value',size(input,2));
                %                     end
                %                 end
                %                 if popupvaluesOUT(1) > size(output,2)
                %                     set(popupvaluesOUT(2),'Value',size(output,2));
                %                 end
                %
                %                 % If the input space is set to 2D, check if x- and y-axis are set
                %                 % to the same input. If so change the chosen input of the y-axis.
                %                 dimDarstellung = get(hPopupInputDim,'Value');
                %                 if popupvaluesIN(1,1) == popupvaluesIN(1,2) && ...
                %                         dimDarstellung == 2
                %                     if popupvaluesIN(1,1) == size(input,2)
                %                         set(hPopupYaxis,'Value',popupvaluesIN(1,2)-1);
                %                     else
                %                         set(hPopupYaxis,'Value',popupvaluesIN(1,2)+1);
                %                     end
                %                 end
                
                
                % Check if popup menu values are not greater than the number of
                % inputs respective the number of outputs
                popupvaluesIN  = {get(hPopupXaxis,'Value'),...
                    get(hPopupYaxis,'Value');hPopupXaxis,hPopupYaxis};
                popupvaluesOUT = {get(hPopupZaxis,'Value');hPopupZaxis};
                for jj = popupvaluesIN
                    if jj{1} > size(input,2)
                        set(jj{2},'Value',size(input,2));
                    end
                end
                if popupvaluesOUT{1} > size(output,2)
                    set(popupvaluesOUT{2},'Value',size(output,2));
                end
                
                % If the input space is set to 2D, check if x- and y-axis are set
                % to the same input. If so change the chosen input of the y-axis.
                dimDarstellung = get(hPopupInputDim,'Value');
                if popupvaluesIN{1,1} == popupvaluesIN{1,2} && ...
                        dimDarstellung == 2
                    if popupvaluesIN{1,1} == size(input,2)
                        set(hPopupYaxis,'Value',popupvaluesIN{1,2}-1);
                    else
                        set(hPopupYaxis,'Value',popupvaluesIN{1,2}+1);
                    end
                end
                % Update the scrollbar, that defines the number of points,
                % that should be displayed. Because of the logarithmic
                % scaling, the maximum number of points is only used to
                % determine the maximum value of the scrollbar. This
                % maximum value has to be greater than one to guarantee the
                % Maximum scrollbar value beeing greater than the minimum.
                maxValue = calculateDesiredPoints(getMaximumPoints,'inverse');
                set(hSbDesiredPoints,'Max',maxValue);
                
                %% Make scrollbars
                % Determine for which inputs there has to be scrollbars
                sb = getSBinputs;
                
                lmn    = model{value,1};
                % Determine the maximum and minimum values of the (denormalized)
                % inputs for the scrollbars
                tmpMin = min(lmn.unscaledInput(:,sb));
                tmpMax = max(lmn.unscaledInput(:,sb));
                
                
                % If the chosen model changes and the number of inputs that
                % need scrollbars, the old components has to be deleted before
                % new ones can be created
                if size(sbBars,1) > 0 && ~isempty(sbBars{1})
                    for ii=1:length(sbBars)
                        delete(sbBars{ii});
                        delete(sbTolEdit{ii});
                        delete(sbBezText{ii});
                        delete(sbTolText{ii});
                        delete(sbValEdit{ii});
                        delete(sbWertText{ii});
                    end
                end
                sbBars     = cell(length(sb),1);
                sbTolEdit  = sbBars;
                sbBezText  = sbBars;
                sbTolText  = sbBars;
                sbValEdit  = sbBars;
                sbWertText = sbBars;
                sbwidth    = 325;
                sbheight   = 20;
                editwidth1 = 100;
                editwidth2 = 40;
                editheight = 20;
                topmargin  = 15;
                zwmargin   = 55;
                sbtextmarg = 20;
                sbtextunte = 15;
                sbpanelpos = get(hPanelOperationPoint,'Position');
                for ii=1:length(sb)
                    yposSB  = sbpanelpos(end)-topmargin-40-(ii-1)*zwmargin;
                    wert    = (tmpMax(ii) + tmpMin(ii))/2;
                    
                    sbWertText{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','text',...
                        'Position',[15 yposSB-sbtextunte 32 15],...
                        'HorizontalAlignment','left',...
                        'String','Value:');
                    
                    sbTolEdit{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','edit',...
                        'Position',[340-editwidth2, yposSB-sbtextunte,...
                        editwidth2, editheight],...
                        'String','33',...
                        'Callback',@editTolerance);
                    
                    sbBezText{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','text',...
                        'Position',[15 yposSB+sbtextmarg 215 15],...
                        'HorizontalAlignment','left',...
                        'String',lmn.info.inputDescription{1,sb(ii)});
                    
                    sbTolText{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','text',...
                        'Position',[335-(editwidth2+48),...
                        yposSB-sbtextunte, 50, 15],...
                        'HorizontalAlignment','left',...
                        'String','Tolerance:');
                    
                    sbValEdit{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','edit',...
                        'Position',[50,...
                        yposSB-sbtextunte,...
                        editwidth1, editheight],...
                        'String',num2str(wert),...
                        'Callback',@updatePlotScrollBarsEdit);
                    
                    sbBars{ii,1} = uicontrol('Parent',hPanelOperationPoint,...
                        'Style','slider',...
                        'Position',[15 yposSB sbwidth sbheight],...
                        'Min',tmpMin(ii),'Max',tmpMax(ii),...
                        'Value',wert,...
                        'Callback',@updatePlotScrollBars);
                    addlistener(sbBars{ii,1},...
                        'ContinuousValueChange',@updatePlotScrollBars);
                end
                set([sbBars{:},sbBezText{:},sbTolText{:},sbWertText{:}],...
                    'BackgroundColor',[.929 .929 .929]);
                set([sbTolEdit{:}],'BackgroundColor',backgroundcolor2);
                
                distances = [];
            end % end updateBedienelemente
            
            function sbInputs = getSBinputs()
                % Chosen inputs for the x- and y-axis
                valueU1 = get(hPopupXaxis,'Value');
                valueU2 = get(hPopupYaxis,'Value');
                
                DSno    = get(hPopupModel,'Value');
                xInputs = 1:size(model{DSno,1}.input,2);
                
                % Input space 1D or 2D?
                dimDarstellung = get(hPopupInputDim,'Value');
                if dimDarstellung == 2
                    achsen = unique([xInputs(valueU1) xInputs(valueU2)]);
                else
                    achsen = xInputs(valueU1);
                end
                sbInputs   = setxor(achsen,xInputs);
            end % end getSBinputs
            
            function chooseDIM(hObject,eventdata)
                size(eventdata);
                % Check if the chosen input dimensionality can be shown with the
                % currently chosen model
                if isempty(model)
                    return;
                else
                    DSno  = get(hPopupModel,'Value');
                    data  = model{DSno,1}.input;
                end
                
                
                if size(data,2) < 1
                    msgbox(['Input dimension of the training data is less ',...
                        'than 1... Aborting!'])
                    return;
                end
                
                % Get the chosen input dimensionality
                dimDarstellung = get(hPopupInputDim,'Value');
                if (size(data,2) < 2 && dimDarstellung == 2)
                    set(hPopupInputDim,'Value',1);
                    set([hPopupYaxis,hPopupIllustration],'Enable','off');
                elseif dimDarstellung == 1
                    set([hPopupYaxis,hPopupIllustration],'Enable','off');
                else
                    set([hPopupYaxis,hPopupIllustration],'Enable','on');
                end
                
                %         if dimDarstellung == 2
                %             set([hAxesLeft,hAxesRight],'View',[-30,40]);
                %         end
                
                % If the change of the illustration popup menu caused the call of
                % this function, there is no need to update other control elements
                if hObject ~= hPopupIllustration
                    updateBedienelemente;
                end
                
                % Function, that updates the plots
                %         updateModelDS(hObject,eventdata);
            end % end chooseDIM
            
            function saveModel(hObject,eventdata)
                size(eventdata);
                
                % Save global variable 'model'
                tmpModel        = model;
                
                % Determine whether the model shown in the left or the right axes
                % should be saved
                if hObject == hSaveModelLeft
                    flag1       = checkModelClass(hPopupModel);
                    value       = get(hPopupModel,'Value');
                    model       = model{value,1};
                    smModel     = get(hSmoothnessSliderLeft,'Value');
                    mcModel     = get(hModelComplexitySliderLeft,'Value');
                elseif hObject == hSaveModelRight
                    flag1       = checkModelClass(hPopupModel);
                    value       = get(hPopupModelRight,'Value');
                    model       = model{value,1};
                    smModel     = get(hSmoothnessSliderRight,'Value');
                    mcModel     = get(hModelComplexitySliderRight,'Value');
                end
                
                if sum(flag1(:,1))==2
                    % Set chosen smoothness and model complexity
                    model.smoothness = smModel;
                    model.leafModels = model.history.leafModelIter{mcModel};
                end
                
                % Save dialog
                [file,filepath] = uiputfile('*.mat');
                if file
                    speichername = [filepath,file];
                else
                    model       = tmpModel;
                    return;
                end
                
                save(speichername,'model');
                model           = tmpModel;
            end % end saveModel
            
            function editModel(hObject,eventdata)
                size(eventdata);
                
                % Determine whether the model shown in the left or the right axes
                % should be edited
                if hObject == hEditModelLeft
                    value       = get(hPopupModel,'Value');
                    %                     LMN         = model{value,1};
                elseif hObject == hEditModelRight
                    value       = get(hPopupModelRight,'Value');
                    %                     LMN         = model{value,1};
                end
                
                model{value,1}  = editModelObject(model{value,1});
                updatePopup;
                updateBedienelemente;
            end % end editModel
            
            function dist = calculateDistances(allPoints,point)
                % This function calculates the distance from the point to
                % all points, that are contained linewise in the matrix
                % allPoints
                
                if size(allPoints,2) == size(point,2)
                    dist = sum(bsxfun(@minus,allPoints,point).^2,2);
                else
                    error('Dimensions does not match. No distance calculation possible.');
                end
                
            end % end calculateDistances
            
            function maximum = getMaximumPoints()
                % Function determines the maximum possible number of
                % points, that can be displayed from a train or test
                % dataset of the currently chosen models
                
                % Get the currently chosen models
                modelIdxLeft = get(hPopupModel,'Value');
                modelIdxRight = get(hPopupModelRight,'Value');
                
                % Define vector containing the indices of the currently
                % chosen models
                modelIdx = unique([modelIdxLeft,modelIdxRight]);
                
                % Initialization of the maximum
                maximum = 0;
                
                % Loop for every model
                for ii = modelIdx
                    lmn = model{ii,1};
                    
                    % If the value of 'maximum' is smaller than the number
                    % of training data, set 'maximum' to the number of
                    % training data
                    if maximum < size(lmn.unscaledInput,1)
                        maximum = size(lmn.unscaledInput,1);
                    end
                    
                    % If the value of 'maximum' is smaller than the number
                    % of test data, set 'maximum' to the number of
                    % test data
                    if ~isempty(lmn.testInput)
                        if maximum < size(lmn.testInput,1)
                            maximum = size(lmn.testInput,1);
                        end
                    end
                    
                end
                
            end % end getMaximumPoints
            
            function setDesiredNumberOfPoints(hObject,eventdata)
                % Callback function for the edit field, where you can set
                % the desired number of points, that should be displayed
                % (train or test data points)
                
                % Get the maximum possible number of points
                sliderValue = get(hSbDesiredPoints,'Max');
                maxNumberOfPoints = calculateDesiredPoints(sliderValue,'normal');
                
                % Read out the desired value
                numberOfDesiredPoints = round(str2double(get(hEditDesiredPoints,'String')));
                if numberOfDesiredPoints < 1
                    numberOfDesiredPoints = 1;
                elseif numberOfDesiredPoints > maxNumberOfPoints
                    numberOfDesiredPoints = maxNumberOfPoints;
                end
                
                set(hEditDesiredPoints,'String',num2str(numberOfDesiredPoints));
                
                set(hSbDesiredPoints,'Value',calculateDesiredPoints(numberOfDesiredPoints,'inverse'));
                updatePlotScrollBars(hObject,eventdata);
                
            end % end setDesiredNumberOfPoints
            
            function output = calculateDesiredPoints(input,flag)
                % This function calculates either the slider value to a given
                % number of desired points or the number of desired points
                % to a given slider value depending on the variable 'flag'
                %
                % output = calculateDesiredPoints(input,flag)
                %
                % INPUTS
                %
                % input         (Scalar): Slider value or desired number of
                %                         points
                %
                % flag          (String): 'inverse' (the slider value is
                %                         calculated) or 'normal' (the
                %                         desired number of points is
                %                         calculated)
                %
                % OUTPUTS
                %
                % output        (Scalar): Slider value or desired number of
                %                         points depending on 'flag'
                
                
                % Obtain the maximum number of points
                maxNumberOfPoints = getMaximumPoints();
                
                % Obtain input dimension
                modelIdxLeft = get(hPopupModel,'Value');
                inputDim = size(model{modelIdxLeft,1}.input,2);
                
                % Factor that guarantees to get the maximum number of
                % points when the slider reaches its maximum value
                m = log(maxNumberOfPoints)/((maxNumberOfPoints)^(1/inputDim));
                
                switch flag
                    case 'inverse'
                        output = log(input)/m;
                    otherwise
                        output = exp(m*input);
                end
                
            end % end calculateDesiredPoints
            
            function [inputData,outputData] = cutOutDefinedNumberOfPoints(inputData,outputData)
                % This function is used to only show the chosen number of
                % points, which are next to the currently selected
                % operating point. More points than the number the user
                % chose are only displayed, if there are several (more than
                % desired) points, that have equal distance to the
                % operating point
                
                %                 numberOfAllPoints = size(inputData,1);
                
                % Obtain currently chosen number of points, that should be
                % displayed
                sliderValue = get(hSbDesiredPoints,'Value');
                desiredPoints = round(calculateDesiredPoints(sliderValue,'normal'));
                set(hEditDesiredPoints,'String',num2str(desiredPoints));
                
                % Obtain operating point
                operatingPoint = zeros(1,size(sbBars,1)); % Pre-define operating point
                for ii = 1:size(sbBars,1)
                    operatingPoint(ii) = get(sbBars{ii,1},'Value');
                end
                
                % Obtain indices of the colums in the data matrix, that
                % determine the operating point
                opIndices = getSBinputs;
                
                % distances contains the maximum distance to either the
                % train or the test dataset (depending on which distance is
                % greater) for every input, that is represented by a slider
                if isempty(distances)
                    distances = zeros(1,size(opIndices,2));
                end
                
                % Calculate all distances of the given inputData-matrix to
                % the operating point
                dist = calculateDistances(inputData(:,opIndices),operatingPoint);
                
                % Sorting the distances in ascending order. Only the
                % indices are of interest, because they are needed to pick
                % out the corresponding points out of the inputData-matrix
                [~,idx] = sort(dist);
                if desiredPoints <= size(dist,1)
                    idx = idx(1:desiredPoints);
                end
                % Check if there are more points in the inputData-matrix,
                % that are as close to the operating point as
                % inputData(idx(end),:)
                tmpIdx = find(dist==dist(idx(end),:));
                
                % Add all indices from tmpIdx to the idx-vector and make
                % sure, that every index only occurs once in the vector
                idx = unique([idx;tmpIdx]);
                
                % Give back the matrix consisting of all data points, that
                % should be displayed
                inputData = inputData(idx,:);
                outputData = outputData(idx,:);
                
                % Calculate greatest distance for every input, that is
                % represented by a slider (to the operating point)
                distance = bsxfun(@minus,inputData(:,opIndices),operatingPoint);
                distance = max(abs(distance),[],1);
                
                for ii = 1:size(opIndices,2)
                    bereich = get(sbBars{ii,1},'Max') - get(sbBars{ii,1},'Min');
                    if distance(ii) > distances(ii)
                        distances(ii) = distance(ii);
                    end
                    value = distances(ii)/bereich*100;
                    set(sbTolEdit{ii,1},'String',num2str(value));
                    %                     maxStep = value/50;
                    %                     minStep = maxStep/3;
                    %                     set(sbBars{ii,1},'SliderStep',[minStep maxStep]);
                end
                
            end % end updateDisplayedPoints
            
            function deleteModel(hObject,eventdata)
                size(eventdata);
                
                % Determine whether the model shown in the left or the right axes
                % should be deleted
                if hObject == hDeleteModelLeft
                    value       = get(hPopupModel,'Value');
                elseif hObject == hDeleteModelRight
                    value       = get(hPopupModelRight,'Value');
                end
                
                % Delete model
                model{value,1}  = [];
                updatePopup;
                
                % Aktualisierung der graphischen Ausgabe
                %         if ~isempty(fh.dataSet)
                %             notify(fh,'GRchange');
                %         end
            end % end deleteModel
            
            function updateDataToBePlotted(varargin)
                % Updates the data to be plotted either of one of the both models
                % or of only one model
                %
                %
                % updateDataToBePlotted(popuphandle1,popuphandle2)
                %
                %
                % INPUT
                %
                % popuphandle1:            Handle to the popup menu where you can
                %                          choose the LMN
                % popuphandle2 (optional): Handle to the popup menu where you can
                %                          choose the LMN
                
                
                % Get common settings
                gridResolution     = str2double(get(hGridResolutionEdit,'String'));
                inputSpace         = get(hPopupInputDim,'Value');
                xAxisIdx           = get(hPopupXaxis,'Value');
                yAxisIdx           = get(hPopupYaxis,'Value');
                zAxisIdx           = get(hPopupZaxis,'Value');
                
                % Determine for which inputs values from the scrollbars are
                % needed
                sb          = getSBinputs;
                sb          = [sb;1:size(sb,2)];
                
                for jj = 1:size(varargin,2)
                    
                    % popup handle of the current run of the loop
                    popuphandle         = varargin{jj};
                    modelIdx            = get(popuphandle,'Value');
                    lmn                 = model{modelIdx,1};
                    
                    % Check if there are properties to be set in the
                    % current model
                    flag1 = checkModelClass(varargin{jj});
                    if sum(flag1(:,1))==2
                        % Set smoothness and model complexity to the values, that are
                        % chosen within the GUI for the corresponding model
                        if varargin{jj} == hPopupModel
                            lmn.smoothness  = str2double(get(hSmoothnessEditLeft,'String'));
                            lmn.leafModels  = ...
                                lmn.history.leafModelIter{1,str2double(get(hModelComplexityEditLeft,'String'))};
                        else
                            lmn.smoothness  = str2double(get(hSmoothnessEditRight,'String'));
                            lmn.leafModels  = ...
                                lmn.history.leafModelIter{str2double(get(hModelComplexityEditRight,'String'))};
                        end
                    end
                    
                    % Input dimension of the model
                    inputDim            = size(lmn.input,2);
                    
                    % Define points per axis
                    xAxis      = linspace(min(lmn.input(:,xAxisIdx)),...
                        max(lmn.input(:,xAxisIdx)),gridResolution);
                    
                    yAxis      = linspace(min(lmn.input(:,yAxisIdx)),...
                        max(lmn.input(:,yAxisIdx)),gridResolution);
                    
                    dimDarstellung = get(hPopupInputDim,'Value');
                    if dimDarstellung == 1
                        % Define input matrix the model output should be evaluated for
                        inputData = zeros(gridResolution,inputDim);
                        inputData(:,xAxisIdx) = xAxis(:);
                    else
                        % Create grid
                        [xGrid yGrid] = meshgrid(xAxis,yAxis);
                        
                        % Define input matrix the model output should be evaluated for
                        inputData   = zeros(gridResolution*gridResolution,inputDim);
                        
                        % Fill the colums for the chosen x- and y-axis (all values
                        % transformed to the normalized codomain)
                        inputData(:,xAxisIdx) = xGrid(:);
                        inputData(:,yAxisIdx) = yGrid(:);
                    end
                    
                    % Denormalize inputData, because all values from the scrollbars
                    % are denormalized
                    if ~isempty(lmn.scaleInput)
                        inputData   = lmn.scaleInput.unscale(inputData);
                    end
                    
                    
                    % Put all scrollbar values in the inputData matrix
                    for ii = sb
                        inputData(:,ii(1)) = get(sbBars{ii(2),1},'Value');
                    end
                    
                    % Evaluation of the LMN output
                    yModel      = lmn.calculateModelOutput(inputData);
                    
                    % Depending of the chosen input space update the data to be
                    % plotted
                    if inputSpace == 1
                        if popuphandle == hPopupModel
                            modelDataLeft{1} = inputData(:,xAxisIdx);
                            modelDataLeft{2} = [];
                            modelDataLeft{3} = yModel(:,zAxisIdx);
                        else
                            modelDataRight{1} = inputData(:,xAxisIdx);
                            modelDataRight{2} = [];
                            modelDataRight{3} = yModel(:,zAxisIdx);
                        end
                    else
                        if popuphandle == hPopupModel
                            modelDataLeft{1} = reshape(inputData(:,xAxisIdx),...
                                gridResolution,gridResolution);
                            modelDataLeft{2} = reshape(inputData(:,yAxisIdx),...
                                gridResolution,gridResolution);
                            modelDataLeft{3} = reshape(yModel(:,zAxisIdx),...
                                gridResolution,gridResolution);
                        else
                            modelDataRight{1} = reshape(inputData(:,xAxisIdx),...
                                gridResolution,gridResolution);
                            modelDataRight{2} = reshape(inputData(:,yAxisIdx),...
                                gridResolution,gridResolution);
                            modelDataRight{3} = reshape(yModel(:,zAxisIdx),...
                                gridResolution,gridResolution);
                        end
                    end
                end % end loop
                
            end % end updateDataToBePlotted
            
            function changeIllustrationStyle(hObject,eventdata)
                makePlot(hPopupModel,hPopupModelRight);
            end
            
            function makePlot(varargin)
                % Function updates the plots in either one or both axis and is able
                % to put the plots into predefined axes outside of the GUI.
                %
                %
                % updatePlot(modelPopup1,modelPopup2)
                %
                %
                % INPUT
                %
                % modelPopup1:      handle to the popup menu which holds the value
                %                   from which line of the variable 'model' the
                %                   data, that should be plotted, has to be
                %                   obtained
                % modelPopup2 (optional):   see modelPopup1
                %
                % modelPopup-inputs can be vectors where the first entry contains
                % the handle to the popup menu and the second entry determines in
                % which axis the data should be plotted
                
                if ~isempty(angleListenerLeft)
                    % Unset model view constrain before updating plots for better
                    % performance
                    delete([angleListenerLeft,angleListenerRight,...
                        zoomListenerLeft,zoomListenerRight]);
                    angleListenerLeft   = [];
                    angleListenerRight  = [];
                    zoomListenerLeft 	= [];
                    zoomListenerRight   = [];
                end
                
                % To guarantee the same scaling for the left and the right
                % axis, both modelIndices are needed
                modelIdxLeft = get(hPopupModel,'Value');
                modelIdxRight = get(hPopupModelRight,'Value');
                Xleft = modelDataLeft{1};
                Xright = modelDataRight{1};
                Yleft = modelDataLeft{2};
                Yright = modelDataRight{2};
                
                for jj = 1:size(varargin,2)
                    modelIdx        = get(varargin{1,jj}(1),'Value');
                    % Determine which axis should be updated
                    if varargin{1,jj}(1) == hPopupModel
                        % Left axis
                        if size(varargin{1,jj},2) > 1
                            currentAxis     = varargin{1,jj}(2);
                        else
                            currentAxis     = hAxesLeft;
                        end
                        plotTrainDataFlag   = ...
                            get(hCheckBoxTrainDataLeft,'Value');
                        plotTestDataFlag    = get(hCheckBoxTestDataLeft,'Value');
                        
                        % Get the data, that should be plotted
                        X       = modelDataLeft{1};
                        Y       = modelDataLeft{2};
                        Z       = modelDataLeft{3};
                    else
                        % Right axis
                        if size(varargin{1,jj},2) > 1
                            currentAxis     = varargin{1,jj}(2);
                        else
                            currentAxis     = hAxesRight;
                        end
                        plotTrainDataFlag   = ...
                            get(hCheckBoxTrainDataRight,'Value');
                        plotTestDataFlag    = get(hCheckBoxTestDataRight,'Value');
                        
                        % Get the data, that should be plotted
                        X       = modelDataRight{1};
                        Y       = modelDataRight{2};
                        Z       = modelDataRight{3};
                    end
                    
                    % Determine maxima and minima for the plot
                    minX    = min([Xleft(:);Xright(:)]);
                    maxX    = max([Xleft(:);Xright(:)]);
                    minY    = min([Yleft(:);Yright(:)]);
                    maxY    = max([Yleft(:);Yright(:)]);
                    
                    % Indices of the in- and outputs within the corresponding
                    % matrices
                    xAxisIdx= get(hPopupXaxis,'Value');
                    yAxisIdx= get(hPopupYaxis,'Value');
                    zAxisIdx= get(hPopupZaxis,'Value');
                    
                    % Get the minimum and maximum value of the chosen output from
                    % the training dataset. It is possible that depending on the
                    % values of the scrollbars not the whole range of the output is
                    % included within the Z matrix. Mind that the training data
                    % might be normalized
                    outputLeft  =  model{modelIdxLeft,1}.unscaledOutput;
                    outputRight = model{modelIdxRight,1}.unscaledOutput;
                    minZ    = min([outputLeft(:,zAxisIdx);outputRight(:,zAxisIdx)]);
                    maxZ    = max([outputLeft(:,zAxisIdx);outputRight(:,zAxisIdx)]);
                    
                    % Plot the data
                    inputSpace      = get(hPopupInputDim,'Value');
                    if inputSpace == 1
                        %                         plot(currentAxis,X,Z,...
                        %                             'LineWidth',linewidth,...
                        %                             'LineStyle',linestyle,...
                        %                             'Marker',marker,...
                        %                             'MarkerSize',markersize)
                        plot(currentAxis,X,Z,...
                            'LineWidth',linewidth,...
                            'LineStyle','-')
                        xlim(currentAxis,[minX maxX]);
                        ylim(currentAxis,[minZ maxZ]);
                        
                        hxlabel     = xlabel(currentAxis,...
                            model{modelIdx,1}.info.inputDescription{xAxisIdx});
                        hylabel     = ylabel(currentAxis,...
                            model{modelIdx,1}.info.outputDescription{zAxisIdx});
                        % hylabel is set to prevent error, when setting the font
                        % style and font size of the current axis
                        hzlabel     = hylabel;
                        
                        % Plot the training data points within the defined
                        % tolerance
                        if plotTrainDataFlag
                            hold(currentAxis,'on');
                            plotTrainData(xAxisIdx,[],zAxisIdx,...
                                model{modelIdx,1},currentAxis,'train');
                            hold(currentAxis,'off');
                        else
                            datenAusschneiden([model{modelIdx,1}.input model{modelIdx,1}.output]);
                        end
                        
                        % Plot the test data points within the defined
                        % tolerance
                        if plotTestDataFlag
                            hold(currentAxis,'on');
                            plotTrainData(xAxisIdx,[],zAxisIdx,...
                                model{modelIdx,1},currentAxis,'test');
                            hold(currentAxis,'off');
                        end
                        
                    elseif inputSpace == 2
                        % Save camera position of the plot
                        CamPos      = get(currentAxis,'View');
                        cameraViewAngle = get(currentAxis,'CameraViewAngle');
                        
                        % Determine what kind of illustration is desired by the
                        % user
                        illustrationIdx     = get(hPopupIllustration,'Value');
                        illustrationCell    = get(hPopupIllustration,'String');
                        illustration        = illustrationCell{illustrationIdx};
                        switch illustration
                            case 'surf'
                                surf(currentAxis,X,Y,Z);
                            case 'mesh'
                                hmesh=mesh(currentAxis,X,Y,Z);
                                set(hmesh,'FaceColor','none');
                            case 'plot3'
                                set(gcf,'CurrentAxes',currentAxis);
                                plot3(X(:),Y(:),Z(:),...
                                    'LineWidth',linewidth,...
                                    'LineStyle',linestyle,...
                                    'Marker',marker,...
                                    'MarkerSize',markersize);
                        end
                        xlim(currentAxis,[minX maxX]);
                        ylim(currentAxis,[minY maxY]);
                        zlim(currentAxis,[minZ maxZ]);
                        
                        hxlabel     = xlabel(currentAxis,...
                            model{modelIdx,1}.info.inputDescription{xAxisIdx});
                        hylabel     = ylabel(currentAxis,...
                            model{modelIdx,1}.info.inputDescription{yAxisIdx});
                        hzlabel     = zlabel(currentAxis,...
                            model{modelIdx,1}.info.outputDescription{zAxisIdx});
                        
                        % If the model has not been changed, keep the camera
                        % position
                        if ~isequal(CamPos(1:2),[0.0 90])
                            set(currentAxis,'View',CamPos);
                            set(currentAxis,'CameraViewAngle',cameraViewAngle);
                        end
                        
                        % Plot the training data points within the defined
                        % tolerance
                        if plotTrainDataFlag
                            hold(currentAxis,'on');
                            plotTrainData(xAxisIdx,yAxisIdx,zAxisIdx,...
                                model{modelIdx,1},currentAxis,'train');
                            hold(currentAxis,'off');
                        else
                            datenAusschneiden([model{modelIdx,1}.input model{modelIdx,1}.output]);
                        end
                        
                        % Plot the test data points within the defined
                        % tolerance
                        if plotTestDataFlag
                            hold(currentAxis,'on');
                            plotTrainData(xAxisIdx,yAxisIdx,zAxisIdx,...
                                model{modelIdx,1},currentAxis,'test');
                            hold(currentAxis,'off');
                        end
                        
                    end % end if inputSpace
                    
                    % Set font family and font size of the current axis
                    set([hxlabel,hylabel,hzlabel,currentAxis],...
                        'FontSize',fontsize,'FontName',fontname);
                    
                    % Be sure the grid of the plots is set to on and the background
                    % color keeps the same
                    grid(currentAxis,'on');
                    set(currentAxis,'Color',backgroundcolor2);
                    
                end % end run of the loop
                
                % Get checkbox value, which determines whether the views of the
                % two models are constrained or not
                value       = get(hViewConstrain,'Value');
                
                % If checkbox is checked, set the listeners. Listeners must
                % be set after the plots are generated!!
                if value && inputSpace == 2
                    angleListenerLeft   = addlistener(hAxesLeft,'View',...
                        'PostSet',@updateRight);
                    angleListenerRight  = addlistener(hAxesRight,...
                        'View','PostSet',@updateLeft);
                    zoomListenerLeft    = ...
                        addlistener(hAxesLeft,'CameraViewAngle',...
                        'PostSet',@updateRight);
                    zoomListenerRight   = ...
                        addlistener(hAxesRight,'CameraViewAngle',...
                        'PostSet',@updateLeft);
                end
                
            end % end makePlot
            
            function updatePlotScrollBars(hObject,eventdata)
                size(hObject);
                size(eventdata);
                
                distances = [];
                updateDataToBePlotted(hPopupModel,hPopupModelRight);
                makePlot(hPopupModel,hPopupModelRight);
                
                for ii=1:size(sbBars,1)
                    value   = get(sbBars{ii,1},'Value');
                    set(sbValEdit{ii,1},'String',num2str(value));
                end
                
                % Update displayed operating point
                %                 if strcmp('double',class(hObject))
                %                     [~,editIdx,~] = intersect([sbBars{:}],hObject);
                %                     if ~isempty(editIdx)
                %                         set(sbValEdit{editIdx,1},'String',num2str(get(sbBars{editIdx,1},'Value')));
                %                     end
                %                 end
                %                 value   = get(sbBars{ii,1},'Value');
                %                     set(sbValEdit{ii,1},'String',num2str(value));
                
            end % end updatePlot
            
            function updatePlot(hObject,eventdata)
                size(hObject);
                size(eventdata);
                
                updatePopup;
                updateBedienelemente;
                updateDataToBePlotted(hPopupModel,hPopupModelRight);
                makePlot(hPopupModel,hPopupModelRight);
            end % end updatePlot
            
            function data = datenAusschneiden(data)
                % Get data near the operating point. Mind that all scrollbar values
                % are NOT normalized
                for ii = 1:size(sbBars,1)
                    tol     = str2double(get(sbTolEdit{ii,1},'String'));
                    tmpMin  = get(sbBars{ii,1},'Min');
                    tmpMax  = get(sbBars{ii,1},'Max');
                    bereich = tmpMax-tmpMin;
                    tol     = tol/100*bereich; % absolute value
                    value   = get(sbBars{ii,1},'Value');
                    % Cut all data out, that is smaller than the current value of
                    % the scrollbar minus the half range of the tolerance
                    sb      = getSBinputs;
                    idx     = data(:,sb(ii)) > (value-tol);
                    data    = data(idx,:);
                    % Cut all data out, that is larger than the current value of
                    % the scrollbar plus the half range of the tolerance
                    idx     = data(:,sb(ii)) < (value+tol);
                    data    = data(idx,:);
                end
            end % end datenAusschneiden
            
            function plotTrainData(drx,dry,drz,lmn,currentAxis,dataType)
                % Plots training data to a defined axis
                %
                % plotTrainData(drx,dry,drz,lmn,currentAxis)
                %
                % INPUT
                %
                %
                
                switch dataType
                    case 'train'
                        if ~isempty(lmn.input) && ~isempty(lmn.output)
                            % Denormalization is neccessary because all values of the
                            % scrollbars, that are used to cut out data outside the tolerance
                            % are not normalized
                            input       = lmn.unscaledInput;
                            output      = lmn.unscaledOutput;
                            
                            dataColor = [1 0 0];
                        end
                    case 'test'
                        if ~isempty(lmn.testInput) && ~isempty(lmn.testOutput)
                            % If test data should be plotted
                            input = lmn.testInput;
                            output = lmn.testOutput;
                            
                            dataColor = [0 .8 0];
                        end
                end
                if exist('input','var')
                    displayDesiredPoints = get(hTextDesiredPoints,'Value');
                    if displayDesiredPoints == 1
                        % Cut out all data except for the disired number of
                        % data points, that should be displayed
                        [input,output] = cutOutDefinedNumberOfPoints(input,output);
                    else
                        % Cut out all data outside the tolerance
                        tmp         = datenAusschneiden([input output]);
                        input       = tmp(:,1:size(input,2));
                        output      = tmp(:,size(input,2)+1:end);
                    end
                    
                    % Plot the data points
                    if isempty(dry)
                        % 1D input space
                        plot(currentAxis,input(:,drx),output(:,drz),...
                            'LineWidth',linewidth,'LineStyle',linestyle,...
                            'Marker',marker,'MarkerSize',markersize,...
                            'color',[1 0 0]);
                    else
                        % 2D input space
                        set(gcf,'CurrentAxes',currentAxis);
                        plot3(input(:,drx),input(:,dry),output(:,drz),...
                            'LineWidth',linewidth,'LineStyle',linestyle,...
                            'Marker',marker,'MarkerSize',markersize,...
                            'color',dataColor);
                    end
                end
            end % end plotTrainData
            
            function updatePlotScrollBarsEdit(hObject,eventdata)
                size(eventdata);
                [~,editIdx,~] = intersect([sbValEdit{:}],hObject);
                set(sbBars{editIdx},'Value',...
                    str2double(get(hObject,'String')));
                updatePlotScrollBars(hObject,eventdata);
            end % end updatePlotScrollBarsEdit
            
            function chooseModel(hObject,eventdata)
                % Function proofs if the newly chosen model has the same number of
                % inputs and the same number of outputs as the one that is kept the
                % same. If this proof is passed the corresponding plot is updated.
                size(eventdata);
                size(hObject);
                
                % Get the currently chosen models
                modelIdxLeft        = get(hPopupModel,'Value');
                modelIdxRight       = get(hPopupModelRight,'Value');
                lmnLeft             = model{modelIdxLeft,1};
                lmnRight            = model{modelIdxRight,1};
                
                % Check equality of the size of the input spaces
                if size(lmnLeft.input,2) ~= size(lmnRight.input,2)
                    errorMessage('input');
                    return;
                end
                
                % Check equality of the size of the output spaces
                if size(lmnLeft.output,2) ~= size(lmnRight.output,2)
                    errorMessage('output');
                    return;
                end
                
                % Update plot
                updateBedienelemente;
                flag1 = checkModelClass(hPopupModel,hPopupModelRight);
                if sum(flag1(:,1)) == 2
                    setModelComplexityAndSmoothness(hPopupModel);
                end
                if sum(flag1(:,2)) == 2
                    setModelComplexityAndSmoothness(hPopupModelRight);
                end
                
                updateDataToBePlotted(hPopupModel,hPopupModelRight);
                makePlot(hPopupModel,hPopupModelRight);
                
                % Error message, if the size of the in- or output space does not
                % match
                function errorMessage(flag)
                    switch flag
                        case 'input'
                            msgbox(['Size of the input spaces of the chosen ',...
                                'models does not match. Plots will be ',...
                                'updated as soon as the size of the input ',...
                                'spaces match again.'],'Error','error');
                        case 'output'
                            msgbox(['Size of the output spaces of the chosen ',...
                                'models does not match. Plots will be ',...
                                'updated as soon as the size of the output ',...
                                'spaces match again.'],'Error','error');
                    end
                end % end errorMessage
            end % end chooseModel
            
            function exportFigures(hObject,eventdata)
                % Opens new figure an puts the two plots from the GUI into two
                % subplots within the new figure
                size(hObject);
                size(eventdata);
                
                if isempty(model)
                    msgbox(['At least there has to be one model already read ',...
                        'in to export the figures.'],'Error','error');
                    return;
                end
                
                % Create new figure and axes
                widthTmp    = 800;
                heightTmp   = 600;
                positionTmp = [(scrsize(3) - widthTmp)/2, ...
                    (scrsize(4) - heightTmp)/2, widthTmp, heightTmp];
                hExportedFigure = figure;
                set(hExportedFigure,'Position',positionTmp)
                axLeft      = subplot(1,2,1);
                axRight     = subplot(1,2,2);
                
                % Get camera position and view angle from the already existing
                % plots
                viewLeft                = get(hAxesLeft,'View');
                cameraViewAngleLeft     = get(hAxesLeft,'CameraViewAngle');
                cameraPositionLeft      = get(hAxesLeft,'CameraPosition');
                viewRight               = get(hAxesRight,'View');
                cameraViewAngleRight    = get(hAxesRight,'CameraViewAngle');
                cameraPositionRight     = get(hAxesRight,'CameraPosition');
                
                % Make plots
                makePlot([hPopupModel axLeft],[hPopupModelRight axRight]);
                
                % Set camera position and view angle
                set(axLeft,'View',viewLeft,...
                    'CameraViewAngle',cameraViewAngleLeft,...
                    'CameraPosition',cameraPositionLeft);
                set(axRight,'View',viewRight,...
                    'CameraViewAngle',cameraViewAngleRight,...
                    'CameraPosition',cameraPositionRight);
                
                % Determine string elements for titles
                modelIdxLeft        = get(hPopupModel,'Value');
                modelIdxRight       = get(hPopupModelRight,'Value');
                
                cellStringLeft      = get(hPopupModel,'String');
                cellStringRight     = get(hPopupModelRight,'String');
                
                modelNameLeft       = cellStringLeft{modelIdxLeft};
                modelNameRight      = cellStringRight{modelIdxRight};
                
                MCleft              = get(hModelComplexityEditLeft,'String');
                MCright             = get(hModelComplexityEditRight,'String');
                
                SMleft              = get(hSmoothnessEditLeft,'String');
                SMright             = get(hSmoothnessEditRight,'String');
                
                % Make titles for plots
                htLeft      = title(axLeft,{modelNameLeft,...
                    ['Number of local models: ',MCleft],...
                    ['Smoothness: ',SMleft]});
                htRight     = title(axRight,{modelNameRight,...
                    ['Number of local models: ',MCright],...
                    ['Smoothness: ',SMright]});
                
                set([htLeft,htRight],'FontName',fontname,'FontSize',fontsize);
                
            end % end exportFigures
            
            function constrainView(hObject,eventdata)
                % Set or unset the constrain between the model views
                size(hObject);
                size(eventdata);
                
                % Get checkbox value
                value       = get(hViewConstrain,'Value');
                
                if ~value
                    delete([angleListenerLeft,angleListenerRight,...
                        zoomListenerLeft,zoomListenerRight]);
                    angleListenerLeft   = [];
                    angleListenerRight  = [];
                    zoomListenerLeft 	= [];
                    zoomListenerRight   = [];
                end
                
                % Update plots
                makePlot(hPopupModel,hPopupModelRight);
            end % end Right
            
            function changeSmoothnessLeft(hObject,eventdata)
                size(eventdata);
                
                if hObject == hSmoothnessEditLeft
                    % Get desired value of the smoothness
                    value       = str2double(get(hObject,'String'));
                    set(hSmoothnessSliderLeft,'Value',value);
                elseif hObject == hSmoothnessSliderLeft
                    % Get desired value of the smoothness
                    value       = get(hObject,'Value');
                    set(hSmoothnessEditLeft,'String',num2str(value));
                else
                    % Function is called by the continousValueChange-event
                    % Get desired value from the slider
                    value       = get(hSmoothnessSliderLeft,'Value');
                    set(hSmoothnessEditLeft,'String',num2str(value));
                end
                
                % Update data to be plotted (within that function the smoothness of
                % the slider will be used to calculate the model output)
                updateDataToBePlotted(hPopupModel);
                
                % Update plot
                makePlot(hPopupModel);
                
            end % end changeSmoothnessLeft
            
            function changeSmoothnessRight(hObject,eventdata)
                size(eventdata);
                
                if hObject == hSmoothnessEditRight
                    % Get desired value of the smoothness
                    value       = str2double(get(hObject,'String'));
                    set(hSmoothnessSliderRight,'Value',value);
                elseif hObject == hSmoothnessSliderRight
                    % Get desired value of the smoothness
                    value       = get(hObject,'Value');
                    set(hSmoothnessEditRight,'String',num2str(value));
                else
                    % Function is called by the continousValueChange-event
                    % Get desired value of the slider
                    value       = get(hSmoothnessSliderLeft,'Value');
                    set(hSmoothnessEditLeft,'String',num2str(value));
                end
                
                % Update data to be plotted (within that function the smoothness of
                % the slider will be used to calculate the model output)
                updateDataToBePlotted(hPopupModelRight);
                
                % Update plot
                makePlot(hPopupModelRight);
                
            end % end changeSmoothnessLeft
            
            function changeModelComplexityLeft(hObject,eventdata)
                size(eventdata);
                
                % Get currently chosen model
                modelIdx        = get(hPopupModel,'Value');
                lmn             = model{modelIdx,1};
                
                % determine which GUI-component has called this function
                if hObject == hModelComplexitySliderLeft
                    modelComplexity     = get(hModelComplexitySliderLeft,'Value');
                elseif hObject == hModelComplexityEditLeft
                    modelComplexity     = ...
                        str2double(get(hModelComplexityEditLeft,'String'));
                end
                
                % make sure, that the desired model complexity is always an
                % integer and is not larger than the maximum model complexity
                if modelComplexity < 1
                    modelComplexity = 1;
                elseif modelComplexity > size(lmn.history.leafModelIter,2)
                    modelComplexity = size(lmn.history.leafModelIter,2);
                else
                    modelComplexity = round(modelComplexity);
                end
                set(hModelComplexityEditLeft,'String',...
                    num2str(modelComplexity));
                set(hModelComplexitySliderLeft,'Value',modelComplexity);
                
                % update graphical representation
                updateDataToBePlotted(hPopupModel);
                
                % Update plot
                makePlot(hPopupModel);
                
            end % end changeModelComplexityLeft
            
            function changeModelComplexityRight(hObject,eventdata)
                size(eventdata);
                
                % Get currently chosen model
                modelIdx        = get(hPopupModelRight,'Value');
                lmn             = model{modelIdx,1};
                
                % determine which GUI-component has called this function
                if hObject == hModelComplexitySliderRight
                    modelComplexity     = get(hModelComplexitySliderRight,'Value');
                elseif hObject == hModelComplexityEditRight
                    modelComplexity     = ...
                        str2double(get(hModelComplexityEditRight,'String'));
                end
                
                % make sure, that the desired model complexity is always an
                % integer and is not larger than the maximum model complexity
                if modelComplexity < 1
                    modelComplexity = 1;
                elseif modelComplexity > size(lmn.history.leafModelIter,2)
                    modelComplexity = size(lmn.history.leafModelIter,2);
                else
                    modelComplexity = round(modelComplexity);
                end
                set(hModelComplexityEditRight,'String',...
                    num2str(modelComplexity));
                set(hModelComplexitySliderRight,'Value',modelComplexity);
                
                % update graphical representation
                updateDataToBePlotted(hPopupModelRight);
                
                % Update plot
                makePlot(hPopupModelRight);
                
            end % end changeModelComplexityRight
            
            function showPartitioning(hObject,eventdata)
                size(eventdata);
                
                if hObject == hShowPartitioningLeft
                    modelIdx    = get(hPopupModel,'Value');
                    hpopuptmp   = hPopupModel;
                    smModel     = get(hSmoothnessSliderLeft,'Value');
                    mcModel     = get(hModelComplexitySliderLeft,'Value');
                    
                else
                    modelIdx    = get(hPopupModelRight,'Value');
                    hpopuptmp   = hPopupModelRight;
                    smModel     = get(hSmoothnessSliderRight,'Value');
                    mcModel     = get(hModelComplexitySliderRight,'Value');
                end
                
                % Set model object options
                lmn             = model{modelIdx,1};
                lmn.smoothness  = smModel;
                lmn.leafModels  = lmn.history.leafModelIter{mcModel};
                
                % Show partitioning
                lmn         = GUIvisualize.plotPartitionGUI(lmn);
                
                % Change smoothness and model complexity
                model{modelIdx,1}.smoothness    = lmn.smoothness;
                model{modelIdx,1}.leafModels    = lmn.leafModels;
                
                % Update edit fields and slider to the chosen model complexity and
                % smoothness
                flag1 = checkModelClass(hpopuptmp);
                if sum(flag1(:,1))==2
                    setModelComplexityAndSmoothness(hpopuptmp);
                end
                
                % Update plot
                updateDataToBePlotted(hpopuptmp);
                makePlot(hpopuptmp);
                
            end % end showPartitioning
            
            function editTolerance(hObject,eventdata)
                size(hObject);
                size(eventdata);
                
                makePlot(hPopupModel,hPopupModelRight);
            end % end editTolerance
            
            function reposElements(hObject,eventdata)
                size(hObject);
                if strcmp(eventdata.Key,'r')
                    hList1     = [get(fh.figureHandle,'children');...
                        get(hPanelModel1,'children');...
                        get(hPanelBothModels,'children')];
                    set(hList1,'Visible','on');
                    reposGUIelements(hList1,fh.figureHandle);
                end
            end % end reposElements
        end % end constructor
    end % end methods
    
    methods(Static=true)
        
        modelObject = plotPartitionGUI(modelObject);
        phi         = calculateValidityFunctionAllClasses(modelObject,zRegressor);
        
    end
    
end

