function [Index,selpts,clkpts]=selectpts(Xdat,Ydat,Xstd,Ystd,nfig)
%SELECTPTS - select individual points on a plot
% 
%USAGE -	[Index,selpts,clkpts]=selectpts(Xdat,Ydat,Xstd,Ystd,nfig)
%		
%		Index -	index to points in [Xdat, Ydat]
%		selpts - data values at Index in [Xdat,Ydat]
%		clkpts - [x,y] coordinates clicked on
%		Xdat - x data values
%		Ydat - y data values
%		Xstd - reference x data for comparison (optional)
%		Ystd - reference y data for comparison (optional)
%		nfig - draw a new figure, or use an existing plot (0 or 1)
%
%EXPLANATION -	present a display of points and optionally a reference 
%	array, offer an opportunity to select individual points and 
%	return indices of the chosen points. return also the points
%	selected, and the coordinates actually clicked. use shift- and 
%	ctrl-click to zoom in and out. use left click to select points. 
%	point selection is by choosing the minimum vector distance in 
%	the data array from the point clicked.
%
%SEE ALSO -	
%

%PROGRAM - 	MATLAB code by c.m.duncombe rae
%
%CREATED - 2008/02/06
%	$Revision: 1.7 $
%	$Date: 2008/04/29 20:02:32 $
%	$Id: selectpts.m,v 1.7 2008/04/29 20:02:32 duncombe Exp duncombe $
%
%CHANGELOG -	
%  2008/04/29 CMDR
%	* the zoom interaction with matlab is going weird. something to
%	do with java? So turn off zoom and reset the state when we leave.
%
%DISCLAIMER -	No responsibility can be accepted for failure or 
%		incorrect operation of this code. No guarantee, express 
%		or implied, is given. 
%

% 
%PROGRAMMING NOTES
% 	* look at showctd for uicontrol stuff
% 

morestate=get(0,'more');
more off;

if ~exist('nfig'), nfig=[]; end;
if isempty(nfig), nfig=0; end;

if nfig,
Fig=figure; plot(Xdat,Ydat,'x');
	hold on;
	if exist('Xstd'), plot(Xstd,Ystd); end;
end;

% zoomh=zoom(gcf);zoomstate=zoomh.enable;
% zoom off;
zoom on
oriax=axis;

blurb=	{'click to select' ...
	 'shift-click to zoom in' ...
	 'ctrl-click to zoom out' ...
	 'Press q to quit choosing'};
Index=[];
selpts=[];
clkpts=[];
hndl=[];
pcnt=0;
key2=1;

% this is a standard matlab constant, however, to be sure we know
% what we are talking about, define it here...
j=sqrt(-1);

for i=1:length(blurb), disp(blurb{i}); end;

while 1, % repeat until we get a quit command
% if there were multiple points, we have 
% a buttonclick not dealt with (flag in key2)
  if key2, key=waitforbuttonpress; else key=key2; end;
  if key,
  % it was a keypress
	% disp(cpp); disp(cpa); 
	cc=get(gcf,'currentCharacter');
	if strcmp(cc,'q'),
		break; % return;
	else
		for i=1:length(blurb), disp(blurb{i}); end;
	end;
	disp(cpp);
	disp(cp);
	disp(sprintf(form(4),ax.'))
	disp(sprintf(form(4),nax.'))
  else
  % it was a mouseclick
	if key2,
		cpp=get(gca,'currentpoint');
		cp=cpp(1,1:2);
		st=get(gcf,'selectiontype');
	else
		% we have the cp, and st from previous round, reset the flag
		key2=1;
	end;
	ax=axis;
        % shift : we want to zoom, not select
	if strcmp(st,'extend'),
	% zoom in
		zoomer(cp,2);
		nax=axis;
	% control : we want to zoom, not select 
	elseif strcmp(st,'alt'), 
	% zoom out
		zoomer(cp,0.5);
		nax=axis;
	% double click
	elseif strcmp(st,'open'),
	% we want to deselect, not zoom
	% we still need to think about multiple points?
		% axes are usu. unequal, there4 beware choosing point. scale!
		fx=ax(2)-ax(1); fy=ax(4)-ax(3);
		[junk,I]=min([Xdat./fx + j.*Ydat./fy] - (cp./[fx,fy])*[1;j]);
		size(selpts)
		J=find(any(selpts.'==[Xdat(I);Ydat(I)]*ones(1,size(selpts,1))));
		selpts(J,:)=[];
		Index(J)=[];
		pcnt=pcnt-length(J);
		delete(Handle(J));
		Handle(J)=[];
	else
	% we want to select, not zoom
		% [junk,I]=min(abs([Xdat+j.*Ydat]-cp*[1;j]));
		% axes are usu. unequal, there4 beware choosing point. scale!
		fx=ax(2)-ax(1); fy=ax(4)-ax(3);
		dist=abs([Xdat./fx+j.*Ydat./fy]-(cp./[fx,fy])*[1;j]);
		% check if the points can be distinguished, if not 
		% offer a choice or zoom again
		I=find((dist-min(dist))<0.010);
		ncnt=length(I);
		if ncnt>1, 
		   disp([ 'Unsure which point you want. There are ' ...
			  num2str(length(I)) ' in range.']);
		   disp([Xdat(I), Ydat(I)]);
		   if ~isempty(hndl), delete(hndl); end;
		   hndl=[];
		   hndl=plot(Xdat(I), Ydat(I),'o');
		   disp('press "a" to select all');
  		   key2=waitforbuttonpress;
		   if key2,
  			% it was a keypress
		   	cc2=get(gcf,'currentCharacter');
		      	if ~strcmpi(cc2,'a'), ncnt=0; end;
		   else
			% it was a mouse click, so take key2 to the top
			% collect the point and go round again
			cpp=get(gca,'currentpoint'); cp=cpp(1,1:2);
			st=get(gcf,'selectiontype');
			ncnt=0;
		   	nax=axis;
		   end;
		end; 
		if ncnt>0,
		%   clkpts(pcnt,1:2)=cp;
		%   [junk,I]=min(dist);
		   selpts(pcnt+1:pcnt+ncnt,1:2)=[Xdat(I),Ydat(I)];
		   Index(pcnt+1:pcnt+ncnt)=I;
		   hold on;
		   Handle(pcnt+1:pcnt+ncnt)=plot(Xdat(I),Ydat(I),'+');
		   pcnt=pcnt+ncnt;
		end;
		disp(cp);
	end;
  end;
end;

% I want to return Index as a column not a row
[m,n]=size(Index);
if n>m, Index=Index.'; end;


if ~isempty(hndl), delete(hndl); end;
axis(oriax);

% set(zoomh,'enable',zoomstate);
zoom off
more(morestate);
return;

%%%%%%%%%%%%%%%%%%%%%%%%
% function zoomer
%%%%%%%%%%%%%%%%%
function zoomer(cp,fact)
% zoom axes manually by setting them. factor<1 for zooming out, >1 for 
% zooming in. zoom(factor) is available but the way matlab appears to have 
% set it up is ridiculous. The point clicked is not centered, instead the
% zoom appears to take place around the center of the original axes or 
% perhaps some other random point.
	ax=axis;
	dax=[(ax(2)-ax(1)), (ax(4)-ax(3))]./fact./2;
	nax=[cp(1)-dax(1),cp(1)+dax(1), cp(2)-dax(2),cp(2)+dax(2)];
	try,
		axis(nax);
	catch,
		cp, ax, dax, nax
		rethrow(lasterror);
	end;
return;

