function svcgui (message)

% Function svcgui
% Show a nice GUI for entering points and controlling David Tax & 
% Dick de Ridder's (dick@ph.tn.tudelft.nl) Support Vector Classifier code.
%
% Disclaimer
% THIS SOFTWARE IS BEING PROVIDED TO YOU 'AS IS.'  INTERVAL MAKES
% NO EXPRESS, IMPLIED OR STATUTORY WARRANTY OF ANY KIND FOR THE
% SOFTWARE INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF
% PERFORMANCE, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
% IN NO EVENT WILL INTERVAL BE LIABLE TO LICENSEE OR ANY THIRD
% PARTY FOR ANY DAMAGES, INCLUDING LOST PROFITS OR OTHER INCIDENTAL
% OR CONSEQUENTIAL DAMAGES, EVEN IF INTERVAL HAS BEEN ADVISED OF
% THE POSSIBLITY THEREOF.
%
%   This software program is owned by Interval Research
% Corporation, but may be used, reproduced, modified and
% distributed by Licensee.  Licensee agrees that any copies of the
% software program will contain the same proprietary notices and
% warranty disclaimers which appear in this software program.
%
% Malcolm Slaney (malcolm@interval.com)
% Interval Research Corporation
% (c) 1998 by Interval Research Corporation


if nargin < 1
	message = 'Init';
end

switch(message)
case 'Clear',
					% Find the right axes
	h = findobj(gcbf,'Tag','DrawPoints');
	set(h,'UserData',[]);		% Remove all the points.
	cla				% Clear the plot
					
case 'Init',
	figure(1);			% Reserve for 2D Plot
	figure(2);			% Reserve for 3D Plot
	svcgui_init
	SetMethodEnables(findobj(gcf,'Tag','PopupMethod'));
	set(gcbf,'HandleVisibility','callback');


case 'DrawPoints',
	pt = get(gca, 'CurrentPoint');
	button = get(gcbf, 'SelectionType');
	x = pt(1,1);
	y = pt(1,2);

	% fprintf('Got %s at %d,%d.\n', button, x, y);
	switch(button)
	case 'normal',			% Left Button
		value = -1;
		marker = 'x';
	case 'extend',			% Middle Button
		value = 1;
		marker = 'o';
	otherwise			% Ignore anything else
		value = 0;
	end
	if value ~= 0
					% Add the new point to array
		h = findobj(gcbf, 'Tag','DrawPoints');
		data = get(h,'UserData');
		data = [data;x y value];
		set(h,'UserData',data);

		if value < 0
			t = text(x, y, marker, ...
				'HorizontalAlignment','Center', ...
				'Color',[1 0 0]);
		else
			t = text(x, y, marker, ...
				'HorizontalAlignment','Center', ...
				'Color',[0 0 1]);
		end
	end

case 'DoIt',
	options(1) = get(findobj(gcbf, 'Tag','PopupMethod'),'Value') - 1;
	options(2) = eval(get(findobj(gcbf, 'Tag','EditPolyDim'),'String'));
	options(3) = eval(get(findobj(gcbf, 'Tag','EditC'),'String'));
	options(4) = eval(get(findobj(gcbf, 'Tag','EditRadialBasis'),'String'));
	options(5) = eval(get(findobj(gcbf, 'Tag','EditPotentialSigma'), ...
								'String'));
	options(6) = eval(get(findobj(gcbf, 'Tag','EditNeuralV'),'String'));
	options(7) = eval(get(findobj(gcbf, 'Tag','EditNeuralC'),'String'));
	options(8) = get(findobj(gcbf, 'Tag','Check2D'),'Value');
	options(9) = get(findobj(gcbf, 'Tag','Check3D'),'Value');

	h = findobj('Tag','DrawPoints');
	data = get(h,'UserData');
					
	set(gcbf,'HandleVisibility','off');
	svc2(data(:,1:2),data(:,3),options);
	set(gcbf,'HandleVisibility','callback');

case 'Help',
	fprintf('Got the Help button.\n');
