📄 tourgui.m
字号:
function tourgui(arg)
% TOURGUI Data Tours Gui
%
% This GUI function allows one to conduct tours of the data to seek out new
% structure and new patterns... to boldly go where no analyst has gone
% before.
%
% It includes the grand tour, the pseudo grand tour, and the permutation
% tour.
%
% One can call it from the edagui GUI or stand-alone from the command
% line. To call from the command line use
%
% tourgui
%
% NOTE: Group colors on this GUI refer to group labels, if loaded.
%
% Exploratory Data Analysis Toolbox, April 2005
% Martinez and Martinez, Exploratory Data Analysis with MATLAB
% CRC Press
% First set up the layout if it does not exist.
flg = findobj('tag','tourgui');
if isempty(flg)
% then create the gui
tourslayout
elseif nargin == 0
% bring it forward
figure(flg)
end
if nargin == 0
arg = ' ';
end
if strcmp(arg,'grandtour')
% Display all possible pairwise scatterplots with polar smooths.
grandtour
elseif strcmp(arg,'pseudotour')
% Display all possible pairwise bivariate histograms.
pseudotour
elseif strcmp(arg,'permtour')
% Display scatterplots with hexagonal smoothing.
permtour
elseif strcmp(arg,'gtdataout')
% Export projected torus grand tour data to the workspace.
% First get the data and project.
ud = get(0,'userdata');
if ~isempty(ud.gt)
data = ud.X*ud.gt;
else
errordlg('You have not gone on a tour yet.')
return
end
promptstrg = 'Specify variable name:';
titlestrg = 'Output Grand Tour Projected Data to Workspace';
def = {'data'};
saveinfo(promptstrg,titlestrg,def,data)
elseif strcmp(arg,'gtprojout')
% Export projection matrix from the grand tour to the workspace.
ud = get(0,'userdata');
if ~isempty(ud.gt)
data = ud.gt;
else
errordlg('You have not gone on a tour yet.')
return
end
promptstrg = 'Specify variable name:';
titlestrg = 'Output Grand Tour Projection to Workspace';
def = {'projection'};
saveinfo(promptstrg,titlestrg,def,data)
elseif strcmp(arg,'ptdataout')
% Export projected pseudo tour data to the workspace.
ud = get(0,'userdata');
if ~isempty(ud.pgt)
data = ud.X*ud.pgt;
else
errordlg('You have not gone on a tour yet.')
return
end
promptstrg = 'Specify variable name:';
titlestrg = 'Output Pseudo Grand Tour Projected Data to Workspace';
def = {'data'};
saveinfo(promptstrg,titlestrg,def,data)
elseif strcmp(arg,'ptprojout')
% Export projection matrix from pseudo tour to the workspace.
ud = get(0,'userdata');
if ~isempty(ud.pgt)
data = ud.pgt;
else
errordlg('You have not gone on a tour yet.')
return
end
promptstrg = 'Specify variable name:';
titlestrg = 'Output Pseudo Grand Tour Projection to Workspace';
def = {'projection'};
saveinfo(promptstrg,titlestrg,def,data)
elseif strcmp(arg,'close')
% in other gui's we will do some housekeeping. With this gui, we do not
% have to do so. Obviously, the user will want to keep the data from
% the loadgui for other applications. That is the purpose.
tg = findobj('tag','tourgui');
H = get(tg,'userdata');
if ~isempty(H.plots)
button = questdlg('Closing this GUI will close the associated plot windows.',...
'Closing GUI Warning','OK','Cancel','Cancel');
if strcmp(button,'Cancel')
return
else
close(H.plots)
end
end
delete(tg)
end
%************************************************************
%************************************************************
function grandtour
% Get the data matrix. Get the GUI info.
ud = get(0,'userdata');
if isempty(ud.X)
errordlg('You must load up some data first.')
return
end
[n,p] = size(ud.X);
Hf = findobj('tag','gt');
if isempty(Hf)
% then create the new thing
tg = findobj('tag','tourgui');
H = get(tg,'userdata');
% Get the various stuff from the GUI
gtstep = str2double(get(H.gtstep,'string'));
if gtstep <= 0
errordlg('The step size must be greater than 1.')
return
end
gtdim = round(str2double(get(H.gtdim,'string')));
if gtdim <= 1
errordlg('The number of dimensions must be greater than 2.')
return
elseif gtdim > p
errordlg('The number of dimensions must be in the interval 2 to p.')
return
end
gtiter = round(str2double(get(H.gtiter,'string')));
if gtiter <= 1
errordlg('The number of iterations must be greater than 1.')
return
end
hf = figure;
set(hf,'tag','gt','numbertitle','off','name','EDA: Torus Grand Tour')
% Upon figure close, this should delete from the array.
set(hf,'CloseRequestFcn',...
'tg = findobj(''tag'',''tourgui''); H = get(tg,''userdata''); H.plots(find(H.plots == gcf)) = []; set(tg,''userdata'',H); delete(gcf)')
H.plots = [H.plots, hf];
set(tg,'userdata',H)
gtdisp = get(H.gtdisplay,'value');
% 1. Scatterplot -> torustour
% 2. Andrews -> kdimtour with 'a' as type
% 3. Parallel -> kdimtour with 'p' as type
switch gtdisp
case 1
% run torustour
if gtdim > 2
errordlg('You can only do a scatterplot in 2 dimensions.')
close(hf)
return
end
runtorustour(ud.X,gtiter,hf,gtstep)
case 2
% runkdimtour with type 'a'
runkdimtour(ud.X,gtiter,gtdim,'a',hf,gtstep)
case 3
% runkdimtour with type 'p'
runkdimtour(ud.X,gtiter,gtdim,'p',hf,gtstep)
end
else
gtud = get(Hf,'userdata');
switch gtud.gtdisp % save this in the structure
case 1
% run torustour
runtorustour(ud.X,gtud.maxit,Hf,gtud.delt)
case 2
% run andrews kdimtour
runkdimtour(ud.X,gtud.maxit,gtud.k,'a',Hf,gtud.delt)
case 3
% run parallel kdimtour
runkdimtour(ud.X,gtud.maxit,gtud.k,'p',Hf,gtud.delt)
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function pseudotour
% Get the data matrix. Get the GUI info.
ud = get(0,'userdata');
if isempty(ud.X)
errordlg('You must load up some data first.')
return
end
% Check to see if tour window exists
Hf = findobj('tag','pgt');
if isempty(Hf)
% then create the new thing.
tg = findobj('tag','tourgui');
H = get(tg,'userdata');
% Get the values from the GUI.
pstep = str2double(get(H.psstep,'string'));
if pstep <= 0
errordlg('The step size must be greater than 0.')
return
end
psiter = str2double(get(H.psiter,'string'));
if psiter <= 1
errordlg('The maximum number of iterations must be greater than 1.')
return
end
hf = figure;
set(hf,'tag','pgt','numbertitle','off','name','EDA: Pseudo Grand Tour')
% Upon figure close, this should delete from the array.
set(hf,'CloseRequestFcn',...
'tg = findobj(''tag'',''tourgui''); H = get(tg,''userdata''); H.plots(find(H.plots == gcf)) = []; set(tg,''userdata'',H); delete(gcf)')
H.plots = [H.plots, hf];
set(tg,'userdata',H)
runptour(ud.X,psiter,hf,pstep);
else
gtud = get(Hf,'userdata');
runptour(ud.X,gtud.maxit,gtud.Hf,gtud.delt)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function permtour
% Get the data matrix. Get the GUI info.
ud = get(0,'userdata');
if isempty(ud.X)
errordlg('You must load up some data first.')
return
end
[n,p] = size(ud.X);
tg = findobj('tag','tourgui');
H = get(tg,'userdata');
hf = figure;
% MIGHT NEED TWO DIFFERENT ONES HERE - ANDREWS AND PARALLEL
set(hf,'numbertitle','off','name','EDA: Permutation Tour')
% Upon figure close, this should delete from the array.
set(hf,'CloseRequestFcn',...
'tg = findobj(''tag'',''tourgui''); H = get(tg,''userdata''); H.plots(find(H.plots == gcf)) = []; set(tg,''userdata'',H); delete(gcf)')
H.plots = [H.plots, hf];
set(tg,'userdata',H)
% Get the desired type of tour - all permutations or Wegman's minimal tour
tourtype = get(H.permtype,'value');
% Get the desried type of display - Andrews or parallel
disptype = get(H.permdisplay,'value');
% Get the information to plot in colors or not.
colflag = get(H.permcolflag,'value');
if isempty(ud.classlab) & colflag == 1
% The user chose to display using colors and class labels are not
% loaded.
close(hf)
errordlg('You must have some group/class labels loaded to use color by groups.')
return
end
% Now do the tour.
if tourtype == 1 & disptype == 1
% Then do permutation tour with all permutations
permtourandrews(ud.X,0,colflag,hf)
elseif tourtype == 2 & disptype == 1
% Then do permutation tour with Wegman's partial tour
permtourandrews(ud.X,1,colflag,hf)
elseif tourtype == 1 & disptype == 2
% Then do paralle coordinate tour with all permutations
% Actually, this one is not available for parallel coordinates.
% Only need to do the wegman partial tour, so provide an error.
close(hf)
errordlg('You can only do the minimal version with the permutation tour in parallel coordinates.')
return
elseif tourtype == 2 & disptype == 2
% Then do parallel coordinate tour with Wegman's partial tour
permtourparallel(ud.X,colflag,hf)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function saveinfo(promptstrg,titlestrg,def,data)
% data is the information to be saved to the workspace
answer = inputdlg(promptstrg,titlestrg,1,def);
if ~isempty(answer)
assignin('base',answer{1},data)
% else
% assignin('base','data,H.data')
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function permtourparallel(X,colflag,Hfig)
% PERMTOURPARALLEL Permutes axes in parallel coordinates
% SPecial version for the tourgui.
[n,p] = size(X);
% Get the permutations - each row corresponds to a different one.
P = permweg(p);
[nP,pP] = size(P);
set(Hfig,'tag','figparatour','renderer','painters','DoubleBuffer','on','backingstore','off');
% Set up the line handles - need n of these
Hline = zeros(1,n);
for i = 1:n
Hline(i) = line('xdata',nan,'ydata',nan,'linestyle','-');
end
% get the axes lines
ypos = linspace(0,1,p);
xpos = [0 1];
% THe following gets the axis lines.
% Save the text handles, so they can be permuted, too.
% Save the text strings, too.
Htext = zeros(1,p);
k = p;
for i=1:p
line(xpos,[ypos(i) ypos(i)],'color','k')
Htext(i) = text(-0.05,ypos(i), ['x' num2str(k)]);
k=k-1;
end
axis off
% parallel(Hline,X,Htext,1:p);
title('Hit any key to step through the tour:')
% Loop through all of the permutations.
for i = 1:nP
% permute the columns by the row of the permutation matrix
xP = X(:,P(i,:));
parallel(Hline,xP,Htext,P(i,:),colflag);
pause
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function parallel(Hline,x,Htext,P,colflag)
if colflag == 1
% Then plot using colors based on ud.classlab
ud = get(0,'userdata');
end
% If parallel coordinates, then change range.
% map all values onto the interval 0 to 1
% lines will extend over the range 0 to 1
md = min(x(:)); % find the min of all the data
rng = range(x(:)); %find the range of the data
xn = (x-md)/rng;
[n,p] = size(x);
ypos = linspace(0,1,p);
if colflag == 0
% then display without class colors
for i=1:n
set(Hline(i),'xdata',xn(i,:),'ydata',fliplr(ypos))
end
P = fliplr(P);
for i = 1:p
set(Htext(i),'string', ['x' num2str(P(i))]);
end
elseif colflag == 1
% then display WITH group colors.
% Can only display up to 7 groups by color. this should be sufficient.
% We will use the default MATLAB colors
cols = {'b';'g';'r';'c';'m';'y';'k'};
clab = unique(ud.classlab);
if length(clab) > length(cols)
errordlg('The maximum number of allowed groups is 7.')
return
end
for k = 1:length(clab)
% loop over all of the different colors and display
inds = find(ud.classlab==clab(k));
for i=inds
set(Hline(i),'xdata',xn(i,:),'ydata',fliplr(ypos),'color',cols{k})
end
P = fliplr(P);
for i = 1:p
set(Htext(i),'string', ['x' num2str(P(i))]);
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function permtourandrews(X,typeflag,colflag,Hfig)
% PERMTOURANDREWS Permutes variable order in Andrews' curves
% SPecial version for the tourgui.
[n,p] = size(X);
if typeflag == 1
% Get the Wegman partial tour
% Get the permutations - each row corresponds to a different one.
P = permweg(p);
else
P = perms(1:p);
end
[nP,pP] = size(P);
set(Hfig,'tag','figparatour','renderer','painters','DoubleBuffer','on','backingstore','off');
% THe following gets the axis lines.
% Save the text handles, so they can be permuted, too.
% Save the text strings, too.
% axis off
hax = axes('position',[0.05 0.075 0.9 0.8]);
set(hax,'visible','off')
set(hax,'xlimmode','manual')
set(hax,'xlim',[-pi pi])
axis off
% Set up the line handles - need n of these
Hline = zeros(1,n);
for i = 1:n
Hline(i) = line('xdata',nan,'ydata',nan,'linestyle','-');
end
theta = -pi:0.1:pi; %this defines the domain that will be plotted
y = zeros(n,p); %there will n curves plotted, one for each obs
ang = zeros(length(theta),p); %each row must be dotted w/ observation
% Get the string to evaluate function.
fstr = ['[1/sqrt(2) ']; %Initialize the string.
for i = 2:p
if rem(i,2) == 0
fstr = [fstr,' sin(',int2str(i/2), '*i) '];
else
fstr = [fstr,' cos(',int2str((i-1)/2),'*i) '];
end
end
fstr = [fstr,' ]'];
k=0;
% evaluate sin and cos functions at each angle theta
for i=theta
k=k+1;
ang(k,:)=eval(fstr);
end
title('Hit any key to step through the tour:')
% Loop through all of the permutations.
for i = 1:nP
% permute the columns by the row of the permutation matrix
xP = X(:,P(i,:));
andrews(Hline,xP,theta,ang,colflag);
pause
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ANDREWS CURVES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function andrews(Hline,data,theta,ang,colflag)
[n,p] = size(data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -