%PLOTC Plot classifiers % % PLOTC(W,S,LINE_WIDTH) % PLOTC(W,LINE_WIDTH,S) % % Plots the discriminant as given by the mapping W on predefined axis, % typically set by scatterd. Discriminants are defined by the points % where class differences for mapping values are zero. % % S is the plot string, e.g. S = 'b--'. In case S = 'col' a color plot is % produced filling the regions of different classes with different colors. % Default S = 'k-'; % % LINE_WIDTH sets the width of the lines and box. Default LINE_WIDTH = 1.5 % % In W a cell array of classifiers may be given. In S a set of plot strings % of appropriate size may be given. Automatically a legend is added to % the plot. % % The linear gridsize is read from the global parameter GRIDSIZE, that % can be set by the function gridsize: for instance 'gridsize(100)' % default gridsize is 30. As all these points have to be classified (e.g. % 100x100) this always done in batch mode. If needed desired the default % batch size may be changed by PRGLOBAL. % % Examples in PREX_CONFMAT, PREX_PLOTC % % SEE ALSO (PRTools Guide) % MAPPINGS, SCATTERD, PLOTM, GRIDSIZE, SETBATCH, PRGLOBAL % Copyright: R.P.W. Duin, duin@ph.tn.tudelft.nl % Faculty of Applied Sciences, Delft University of Technology % P.O. Box 5046, 2600 GA Delft, The Netherlands % $Id: plotc.m,v 1.6 2009/10/30 11:01:47 davidt Exp $ function handle = plotc(w,varargin) linew = 1.5; s = []; if nargin < 1 | isempty(w) handle = prmapping(mfilename,'combiner',s); return end % Extract the plotwidth and linewidth: for j = 1:nargin-1 if isstr(varargin{j}) s = varargin{j}; else linew = varargin{j}; end end ss = char('k-','r-','b-','m-','k--','r--','b--','m--'); ss = char(ss,'k-.','r-.','b-.','m-.','k:','r:','b:','m:'); % When we want to plot a list of classifiers, we set up different % plot strings ss and call plotc several times. if iscell(w) w = w(:); n = length(w); names = []; % Check if sufficient plotstrings are available if ~isempty(s) if size(s,1) == 1 s = repmat(s,n,1); elseif size(s,1) ~= n error('Wrong number of plot strings') end else s = ss(1:n,:); end % Plot the individual boundaries by calling 'mfilename' (i.e. this % function again) names = []; hh = []; for i=1:n h = feval(mfilename,w{i},deblank(s(i,:)),linew); hh = [hh h(1)]; names = char(names,getname(w{i})); end % Finally fix the legend: names(1,:) = []; legend(hh,names,0); if nargout > 0 handle = hh; end return end % Now the task is to plot a single boundary (multiple boundaries are % already covered above): if ~isa(w,'prmapping') | ~istrained(w) error('Trained classifier expected') end %w = w*setbatch; % Avoid memory prolems with large gridsizes [k,c] = size(w); c = max(c,2); if nargin < 2 | isempty(s) % default plot string s = 1; end %DXD: Stop when the classifier is not in 2D: if (k~=2) error('Plotc can only plot classifiers operating in 2D.'); end if ~isstr(s) if s > 16 | s < 1 error('Plotstring undefined') else s = deblank(ss(s,:)); end end % Get the figure size from the current figure: hold on V=axis; hh = []; set(gca,'linewidth',linew) % linear discriminant if isaffine(w) & c == 2 & ~strcmp(s,'col') % plot as vector d = +w; n = size(d.rot,2); if n == 2, n = 1; end for i = 1:n w1 = d.rot(:,i); w0 = d.offset(i); J = find(w1==0); if ~isempty(J) w1(J) = repmat(realmin,size(J)); end x = sort([V(1),V(2),(-w1(2)*V(3)-w0)/w1(1),(-w1(2)*V(4)-w0)/w1(1)]); if (x(1)==x(2)) % for exactly vertical lines... y = V(3:4); else y = (-w1(1)*x-w0)/w1(2); end h = plot(x,y,s); set(h,'linewidth',linew) hh = [hh h]; end else % general case: find contour(0) % First define the mesh grid: n = gridsize; m = (n+1)*(n+1); dx = (V(2)-V(1))/n; dy = (V(4)-V(3))/n; [X Y] = meshgrid(V(1):dx:V(2),V(3):dy:V(4)); D = double([X(:),Y(:),zeros(m,k-2)]*w); if min(D(:)) >=0, D = log(D+realmin); end % avoid infinities % A two-class output can be given in one real number, avoid this % special case and fix it: if c == 2 & min(size(D)) == 1; D = [D -D]; end c = size(D,2); if ~strcmp(s,'col') % Plot the contour lines if c < 3 Z = reshape(D(:,1) - D(:,2),n+1,n+1); if ~isempty(contourc([V(1):dx:V(2)],[V(3):dy:V(4)],Z,[0 0])) [cc h] = contour([V(1):dx:V(2)],[V(3):dy:V(4)],Z,[0 0],s); set(h,'linewidth',linew) %DXD Matlab 7 has different handle definitions: if str2num(version('-release'))>13, h = get(h,'children'); end hh = [hh;h]; end else for j=1:c-1 L = [1:c]; L(j) = []; Z = reshape( D(:,j) - max(D(:,L),[],2),n+1,n+1); if ~isempty(contourc([V(1):dx:V(2)],[V(3):dy:V(4)],Z,[0 0])) [cc h] = contour([V(1):dx:V(2)],[V(3):dy:V(4)],Z,[0 0],s); set(h,'linewidth',linew) %DXD Matlab 7 has different handle definitions: if str2num(version('-release'))>13, h = get(h,'children'); end hh = [hh;h]; end end end else % Fill the areas with some colour: col = 0; mapp = hsv(c+1); h = []; for j=1:c L = [1:c]; L(j) = []; Z = reshape( D(:,j) - max(D(:,L)',[],1)',n+1,n+1); Z = [-inf*ones(1,n+3);[-inf*ones(n+1,1),Z,-inf*ones(n+1,1)];-inf*ones(1,n+3)]; col = col + 1; if ~isempty(contourc([V(1)-dx:dx:V(2)+dx],[V(3)-dy:dy:V(4)+dy],Z,[0 0])) [cc h] = contour([V(1)-dx:dx:V(2)+dx],[V(3)-dy:dy:V(4)+dy],Z,[0 0]); while ~isempty(cc) len = cc(2,1); h = [h;fill(cc(1,2:len+1),cc(2,2:len+1),mapp(col,:),'FaceAlpha',0.5)]; %fill(cc(1,2:len+1),cc(2,2:len+1),mapp(col,:),'FaceAlpha',0.5); cc(:,1:len+1) = []; end hh = [hh;h]; end end end end axis(V); % Return the handles if they are requested: if nargout > 0, handle = hh; end hold off return