function [markerHandle,lineHandle] = plotOutputOverMeasuredData(obj,inputCombination,measuredInput,measuredOutput,axesHandle,markerColor,plotOptionObject)

%%

if ~exist('plotOptionObject','var') || isempty(plotOptionObject)
%     plotOptionObject = PlotOptions;
end

% Load plot options
% fontName = plotOptionObject.fontname;
% fontSize = plotOptionObject.fontsize;
% linewidth = plotOptionObject.linewidth;
% markerSize = plotOptionObject.markersize;
[fontName,fontSize,linewidth] = sensitivityAnalysis.getPlotOptions;
markerSize = 12;

% Check if it is possible to create the demanded plot, otherwise abort
if isempty(obj.input)
    error('The object has neither any training data nor an input selection happened previously. So no visualization is possible right now.');
end

% Check if there is an inputCombination vector passed. If not use all
% available inputs to create the plot
if ~exist('inputCombination','var') || isempty(inputCombination)
    inputCombination = true(1,size(obj.input,2));
end

% Check if there is an markerColor passed
if ~exist('markerColor','var') || isempty(markerColor)
    markerColor = [1 0 0];
end

% Check if arguments for the measured in- and output has been passed to
% this function
if ~exist('measuredInput','var') || isempty(measuredInput)
    measuredInput = obj.unscaledInput;
end
if ~exist('measuredOutput','var') || isempty(measuredOutput)
    measuredOutput = obj.unscaledOutput;
end

% There must be the same number of samples in the measured input as in the
% measured output
if size(measuredOutput,1) ~= size(measuredInput,1)
    error('The number of samples of the measured in- and output differs. Please check your passed variables.');
end

% Check if the number of inputs of the measured data matches the number of
% inputs contained in the inputCombination vector. If necessary use
% inputCombination to create the input matrix for the model output
% evaluation
if size(measuredInput,2) == size(inputCombination,2)
    % The passed (measured) input dimension is equal to the 
    % input dimension of the training data set of
    % the model object with all possible inputs
    measuredInput = measuredInput(:,inputCombination);
    
elseif size(measuredInput,2) == sum(inputCombination)
    % The passed (measured) input dimension equals the dimension that the
    % reduced model has
    
    % In this case nothing has to be done, because the measuredInput-matrix
    % can be used as it is passed.
    
else
    % No matching of the previous checkings indicate a misstake in the 
    % passing of variables
    error('The dimensionality of the passed (measured) inputs does not match the demanded number of inputs within the inputCombination vector.');
end

% Choose the model, that should be used to calculate the output on the
% measured inputs
if size(obj.sensitivityResults,2) == 0
    % If there are no sensitivityResults, train the object on the training
    % data with the demanded inputs contained in the inputCombination
    % vector with the standard options.
    lmn = deleteAndRetrainNet(obj,inputCombination);
    
else
    % Look for the inputCombination vector within the combinationMatrix of
    % the object
    idx = find(sum(bsxfun(@eq,obj.combinationMatrix,inputCombination),2)==size(inputCombination,2));
    
    if isempty(idx)
        % THIS SECTION SHOULD BE OUTSOURCED INTO A SINGLE FUNCTION
        lmn = deleteAndRetrainNet(obj,inputCombination);
        
    else
        % If the demanded input combination has been performed in an former
        % input selection, pick the corresponding hilomot-model
        lmn = obj.sensitivityResults.model{1,idx};
        
    end
    
end

% % If there was a previous input scaling, the input scaling parameters do
% % not match the number of reduced inputs
% if ~isempty(lmn.scaleInput)
%     adaptedScaling = scaleData;
%     adaptedScaling.method = lmn.scaleInput.method;
%     
%     % Currently works only with the unitVarianceScaling !!!!!!!!!!!
%     adaptedScaling.parameter.mean = lmn.scaleInput.parameter.mean(inputCombination);
%     adaptedScaling.parameter.std = lmn.scaleInput.parameter.std(inputCombination);
%     
%     lmn.scaleInput = adaptedScaling;
% end

% Now calculate the model output to the measuredInput-matrix
yHat = lmn.calculateModelOutput(measuredInput);

% May be used in case there is an axis specified for the plot output
formerMin = inf;
formerMax = -inf;

% Create plot
if exist('axesHandle','var')
    ah = axesHandle;
    hold(ah,'on');
    
    % Check if there is already something plotted in the passed axis
    handles = get(ah,'Children');
    
    for jj=1:size(handles,1)
        % If there is already a line element, save the XData and delete it
        tmp = get(handles(jj)); % Create structure
        
        % Check if children is of type line
        if strcmp(tmp.Tag,'LINE')
            formerMin = min([tmp.XData formerMin]);
            formerMax = max([tmp.XData formerMax]);
            
            % Delete the line (later on a new one will be created)
            delete(handles(jj));
        end
        
    end
    
else
    fh = figure;
    ah = axes;
    set(fh,'CurrentAxes',ah);
end

% Evaluate min and max values for x- and y-axis
minBothAxes = min([measuredOutput;yHat;formerMin]);
maxBothAxes = max([measuredOutput;yHat;formerMax]);
bereich = maxBothAxes-minBothAxes;
minBothAxes = minBothAxes-0.07*bereich;
maxBothAxes = maxBothAxes+0.07*bereich;

set(gcf,'CurrentAxes',ah);
hl = line([minBothAxes maxBothAxes],[minBothAxes maxBothAxes]);
set(hl,'LineWidth',linewidth/2,'LineStyle','--','Color',[0 0 0],'Tag','LINE')
hold(ah,'on');
lineHandle = hl;

markerHandle = plot(ah,measuredOutput(:,1),yHat,'LineWidth',linewidth,...
    'LineStyle','none','Marker','.','MarkerSize',markerSize,'Color',markerColor);

set(ah,'XLim',[minBothAxes maxBothAxes],'YLim',[minBothAxes maxBothAxes],'Box','on');
grid(ah,'on')

hx = xlabel(ah,'Measured output');
hy = ylabel(ah,'Model output');

set([ah,hx,hy],'FontName',fontName,'FontSize',fontSize)


    function netz = deleteAndRetrainNet(netz,combination)
        % Delete training, if there has been one before
        netz.history         = modelHistory;
        netz.leafModels      = [];
        netz.localModels     = [];
        netz.outputModel     = [];
        netz.xRegressor      = [];
        netz.zRegressor      = [];
        if isprop(netz,'phi')
            netz.phi = [];
        end
        if isprop(netz,'MSFValue')
            netz.MSFValue = {[]};
        end
        netz.testInput = [];
        netz.testOutput = [];
        netz.validationInput = [];
        netz.validationOutput = [];
        % In- and output scaling has to be deleted, to guarantee that the
        % number of parameters is equal to the number of inputs
        if ~isempty(netz.scaleInput)
            scaleMethod = netz.scaleInput.method;
            netz.scaleInput = [];
            netz.inputScalingComplete = false;
            netz.scaleInput = scaleData;
            netz.scaleInput.method = scaleMethod;
        end
        if ~isempty(netz.scaleOutput)
            scaleMethod = netz.scaleOutput.method;
            netz.scaleOutput = [];
            netz.outputScalingComplete = false;
            netz.scaleOutput = scaleData;
            netz.scaleOutput.method = scaleMethod;
        end
        
        % Pass the training data to the model object and start the training
        netz.input = netz.input(:,combination);
        netz = netz.train(false);
    end

end
