somtoolbox2/som_clplot.m
4dbef185
 function h = som_clplot(sC,varargin)
 
 %SOM_CLPLOT Visualize clustering.
 % 
 % h = som_clplot(sC, [[argID,] value, ...])
 % som_clplot(sM, part)
 % 
 %   som_clplot(sC);
 %   som_clplot(som_clstruct(Z))
 %   som_clplot(sC,sM);
 %   som_clplot(sC,'coord',P);
 %   som_clplot(sC,'dendrogram',[1 1 1 1 0 0 1 1 0 0 1]);
 %   som_clplot(sC,'linewidth',10);
 %   som_clplot(sC,'size',10);
 %   som_clplot(sM,part);
 %    
 %  Input and output arguments ([]'s are optional):    
 %   sC        (struct) clustering struct, as produced by SOM_CLSTRUCT
 %   [argID,   (string) See below. Each pair is the fieldname and 
 %    value]   (varies) the value to be given to that field.
 %   sM        (struct) map struct
 %   part      (vector) length = munits, partitioning for the map
 %
 %   h         (vector) handles to the arcs between 
 %   
 % Here are the valid argument IDs and corresponding values. The values 
 % which are unambiguous (marked with '*') can be given without the
 % preceeding argID.
 %   'linecolor' (string) color of the arc lines, 'k' by default
 %               (vector) size 1 x 3
 %   'linewidth' (scalar) width of the arc lines
 %   'size'      (vector) length 2*clen-1, sizes for each of the 
 %                        cluster markers
 %               (scalar) this size is used for all cluster markers
 %   'dendrogram'(vector) size 2*clen-1, indicates which clusters 
 %                        are shown in the dendrogram
 %              *(string) 'on' or 'off' ('on' by default)
 %   'coord'     (matrix) size dlen x odim, the coordinates
 %                        for the data. If odim<=2, these are used as is.
 %                        Otherwise a 2-dimensional PCA-projection is
 %                        first made (see function PCAPROJ). These
 %                        coordinates are applied also to the clusters.
 %              *(struct) data struct: as above
 %                        map or topology struct: the coordinates given 
 %                        by SOM_VIS_COORDS are used for the data 
 %   'color'     (matrix) size dlen x 3, color for each data. By
 %                        default the colors defined for base 
 %                        clusters are used (sC.color(sC.base,:)).
 %                        For ignored data figure background color is used. 
 %               (vector) size dlen x 1, indexed colors are used
 %
 % See also SOM_CLSTRUCT, SOM_LINKAGE, SOM_CLPRUNE, LINKAGE, DENDROGRAM.
 
 % Copyright (c) 2000 by Juha Vesanto
 % Contributed to SOM Toolbox on XXX by Juha Vesanto
 % http://www.cis.hut.fi/projects/somtoolbox/
  
 % Version 2.0beta juuso 180600
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% read the arguments
 
 % sC
 if strcmp(sC.type,'som_map'), 
   base = varargin{1}; 
   clen = length(unique(base(isfinite(base)))); 
   Z = ones(clen-1,3); 
   Z(:,1) = randperm(clen-1)'; 
   Z(:,2) = [clen:2*clen-2]'; 
   Z(:,3) = [1:clen-1]'; 
   sT = sC;
   sC = som_clstruct(Z,'base',varargin{1}); 
   h = som_clplot(sC,'coord',sT,'dendrogram','off',varargin{2:end}); 
   return; 
 end
 clen = size(sC.tree,1)+1; 
 
 % varargin
 show = 'on'; 
 markersize = 10; 
 linecolor = 'k'; 
 linewidth = 1; 
 datacoord = []; 
 datacolor = []; 
 
 i=1; 
 while i<=length(varargin), 
   argok = 1; 
   if ischar(varargin{i}), 
     switch varargin{i}, 
      case 'dendrogram', i=i+1; show = varargin{i}; 
      case 'size',       i=i+1; markersize = varargin{i}; 
      case 'linecolor',  i=i+1; linecolor = varargin{i}; 
      case 'linewidth',  i=i+1; linewidth = varargin{i};
      case 'color',      i=i+1; datacolor = varargin{i};
      case 'coord',      i=i+1; datacoord = varargin{i};
      case {'on','off'}, show = varargin{i}; 
      otherwise argok=0; 
     end
   elseif isstruct(varargin{i}), datacoord = varargin{i}; 
   else argok = 0; 
   end
   if ~argok, disp(['(som_clplot) Ignoring invalid argument #' num2str(i+1)]); end
   i=i+1;
 end
 
 % markersize
 if length(markersize)==1, markersize = ones(2*clen-1,1)*markersize; end
 
 % datacoord
 if ~isempty(datacoord),
   if isstruct(datacoord), 
     switch datacoord.type, 
      case 'som_map',   datacoord = datacoord.topol;
      case 'som_topol', %nil 
      case 'som_data',  datacoord = datacoord.data;
      otherwise,        datacoord = []; 
     end  
   end
   if isstruct(datacoord), 
     sC = som_clstruct(sC,'coord',som_vis_coords(datacoord.lattice,datacoord.msize));
   else
     [dlen dim] = size(datacoord);
     if dim>2, datacoord = pcaproj(datacoord,2); end
     sC = som_clstruct(sC,'coord',datacoord);
   end
 end
 
 % show
 if ischar(show), show = strcmp(show,'on'); end
 if prod(size(show)) == 1, show = ones(2*clen-1,1)*show; end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% initialize values
 
 % find the children to show for each cluster
 sTree0 = struct('parent',0,'children',[]); 
 sTree = sTree0; 
 for i=2:(2*clen-1), sTree(i) = sTree0; end
 for i=(clen+1):(2*clen-1), 
   if isfinite(sC.tree(i-clen,3)), 
     ch = sC.tree(i-clen,1:2);
     sTree(i).children = ch; 
     for j=1:length(ch), sTree(ch(j)).parent = i; end
   end  
 end
 if any(show==0), % some clusters are not shown
   for i=(clen+1):(2*clen-1), 
     if ~show(i),
       p = sTree(i).parent;
       ch = sTree(i).children;
       if p, 
 	j = find(sTree(p).children == i);
 	sTree(p).children = [sTree(p).children([1:(j-1),(j+1):end]), ch]; 
 	for j=1:length(ch), sTree(ch(j)).parent = p; end
       end
     end    
   end  
 end
 
 % the arcs
 lfrom = []; lto = []; ladd = [];
 for i=(clen+1):(2*clen-1),   
   if show(i), 
     ch = sTree(i).children'; 
     %ch = ch(find(show(ch)==1)); 
     lfrom = [lfrom; i*ones(length(ch),1)]; 
     lto = [lto; ch];     
   end
 end
 
 % infinite height
 %isinf = ~isfinite(sC.height); 
 %sC.height(isinf) = 2*max(sC.height(~isinf)); 
 
 % the coordinates of the arcs
 Co = [sC.coord, sC.height];
 if size(Co,2)==2, 
   Lx = [Co(lfrom,1),   Co(lto,1),     Co(lto,1)];
   Ly = [Co(lfrom,end), Co(lfrom,end), Co(lto,end)];
   Lz = []; 
 else
   Lx = [Co(lfrom,1),   Co(lto,1),     Co(lto,1)];
   Ly = [Co(lfrom,2),   Co(lto,2),     Co(lto,2)];
   Lz = [Co(lfrom,end), Co(lfrom,end), Co(lto,end)];
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% plot
 
 washold = ishold; 
 if ~washold, cla; hold on; end
 
 % plot data
 if ~isempty(datacoord), 
   if isempty(datacolor),
     nancolor = get(gcf,'Color'); 
     Col = nancolor(ones(length(sC.base),1),:);
     ind = find(isfinite(sC.base)); 
     Col(ind,:) = sC.color(sC.base(ind),:); 
   elseif size(datacolor,2)==1, Col = som_normcolor(datacolor,jet); 
   else Col = datacolor;     
   end    
   if isstruct(datacoord), som_cplane(datacoord,Col);
   else som_grid('rect',[length(sC.base) 1],'line','none',...
 		'Coord',datacoord,'Markercolor',Col); 
   end
 end
 
 h = []; 
 if any(show), 
 
   % plot the lines
   if isempty(Lz), 
     h = line(Lx',Ly','color',linecolor,'linewidth',linewidth); 
   else 
     h = line(Lx',Ly',Lz','color',linecolor,'linewidth',linewidth); 
     if ~washold, view(3); end
     rotate3d on
   end
   
   % plot the nodes
   inds = find(show); 
   som_grid('rect',[length(inds) 1],'line','none',...
 	   'Coord',Co(inds,:),...
 	   'Markercolor',sC.color(inds,:),...
 	   'Markersize',markersize(inds));
 end
 
 if ~washold, hold off, end
 
 return;
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%