% Classifier, which takes binary Classifiers as input.
% Note: The patterns of different classifiers must(!) exactly be the same,
% there will bin no check.
classdef janis_ensemble_majorityVote < janis_classifier


    methods (Static)
        function shortName = name
            shortName = 'Classifier Ensemble: Majority Vote';
        end
        % special classifier, needs special setup, should not appear in
        % default list of classifiers
        function beVisbile = shouldBeVisible
            beVisbile = false;
        end
    end

    methods
        % For ensemble: trainPatterns are validators (any kind)
        function this = train(this,trainPatterns,trainLabels)
            classifierStruct.trainPatterns = trainPatterns;
            classifierStruct.trainLabels = trainLabels';
            this.classifierStruct = classifierStruct;
        end
        % testPatterns: indices of Patterns to test (which MUST be the same
        % in each classifier.

        function [predictions decFactors] = test(this,testPatterns)
            performances = cell(size(this.classifierStruct.trainPatterns,2));
            predictions = [];
            % for every classifier compute predicitions of specified
            % testPatterns.
            for valis=1:size(this.classifierStruct.trainPatterns,2)
                performances{valis} = this.classifierStruct.trainPatterns{valis}.computeForSubjects(testPatterns);
                predictions = [predictions; this.classifierStruct.trainPatterns{valis}.predicted(end,:)];
            end
            %resTemp = sum(predictions)/size(predictions,1);
            for sub=1:size(predictions,2)
                observed = unique(predictions(:,sub));     % observed predictions, unique
                [n,bins] = hist(double(predictions(:,sub)),double(observed));
                maxObs = max(n);               % maximal observation
                maxVals = bins(n==maxObs);
                % stupid fix for hist, which will not do anything for only
                % one value - grml hmpf
                if isempty(maxVals) && length(observed) == 1
                    maxVals = observed;
                end
                if (size(maxVals,1)>1)
                    meanDec = mean(performances{end,1}.decFactors(end).decVals);
                    if length(meanDec) < 3
                        resTemp(1,sub) = int32(mean(performances{end,1}.decFactors(end).decVals) > 0);
                    else
                        [val loc] = max(meanDec);
                        resTemp(1,sub) = loc;
                        warning('Patt situation in Multiclass - decision handling extremely experimental!');
                    end
                    warning('Patt situation - will decide on decision values instead of labels');
                else
                    resTemp(1,sub) = maxVals;
                end
                % decVals (fake, not for multiple stuff!)
                decFactors.decVals(sub) = mean((predictions(:,sub)-0.5)*2);
            end
            predictions = resTemp';
        end

        % return the classifierStruct (cell of validators)
        function classifierStruct  = getClassifier(this,trainPatterns,trainLabels)
            classifierStruct.trainPatterns = trainPatterns;
            classifierStruct.trainLabels = trainLabels;
        end

        % nothing to configure here
        function jc = uiconfigure(this)
            msgbox('Nothing to configure here.');
        end


        % show setup
        function show(this)
            show@janis_classifier(this);
        end
    end
end