function tree(objectorder,heights) %TREE creates a tree in which the leaves represent % objects. The vertical coordinate of the junction % of two branches is the dissimilarity between the % corresponding clusters (maximal 30 objects allowed). % % The algorithm is fully described in: % Kaufman, L. and Rousseeuw, P.J. (1990), % "Finding groups in data: An introduction to cluster analysis", % Wiley-Interscience: New York (Series in Applied Probability and % Statistics), ISBN 0-471-87876-6. % % Required input arguments: % objectorder : order of objects % heights : diameter of cluster before dividing it % (=length of banner) % % I/O: % tree(objectorder,heights) % % Example (subtracted from the referenced book) % load agricul.mat % result = diana(agricul,[4 4],0,0,1); % tree(result.objectorder,result.heights) % % The output of TREE is a figure containing the % agglomerative (agnes) or divise (diana) tree. % % This function is part of LIBRA: the Matlab Library for Robust Analysis, % available at: % http://wis.kuleuven.be/stat/robust.html % % Written by Wai Yan Kong (May 2006) % Last Revision: 28/09/2006 clf reset whitebg([1 1 1]); if (nargin<2) error('Two input arguments required') elseif (nargin>2) error('Too many input arguments') end if(size(objectorder,2)~=size(heights,2)+1) error('Missing values in objectorder or heights') end Heights=H(heights); number=size(objectorder,2); if (number>30) error('Only 30 objects allowed') end %midden=[]; middle(1)=0; Maxi=0; Mini=0; PrevMID=middle(1); lengt=[]; %length high=[]; %height indices=[]; L=[]; [maxim,index]=max(Heights); if(1<=index-1) [Prevmax,Previndex]=max(Heights(1:(index-1))); else Prevmax=maxim; Previndex=index; end if(index+1<=number-1) [Postmax,Postindex]=max(Heights((index+1):(number-1))); Postindex=Postindex+index+1-1; else Postmax=maxim; Postindex=index; end if(Postindex+1<=number-1) [Post2max,Post2index]=max(Heights(Postindex+1:number-1)); Post2index=Post2index+Postindex+1-1; else Post2max=Postmax; Post2index=Postindex; end if(Postindex+1<=Post2index-1) [Betweenmax,Betweenindex]=max(Heights(index+1:Postindex-1)); Betweenindex=Betweenindex+index+1-1; else Betweenmax=Postmax; Betweenindex=Postindex; end L=cat(2,L,maxim); high=cat(2,high,[Post2max,Postmax,Betweenmax,maxim,Prevmax]); indices=cat(2,indices,[Post2index,Postindex,Betweenindex,index,Previndex]); M=0; extra=number/2; lengt(1)=Postindex-Previndex+extra+2; PrevLEN=lengt(1); rectangle('Position',[middle(1)-(lengt(1)/2),maxim,lengt(1),0.0001]); NbanFirst=1; k=1; branch=0; over=0; Element=0; Special=0; Spec=0; Sp=0; S=0; ww=0; if(maxim<20) extrawaystick=0.8; extrawaytext=1.5; else extrawaytext=0; extrawaystick=0; end right=0; direct11=0; direct111=0; righttree=0; if(index==1) direct1=1; else direct1=0; end Last=size(lengt,2); LastM=size(middle,2); LastL=size(lengt,2); while(k<=number) w=0; LastH=size(high,2); if((high(LastH)~=high(LastH-1)) & Element==0) while(branch==0) S=0; w=w+1; ww=ww+1; if(over==0) middle=cat(2,middle,middle(LastM)-(lengt(LastL)/2)); end if(righttree==1) middle=cat(2,middle,middle(LastM)-(lengt(LastL)/2)); righttree=0; end if(Sp==1) LastM=size(middle,2); LastL=size(lengt,2); middle(LastM)=middle(LastM)+lengt(LastL)/2; Sp=0; S=1; end LastM=size(middle,2); Output=maxim-Prevmax; rectangle('Position',[middle(LastM),Prevmax,0.0001,Output]); if(Betweenmax==Postmax | over==0) Post2max=Postmax; Post2index=Postindex; end if((Betweenmax==Postmax | over==0) & (right~=1 | over==0)) Postmax=maxim; Postindex=index; end maxim=Prevmax; index=Previndex; if(NbanFirst<=(index-1)) [Prevmax,Previndex]=max(Heights(NbanFirst:(index-1))); Previndex=Previndex+NbanFirst-1; else Prevmax=maxim; Previndex=index; end if(index+1<=Postindex-1) [Betweenmax,Betweenindex]=max(Heights(index+1:Postindex-1)); Betweenindex=Betweenindex+index+1-1; else Betweenmax=Postmax; Betweenindex=Postindex; end if(right==1 & over~=0) high=cat(2,high,[Prevmax Prevmax]); indices=cat(2,indices,[Previndex Previndex]); else high=cat(2,high,Prevmax); indices=cat(2,indices,Previndex); end if(Postindex-Previndex<=0) lengt=cat(2,lengt,1); else if(Postindex-Previndex-direct111>0) if(ww==1) lengt=cat(2,lengt,Postindex-Previndex-direct111+2); else lengt=cat(2,lengt,Postindex-Previndex-direct111); end else if(ww==1) lengt=cat(2,lengt,Postindex-Previndex+2); else lengt=cat(2,lengt,Postindex-Previndex); end end end L=cat(2,L,maxim); if(direct111~=0) direct111=0; end LastH=size(high,2); LastL=size(lengt,2); LastM=size(middle,2); rectangle('Position',[middle(LastM)-(lengt(LastL)/2),maxim,lengt(LastL),0.0001]); if(over~=0) over=0; end if(right~=0) right=0; end if(NbanFirst==index) branch=1; end end rectangle('Position',[middle(LastM)-(lengt(LastL)/2),maxim-1+extrawaystick,0.0001,1-extrawaystick]); if(objectorder(k)>10) text(middle(LastM)-(lengt(LastL)/2)-0.25,maxim-2.0+extrawaytext,num2str(double(objectorder(k)))); T=middle(LastM)-(lengt(LastL)/2-0.25); else text(middle(LastM)-(lengt(LastL)/2)-0.1,maxim-2.0+extrawaytext,num2str(double(objectorder(k)))); T=middle(LastM)-(lengt(LastL)/2-0.1); end Maxi=max(Maxi,T); Mini=min(Mini,T); if(Betweenmax~=Postmax) high=high(1:LastH-2); indices=indices(1:LastH-2); Prevmax=Betweenmax; Previndex=Betweenindex; high=cat(2,high,Prevmax); indices=cat(2,indices,Previndex); LastH=size(high,2); LastL=size(lengt,2); middle(LastM)=middle(LastM)+lengt(LastL)/2; over=1; end direct1=0; Special=0; Spec=0; else if(Special==1) Special=0; Spec=1; end if(Sp==1) Sp=0; end if(S==1) S=2; end direct111=0; LastH=size(high,2); LastM=size(middle,2); LastL=size(lengt,2); if(direct1==0) rectangle('Position',[middle(LastM)+(lengt(LastL)/2),high(LastH)-1+extrawaystick,0.0001,1-extrawaystick]); text(middle(LastM)+lengt(LastL)/2-0.1,high(LastH)-2.0+extrawaytext,num2str(double(objectorder(k)))); T=middle(LastM)+lengt(LastL)/2-0.1; Maxi=max(Maxi,T); Mini=min(Mini,T); else rectangle('Position',[middle(LastM)-(lengt(LastL)/2),high(LastH)-1+extrawaystick,0.0001,1-extrawaystick]); text(middle(LastM)-lengt(LastL)/2-0.1,high(LastH)-2.0+extrawaytext,num2str(double(objectorder(k)))); T=middle(LastM)-lengt(LastL)/2-0.1; Maxi=max(Maxi,T); Mini=min(Mini,T); direct1=0; direct11=1; end if(high(LastH-1)==high(LastH)) high=high(1:LastH-2); indices=indices(1:LastH-2); else high=high(1:LastH-1); indices=indices(1:LastH-1); end LastH=size(high,2); maxim=high(LastH); index=indices(LastH); if(LastH-1>=1) Postmax=high(LastH-1); Postindex=indices(LastH-1); end if(LastH-2>=1) Post2max=high(LastH-2); Post2index=indices(LastH-2); end if(index+1<=Postindex-1) [Betweenmax,Betweenindex]=max(Heights(index+1:Postindex-1)); Betweenindex=Betweenindex+index+1-1; else Betweenmax=Postmax; Betweenindex=Postindex; end if(Betweenmax~=Postmax) Prevmax=Betweenmax; Previndex=Betweenindex; else Prevmax=maxim; Previndex=index; end if(high(LastH)>high(LastH-1)) righttree=1; end high(LastH)=Prevmax; indices(LastH)=Previndex; LastM=size(middle,2); LastL=size(lengt,2); Last=size(L,2); if(LastM-1>=1) middle=middle(1:LastM-1); end if(LastL-1>=1) lengt=lengt(1:LastL-1); end if(Last-1>=1) L=L(1:Last-1); end LastM=size(middle,2); LastL=size(lengt,2); Last=size(L,2); if(Last>0) while(maxim>L(Last)) lengt=lengt(1:Last-1); L=L(1:Last-1); Last=size(L,2); end end LastL=size(lengt,2); middle(LastM)=middle(LastM)+(lengt(LastL)/2); if(Betweenmax~=Postmax) Element=0; else Element=1; middle(LastM)=middle(LastM)-(lengt(LastL)/2); end if(righttree==1 | direct11==1) if(Spec==1) Sp=1; end PrevMAX=L(1); [maxim,index]=max(Heights(NbanFirst+1:number-1)); index=index+NbanFirst+1-1; if(NbanFirst+1<=index-1) [Prevmax,Previndex]=max(Heights(NbanFirst+1:index-1)); Previndex=Previndex+NbanFirst+1-1; else Prevmax=maxim; Previndex=index; end if(index+1<=number-1) [Postmax,Postindex]=max(Heights(index+1:number-1)); Postindex=Postindex+index+1-1; else Postmax=maxim; Postindex=index; end if(index+1<=Postindex-1) [Betweenmax,Betweenindex]=max(Heights(index+1:Postindex-1)); Betweenindex=Betweenindex+index+1-1; else Betweenmax=Postmax; Betweenindex=Postindex; end if(Postindex+1<=number-1) [Post2max,Post2index]=max(Heights(Postindex+1:number-1)); Post2index=Post2index+Postindex+1-1; else Post2max=Postmax; Post2index=Postindex; end rectangle('Position',[PrevMID+(PrevLEN/2),maxim,0.0001,PrevMAX-maxim]); LastM=size(middle,2); LastMID=PrevMID+(PrevLEN/2); PrevMID=LastMID; middle=[]; middle(1)=LastMID; LastM=size(middle,2); high=[]; indices=[]; high=cat(2,high,[Post2max,Postmax,Betweenmax,maxim,Prevmax]); indices=cat(2,indices,[Post2index,Postindex,Betweenindex,index,Previndex]); LastH=size(high,2); L=[]; L=cat(2,L,maxim); Last=size(L,2); lengt=[]; if(Postindex>Previndex) if(M10) text(LastMID-1/2-0.25,maxim-2.0+extrawaytext,num2str(double(objectorder(k+1)))); Mini=min(Mini,LastMID-1/2-0.25); else text(LastMID-1/2-0.1,maxim-2.0+extrawaytext,num2str(double(objectorder(k+1)))); Mini=min(Mini,LastMID-1/2-0.1); end rectangle('Position',[LastMID+1/2,maxim-1+extrawaystick,0.0001,1-extrawaystick]); text(LastMID+1/2-0.1,maxim-2.0+extrawaytext,num2str(double(objectorder(k+2)))); Maxi=max(Maxi,LastMID+1/2-0.1); k=k+2; end PrevLEN=lengt(1); LastL=size(lengt,2); if(Element==1) Element=0; end if(direct11==1) if(NbanFirst+1