svchelpstr = {
'This is a simple Graphical User Interface for David Tax & Dick de Ridder''s'
'Support Vector Classification Code.  This GUI was written by Malcolm Slaney'
'(malcolm@interval.com) and should give you a flavor for how Support'
'Vector Classifiers work.'
' '
'When you call the SVC GUI (using the svcgui command) you get three windows.'
'The first window allows a user to specify points on a two-dimensional grid'
'and to control the SVC program.  The results are displayed in one of two'
'other windows.  Figure 1 shows a two dimensional plot of the data, with'
'the first class indicated as "+" and the second class as "*".  The support'
'vectors are circled in red.  Figure 2 shows a color plot of the decision'
'surface.  A black line shows the z=0 line, the z=1 and z=-1 lines are shown'
'as dashed lines.'
' '
'The blank area on the Support Vector Controller window is used to enter'
'points to be classified.  The left mouse button puts down red points, and'
'the middle button (or right if you have two buttons) puts down blue points.'
' '
'The popup menu on the upper right allows you to specify the type of '
'distance metric you would like to use.  Depending on your choice, one of '
'the small edit windows allows you to specify the parameters of the decision'
'surface.'
' '
'The big "Do It" button calls the svc program to do the work and plot the'
'figures.  The two small checkboxes to the right of "Do It" turn on and'
'off the two summary graphs.  Note the 2d plot (figure 1) shows up almost'
'instantaneously, the 3d color plot takes quite a bit longer.'
' '
'The linear method uses the following distance metric:'
'           Xi . Xj'''
'The polynomial method uses the distance metric:'
'           (Xi . Xj'' + 1) ^ dimension'
'The radial basis method uses the distance metric:'
'           exp(-(Xi . Xj'')/po_sigma)'
'The radial basis method uses the distance metric:'
'           exp(-((Xi . Xj'')/rb_sigma)^2)'
'The radial basis method uses the distance metric:'
'           exp(-(Xi . Xj'')/po_sigma)'
'The neural method uses the distance metric:'
'           tanh(nn_v * Xi . Xj'' + nn_c)'
' '
'For more information on Support Vector Classifiers, please see the really'
'excellent paper '
'   Cortes, C. and Vapnik, V. Support-vector networks. Machine Learning, '
'   20:273-297, 1995. '
'The entire package is available from'
'   http://valhalla.ph.tn.tudelft.nl/feature_extraction/source/svc/'
};
	helpwin(svchelpstr,'SVC GUI Help');

case 'NewMethod',
	h = findobj(gcbf, 'Tag','PopupMethod');
	SetMethodEnables(h)

otherwise,
	fprintf('Unknown message %s to svcgui.\n', message);
end

