somtoolbox2/som_order_cplanes.m
4dbef185
 function P = som_order_cplanes(sM, varargin)
 
 %SOM_ORDER_CPLANES Orders and shows the SOM component planes.
 %
 % P = som_order_cplanes(sM, [[argID,] value, ...])
 %
 %  som_order_cplanes(sM);
 %  som_order_cplanes(sM,'comp',1:30,'simil',C,'pca');
 %  P = som_order_cplanes(sM);
 %
 %  Input and output arguments ([]'s are optional): 
 %   sM       (struct) map or data struct
 %            (matrix) a data matrix, size * x dim
 %   [argID,  (string) See below. The values which are unambiguous can
 %    value]  (varies) be given without the preceeding argID.
 %
 %   P        (matrix) size n x * (typically n x 2), the projection coordinates
 %   
 % Here are the valid argument IDs and corresponding values. The values
 % which are unambiguous (marked with '*') can be given without the
 % preceeding argID.
 %   'comp'    (vector) size 1 x n, which components to project, 1:dim by default
 %   'simil'  *(string) similarity measure to use 
 %                      'corr'        linear correlation between component planes
 %                      'abs(corr)'   absolute value of correlation (default)
 %                      'umat'        as 'abs(corr)' but calculated from U-matrices
 %                      'mutu'        mutual information (not implemented yet)
 %             (matrix) size n x n, a similarity matrix to be used             
 %   'proj'   *(string) projection method to use: 'SOM' (default), 
 %                      'pca', 'sammon', 'cca', 'order', 'ring'
 %   'msize'   (vector) size of the SOM that is used for projection
 %   'show'   *(string) how visualization is done: 'planes' (default), 
 %                      'names', or 'none'
 %   'mask'    (vector) dim x 1, the mask to use, ones(dim,1) by default
 %   'comp_names' (cell array) of strings, size dim x 1, the component names
 %
 % The visualized objects have a callback associated with them: by
 % clicking on the object, the index and name of the component are printed
 % to the standard output.
 % 
 % See also SOM_SHOW.
 
 % Copyright (c) 2000 by the SOM toolbox programming team.
 % Contributed to SOM Toolbox on June 16th, 2000 by Juha Vesanto
 % http://www.cis.hut.fi/projects/somtoolbox/
 
 % Version 2.0beta juuso 120600 070601
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% check arguments
 
 % sM
 if isstruct(sM), 
   switch sM.type
   case 'som_map', 
     D = sM.codebook; dim = size(D,2); cnames = sM.comp_names; mask = sM.mask; 
     ismap = 1; 
   case 'som_data', 
     D = sM.data; dim = size(D,2); cnames = sM.comp_names; mask = ones(dim,1); 
     ismap = 0; 
   otherwise, error('Invalid first argument.');
   end                  
 else
   D = sM; 
   dim = size(D,2); mask = ones(dim,1);
   cnames = cell(dim,1); 
   for i = 1:dim, cnames{i} = sprintf('Variable%d',i); end
   ismap = 0; 
 end
 
 % defaults
 comps = 1:dim; 
 simil = 'abs(corr)';
 proj = 'SOM'; 
 show = 'planes'; 
 mapsize = NaN;
 
 % varargin
 i=1;
 while i<=length(varargin),
   argok = 1;
   if ischar(varargin{i}),
     switch varargin{i},
      % argument IDs
      case 'mask',       i=i+1; mask = varargin{i};
      case 'comp_names', i=i+1; cnames = varargin{i};
      case 'comp',       i=i+1; comps = varargin{i}; 
      case 'proj',       i=i+1; proj = varargin{i}; 
      case 'show',       i=i+1; show = varargin{i}; 
      case 'simil',      i=i+1; simil = varargin{i}; 
      case 'msize',      i=i+1; mapsize = varargin{i};
      % unambiguous values
      case {'corr','abs(corr)','umat','mutu'}, simil = varargin{i}; 
      case {'SOM','pca','sammon','cca','order','ring'}, proj = varargin{i}; 
      case {'planes','names','none'}, show = varargin{i}; 
      otherwise argok=0;
     end
   else
     argok = 0;
   end
   if ~argok,
     disp(['(som_order_cplanes) Ignoring invalid argument #' num2str(i+1)]);
   end
   i = i+1;
 end
 
 if strcmp(show,'planes') & ~ismap, 
   warning('Given data is not a map: using ''names'' visualization.'); 
   show = 'names'; 
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% similarity matrix
 
 fprintf(1,'Calculating similarity matrix\n');
 
 % use U-matrix
 if strcmp(simil,'umat'), 
   if ~ismap, error('Given data is not a map: cannot use U-matrix similarity.'); end
   U = som_umat(sM);
   D = zeros(prod(size(U)),dim); 
   m = zeros(dim,1);
   for i=1:dim, m=m*0; m(i)=1; U = som_umat(sM,'mask',m); D(:,i) = U(:); end
 end
 
 % components
 D = D(:,comps); 
 cnames = cnames(comps);
 mask = mask(comps);
 dim = length(comps);
   
 % similarity matrix
 if ischar(simil), 
   switch simil, 
   case {'corr','abs(corr)','umat'}, 
     A = zeros(dim);
     me = zeros(1,dim);
     for i=1:dim, 
         me(i) = mean(D(isfinite(D(:,i)),i)); D(:,i) = D(:,i) - me(i); 
     end  
     for i=1:dim, 
       for j=i:dim, 
         c = D(:,i).*D(:,j); c = c(isfinite(c));
         A(i,j) = sum(c)/length(c); A(j,i) = A(i,j); 
       end
     end
     s = diag(A); 
     A = A./sqrt(s*s');
     switch simil, 
     case {'abs(corr)','umat'}, A = abs(A); 
     case 'corr', A = A + 1; 
     end
   case 'mutu', 
     error('Mutual information not implemented yet.');
   end
 else
   A = simil; 
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% projection
 
 fprintf(1,'Projection\n');
 
 mu = 2*dim; 
 
 switch proj, 
  case 'SOM',
 
   if isnan(mapsize), 
     sMtmp = som_randinit(A,'munits',mu); 
     msize = sMtmp.topol.msize; 
   else 
     msize = mapsize; 
   end
 
   sM2 = som_make(A,'msize',msize,'rect','tracking',0);
   bm  = assign_unique_bm(sM2,A);
   Co  = som_unit_coords(sM2);
   P   = Co(bm,:);
 
  case 'ring', 
 
   if isnan(mapsize), msize = [1 mu]; else msize = mapsize; end
 
   sM2 = som_make(A,'msize',msize,'cyl','rect','tracking',0);
   bm  = assign_unique_bm(sM2,A);
   Co  = som_unit_coords(sM2);
   P   = Co(bm,[1 3]);   
   
  case 'order',
 
   if isnan(mapsize), msize = [1 mu]; else msize = mapsize; end
 
   sM2 = som_make(A,'msize',msize,'tracking',0);
   bm  = assign_unique_bm(sM2,A);
   [dummy,i] = sort(bm); 
   [dummy,P] = sort(i);
   if size(P,2)>1, P = P'; end
   if size(P,2)==1, P(:,2) = zeros(length(P),1); end
 
  case {'pca','sammon','cca'}, 
   P = pcaproj(A,2);  
   if strcmp(proj,'sammon'), P = sammon(A,P,50,'steps');
   elseif strcmp(proj,'cca'), P = cca(A,P,50);
   end
 
 end
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% visualization
 
 if ~strcmp(show,'none'), 
   fprintf(1,'Visualization\n');
   cla
   hold on
   if strcmp(show,'planes')
     s = findscaling(sM.topol.msize,P);
     for i=1:dim, 
       C = som_normcolor(D(:,i));
       if strcmp(simil,'umat'), 
 	h=som_cplane([sM.topol.lattice 'U'],sM.topol.msize,C,1,s*P(i,:));
       else
 	h=som_cplane(sM,C,1,s*P(i,:)); 
       end 
       set(h,'edgecolor','none','Userdata',sprintf('[%d] %s',i,cnames{i}));
       set(h,'ButtonDownFcn','fprintf(1,''%s\n'',get(gco,''UserData''))');
     end
   else 
     s=1; 
     a=[min(P(:,1))-1 max(P(:,1))+1 min(P(:,2))-1-3 max(P(:,2))+1-3];
     axis(s*a);
   end
   h=text(s*P(:,1),s*P(:,2)-3,cnames);
   for i=1:length(h), set(h(i),'Userdata',sprintf('[%d] %s',i,cnames{i})); end
   set(h,'ButtonDownFcn','fprintf(1,''%s\n'',get(gco,''UserData''))');
   hold off
 
   axis on; axis equal; axis tight; set(gca,'XTick',[],'YTick',[],'Box','on');
 end
 
 return; 
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
 %% subfunctions
 
 function bm = assign_unique_bm(sM,D)
 
   munits = size(sM.codebook,1);
   [dlen dim] = size(D);
   margin = max(0,dlen-munits);
 
   [bm,qers] = som_bmus(sM,D); 
   bmi=ones(dim,1);  
   hits = som_hits(sM,D); 
   mult = find(hits>1); 
   while any(mult) & sum(hits(mult))-length(mult)>margin, 
     choices = find(bm==mult(1)); 
     while length(choices)>1,
       [dummy,mv] = max(qers(choices)); mv = choices(mv);
       [mv_to,q] = som_bmus(sM,D(mv,:),bmi(mv)); 
       bmi(mv)=bmi(mv)+1; qers(mv) = q; bm(mv) = mv_to;
       choices = find(bm==mv_to);
     end
     for i=1:length(hits), hits(i)=sum(bm==i); end
     mult = find(hits>1);
   end
   return;
   
 function s = findscaling(msize,P)
 
   d1 = median(abs(diff(unique(sort(P(:,1))))));
   d2 = median(abs(diff(unique(sort(P(:,2))))));
   if d1>0, s1 = 1.5*msize(2)/d1; else s1 = 0; end
   if d2>0, s2 = 1.5*msize(1)/d2; else s2 = 0; end
   s = max(s1,s2);
   if s==0, s=1; end
   return; 
 
 function alternative_SOM_plane_vis(sT,bm,simil,D,cnames)
 
   clf
   for i=1:size(D,2), 
     subplot(sT.msize(2),sT.msize(1),bm(i));
     if strcmp(simil,'umat'), h=som_cplane([sT.lattice 'U'],sT.msize,D(:,i));
     else h=som_cplane(sT,D(:,i)); 
     end
     set(h,'edgecolor','none');
     title(cnames{i});
     axis off
   end    
   return;