function outclass = svmclassify(svmStruct,sample, varargin)
%SVMCLASSIFY classifies data using a support vector machine
%
%   GROUP = SVMCLASSIFY(SVMStruct,SAMPLE) classifies each row of the data
%   in SAMPLE using the information in a support vector machine classifier
%   structure SVMStruct created using SVMTRAIN. SAMPLE must have the same
%   number of columns as the data used to train the classifier in SVMTRAIN.
%   GROUP indicates the group to which each row of SAMPLE is assigned.
%
%   SVMCLASSIFY(...,'SHOWPLOT',true) plots the sample data on the figure
%   created using the SHOWPLOT option in SVMTRAIN.
%
%   Example:
%       % Load the data and select features for classification
%       load fisheriris
%       data = [meas(:,1), meas(:,2)];
%       % Extract the Setosa class
%       groups = ismember(species,'setosa');
%       % Randomly select training and test sets 
%       [train, test] = crossvalind('holdOut',groups);
%       cp = classperf(groups);
%       % Use a linear support vector machine classifier
%       svmStruct = svmtrain(data(train,:),groups(train),'showplot',true);
%       classes = svmclassify(svmStruct,data(test,:),'showplot',true);
%       % See how well the classifier performed
%       classperf(cp,classes,test);
%       cp.CorrectRate
%
%   See also CLASSIFY, KNNCLASSIFY, QUADPROG, SVMTRAIN.

%   Copyright 2004 The MathWorks, Inc.
%   $Revision: 1.1.12.1 $  $Date: 2004/12/24 20:43:34 $

%   References:
%     [1] Kecman, V, Learning and Soft Computing,
%         MIT Press, Cambridge, MA. 2001.
%     [2] Suykens, J.A.K., Van Gestel, T., De Brabanter, J., De Moor, B.,
%         Vandewalle, J., Least Squares Support Vector Machines,
%         World Scientific, Singapore, 2002.
%     [3] Scholkopf, B., Smola, A.J., Learning with Kernels,
%         MIT Press, Cambridge, MA. 2002.

% set defaults


plotflag = false;

% check inputs
if nargin < 2
    error(nargchk(2,Inf,nargin))
end

% deal with struct input case
if ~isstruct(svmStruct)
    error('Bioinfo:svmclassify:TwoInputsNoStruct',...
        'The first input should be a struct generated by SVMTRAIN.');
end


% deal with the various inputs
if nargin > 2
    if rem(nargin,2) == 1
        error('Bioinfo:svmclassify:IncorrectNumberOfArguments',...
            'Incorrect number of arguments to %s.',mfilename);
    end
    okargs = {'showplot',''};
    for j=1:2:nargin-2
        pname = varargin{j};
        pval = varargin{j+1};
        k = strmatch(lower(pname), okargs);%#ok
        if isempty(k)
            error('Bioinfo:svmclassify:UnknownParameterName',...
                'Unknown parameter name: %s.',pname);
        elseif length(k)>1
            error('Bioinfo:svmclassify:AmbiguousParameterName',...
                'Ambiguous parameter name: %s.',pname);
        else
            switch(k)
                case 1 % plotflag
                    plotflag = opttf(pval);
                    if isempty(plotflag)
                        error('Bioinfo:InputOptionNotLogical','%s must be a logical value, true or false.',...
                            upper(char(okargs(k))));
                    end

            end
        end
    end
end

groupnames = svmStruct.GroupNames;

% grp2idx sorts a numeric grouping var ascending, and a string grouping
% var by order of first occurrence

[g,groupString] = grp2idx(groupnames);  %#ok

% check group is a vector -- though char input is special...
if ~isvector(groupnames) && ~ischar(groupnames)
    error('Bioinfo:svmclassify:GroupNotVector',...
        'Group must be a vector.');
end

% do the classification
if ~isempty(sample)
    try
        classified = svmdecision(sample,svmStruct);
    catch
        error('Bioinfo:svmclassify:ClassifyFailed',...
            'An error was encountered during classification.\n%s',lasterr);
        % Add more diagnostics?
    end
    if plotflag
      
        if isempty(svmStruct.FigureHandles)
            warning('Bioinfo:svmclassify:NoTrainingFigure',...
                'No figure was created during training so no ShowPlot option does not work.');

        else
            try
                hAxis = svmStruct.FigureHandles{1};
                hLines = svmStruct.FigureHandles{2};
                hSV = svmStruct.FigureHandles{3};
                [hAxis,hClassLines] = svmplotdata(sample,classified,hAxis); %#ok
                trainingString = strcat(cellstr(groupString),' (training)');
                sampleString = strcat(cellstr(groupString),' (classified)');
                legend([hLines(1),hClassLines(1),hLines(2),hClassLines(2),hSV],...
                    {trainingString{1},sampleString{1},...
                    trainingString{2},sampleString{2},'Support Vectors'});
            catch
                warning('Bioinfo:svmclassify:DisplayFailed',...
                    'An error was encountered during plotting.\n%s',lasterr);
            end
        end
    end
    classified(classified == -1) = 2;
    outclass = classified;
    % Convert back to original grouping variable
    if isnumeric(groupnames) || islogical(groupnames)
        groupString = str2num(char(groupString)); %#ok
        outclass = groupString(outclass);
    elseif ischar(groupnames)
        groupString = char(groupString);
        outclass = groupString(outclass,:);
    else %if iscellstr(groupnames)
        outclass = groupString(outclass);
    end

else
    outclass = [];
end