function SetMethodEnables(h)
	method = get(h,'Value');
	if length(method) < 1
		fprintf('Couldn''t find the Method Popup''s value.\n');
		return;
	end
	% fprintf('Changed the method to %d.\n',method);
	set(findobj('Tag','EditC'),'Enable','on');
	switch (method)
	case 1,				% Linear
		set(findobj(gcbf, 'Tag','EditPolyDim'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditRadialBasis'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditPotentialSigma'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralV'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralC'),'Enable','off');
	case 2,				% Polynomial
		set(findobj(gcbf, 'Tag','EditPolyDim'),'Enable','on');
		set(findobj(gcbf, 'Tag','EditRadialBasis'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditPotentialSigma'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralV'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralC'),'Enable','off');
	case 3,				% Potential
		set(findobj(gcbf, 'Tag','EditPolyDim'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditRadialBasis'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditPotentialSigma'),'Enable','on');
		set(findobj(gcbf, 'Tag','EditNeuralV'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralC'),'Enable','off');
	case 4,				% RadialBasis
		set(findobj(gcbf, 'Tag','EditPolyDim'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditRadialBasis'),'Enable','on');
		set(findobj(gcbf, 'Tag','EditPotentialSigma'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralV'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralC'),'Enable','off');
	case 5,				% Neural
		set(findobj(gcbf, 'Tag','EditPolyDim'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditRadialBasis'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditPotentialSigma'),'Enable','off');
		set(findobj(gcbf, 'Tag','EditNeuralV'),'Enable','on');
		set(findobj(gcbf, 'Tag','EditNeuralC'),'Enable','on');
	end
		

function svcgui_init()
% This is the machine-generated representation of a Handle Graphics object
% and its children.  Note that handle values may change when these objects
% are re-created. This may cause problems with any callbacks written to
% depend on the value of the handle at the time the object was saved.
%
% To reopen this object, just type the name of the M-file at the MATLAB
% prompt. The M-file and its associated MAT-file must be on your path.

mat3={'linear';'polynomial';'potential';'radial basis';'neural'};

a = figure('Color',[0.855388 0.855388 0.855388], ...
	'HandleVisibility','on', ...
	'Name','Support Vector Controller', ...
	'NumberTitle','off', ...
	'Position',[696 495 568 469], ...
	'Tag','Support Vector Controller', ...
	'DefaultaxesColor',[1 1 1], ...
	'DefaultlineColor',[0 0 0], ...
	'DefaultsurfaceEdgeColor',[0 0 0], ...
	'DefaultpatchEdgeColor',[0 0 0], ...
	'DefaultpatchFaceColor',[0 0 0], ...
	'DefaultaxesZColor',[0 0 0], ...
	'DefaultaxesYColor',[0 0 0], ...
	'DefaultaxesXColor',[0 0 0], ...
	'DefaulttextColor',[0 0 0]);
b = axes('Parent',a, ...
	'Units','points', ...
	'ButtonDownFcn','svcgui(''DrawPoints'');', ...
	'CameraUpVector',[0 1 0], ...
	'CameraUpVectorMode','manual', ...
	'Color',[1 1 1], ...
	'Position',[20.8 77.6 279.2 259.2], ...
	'Tag','DrawPoints', ...
	'XColor',[0 0 0], ...
	'YColor',[0 0 0], ...
	'ZColor',[0 0 0]);
c = text('Parent',b, ...
	'Color',[0 0 0], ...
	'HandleVisibility','callback', ...
	'HorizontalAlignment','center', ...
	'Position',[0.497126 -0.0681115 0], ...
	'Tag','Axes1Text4', ...
	'VerticalAlignment','cap');
set(get(c,'Parent'),'XLabel',c);
c = text('Parent',b, ...
	'Color',[0 0 0], ...
	'HandleVisibility','callback', ...
	'HorizontalAlignment','center', ...
	'Position',[-0.0775862 0.495356 0], ...
	'Rotation',90, ...
	'Tag','Axes1Text3', ...
	'VerticalAlignment','baseline');
set(get(c,'Parent'),'YLabel',c);
c = text('Parent',b, ...
	'Color',[0 0 0], ...
	'HandleVisibility','callback', ...
	'HorizontalAlignment','right', ...
	'Position',[-0.0775862 1.14551 0], ...
	'Tag','Axes1Text2', ...
	'Visible','off');
set(get(c,'Parent'),'ZLabel',c);
c = text('Parent',b, ...
	'Color',[0 0 0], ...
	'HandleVisibility','callback', ...
	'HorizontalAlignment','center', ...
	'Position',[0.497126 1.01858 0], ...
	'Tag','Axes1Text1', ...
	'VerticalAlignment','bottom');
set(get(c,'Parent'),'Title',c);
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Callback','svcgui(''NewMethod'');', ...
	'Max',5, ...
	'Min',1, ...
	'Position',[302.4 345.6 118.4 18.4], ...
	'String',mat3, ...
	'Style','popupmenu', ...
	'Tag','PopupMethod', ...
	'Value',2);
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Position',[305.6 288 117.6 20.8], ...
	'String','1000', ...
	'Style','edit', ...
	'Tag','EditC');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Enable','off', ...
	'Position',[305.6 177.6 117.6 20.8], ...
	'String','1', ...
	'Style','edit', ...
	'Tag','EditRadialBasis', ...
	'Value',1);
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Enable','off', ...
	'Position',[305.6 122.4 117.6 20.8], ...
	'String','1', ...
	'Style','edit', ...
	'Tag','EditPotentialSigma');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Enable','off', ...
	'Position',[305.6 67.2 117.6 20.8], ...
	'String','0.1', ...
	'Style','edit', ...
	'Tag','EditNeuralV');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 317.6 115.2 18.4], ...
	'String','C', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 206.4 115.2 18.4], ...
	'String','Radial Basis', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 151.2 115.2 19.2], ...
	'String','Potential Sigma', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 96 115.2 18.4], ...
	'String','Neural V', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Callback','svcgui(''Help'');', ...
	'Position',[16.8 41.6 50.4 19.2], ...
	'String','Help', ...
	'Tag','PushbuttonHelp');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Callback','svcgui(''DoIt'');', ...
	'Position',[73.6 12.8 111.2 48], ...
	'String','Do It!', ...
	'Tag','PushbuttonDoIt');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 263.2 115.2 18.4], ...
	'String','Polynomial Dimension', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Position',[305.6 233.6 117.6 20.8], ...
	'String','4', ...
	'Style','edit', ...
	'Tag','EditPolyDim');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[305.6 40.8 115.2 18.4], ...
	'String','Neural C', ...
	'Style','text', ...
	'Tag','StaticText1');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[1 1 1], ...
	'Enable','off', ...
	'Position',[305.6 11.2 117.6 20.8], ...
	'String','1', ...
	'Style','edit', ...
	'Tag','EditNeuralC');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[47.2 345.6 226.4 16], ...
	'String','Enter Points Here--left (red) and middle (blue) mouse)', ...
	'Style','text', ...
	'Tag','StaticText2');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Callback','svcgui(''Clear'');', ...
	'Position',[16.8 10.4 50.4 20], ...
	'String','Clear', ...
	'Tag','PushbuttonClear');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[189.6 36.8 112 24], ...
	'String','Show 2D Results', ...
	'Style','checkbox', ...
	'Tag','Check2D');
b = uicontrol('Parent',a, ...
	'Units','points', ...
	'BackgroundColor',[0.701961 0.701961 0.701961], ...
	'Position',[189.6 10.4 112 24], ...
	'String','Show 3D Results', ...
	'Style','checkbox', ...
	'Tag','Check3D', ...
	'Value',1);
