Daniel@0: function sC = som_clstruct(Z,varargin) Daniel@0: Daniel@0: %SOM_CLSTRUCT Create a clustering struct or set its field values. Daniel@0: % Daniel@0: % sC = som_clstruct(Z, [argID, value, ...]) Daniel@0: % Daniel@0: % Z = linkage(pdist(sM.codebook)); Daniel@0: % sC = som_clstruct(Z); Daniel@0: % sC = som_clstruct(sC,'coord',som_vis_coords(lattice,msize)); Daniel@0: % sC = som_clstruct(sC,'color',som_colorcode(sM)); Daniel@0: % sC = som_clstruct(sC,'base',sC.base(som_bmus(sM,sD))); Daniel@0: % Daniel@0: % Input and output arguments ([]'s are optional): Daniel@0: % Z (matrix) size clen-1 x 3, where clen is the number of Daniel@0: % base clusters. This is a clustering matrix Daniel@0: % similar to that produced by LINKAGE in Daniel@0: % Statistical Toolbox. See SOM_LINKAGE. Daniel@0: % (struct) clustering struct (as produced by this function) Daniel@0: % [argID, (string) See below. Each pair is the fieldname and Daniel@0: % value] (varies) the value to be given to that field. Daniel@0: % Daniel@0: % sC (struct) clustering struct Daniel@0: % Daniel@0: % The clustering struct is based on the assumption that there Daniel@0: % is a base partitioning of the SOM (or data) which is saved in Daniel@0: % the .base field of the struct. Then a hierarchical clustering Daniel@0: % is applied to this base partitioning. The results are saved to Daniel@0: % .tree field of the struct. Each cluster (base and combined) Daniel@0: % has also three properties: height, coordinate and color, which Daniel@0: % are used in the visualizations. The fields of the struct are: Daniel@0: % .type (string) 'som_clustering' Daniel@0: % .name (string) Identifier for the clustering. Daniel@0: % .tree (matrix) Size clen-1 x 3, as argument Z above. Daniel@0: % .base (vector) Size dlen x 1, the basic groups of data Daniel@0: % forming the base clusters, e.g. as a result Daniel@0: % of partitive clustering. Allowed values are Daniel@0: % 1:clen indicating the base cluster Daniel@0: % to which the data belongs to. Daniel@0: % NaN indicating that the data has Daniel@0: % been ignored in the clustering Daniel@0: % By default [1:clen]. Daniel@0: % .height (vector) Size 2*clen-1 x 1, (clustering) height for each Daniel@0: % cluster. By default 0 for each base cluster and Daniel@0: % .tree(:,3) for the others. Daniel@0: % .coord (matrix) Size 2*clen-1 x *, coordinate for each cluster, Daniel@0: % By default the coordinates are set so that Daniel@0: % the base clusters are ordered on a line, and the Daniel@0: % position of each combined cluster is average of Daniel@0: % the base clusters that constitute it. Daniel@0: % .color (matrix) Size 2*clen-1 x 3, color for each cluster. Daniel@0: % By default the colors are set so that the Daniel@0: % base clusters are ordered on a line, like above, Daniel@0: % and then colors are assigned from the 'hsv' Daniel@0: % colormap to the base clusters. The color Daniel@0: % of each combined cluster is average as above. Daniel@0: % Daniel@0: % Height, coord and color can also be specified in alternate forms: Daniel@0: % 'height' (vector) size 2*clen-1 x 1, if given explicitly Daniel@0: % size clen-1 x 1, specified heights of the Daniel@0: % combined clusters (the base cluster heights Daniel@0: % are all = 0) Daniel@0: % size 0 x 0, default value is used Daniel@0: % 'coord' (matrix) size 2*clen-1 x *, if given explicitly Daniel@0: % size clen x *, to give coordinates for base Daniel@0: % clusters; the coordinate of combined clusters Daniel@0: % are averaged from these Daniel@0: % size dlen x *, to give coordinates of the Daniel@0: % original data: the cluster coordinates are Daniel@0: % averaged from these based on base clusters Daniel@0: % size 0 x 0, default value is used Daniel@0: % 'color' (matrix) as 'coord' Daniel@0: % Daniel@0: % See also SOM_CLPLOT, SOM_CLVALIDITY, SOM_CLGET, SOM_CLLINKAGE. Daniel@0: Daniel@0: % Copyright (c) 2000 by the SOM toolbox programming team. Daniel@0: % Contributed to SOM Toolbox on XXX by Juha Vesanto Daniel@0: % http://www.cis.hut.fi/projects/somtoolbox/ Daniel@0: Daniel@0: % Version 2.0beta juuso 180800 Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: Daniel@0: if isstruct(Z), Daniel@0: base = Z.base; Daniel@0: color = Z.color; Daniel@0: coord = Z.coord; Daniel@0: height = Z.height; Daniel@0: name = Z.name; Daniel@0: Z = Z.tree; Daniel@0: else Daniel@0: base = []; Daniel@0: color = []; Daniel@0: coord = []; Daniel@0: height = []; Daniel@0: name = ''; Daniel@0: end Daniel@0: clen = size(Z,1)+1; Daniel@0: Daniel@0: i=1; Daniel@0: while i<=length(varargin), Daniel@0: argok = 1; Daniel@0: if ischar(varargin{i}), Daniel@0: switch varargin{i}, Daniel@0: case 'tree', i=i+1; Z = varargin{i}; clen = size(Z,1)+1; Daniel@0: case 'base', i=i+1; base = varargin{i}; Daniel@0: case 'color', i=i+1; color = varargin{i}; Daniel@0: case 'coord', i=i+1; coord = varargin{i}; Daniel@0: case 'height', i=i+1; height = varargin{i}; Daniel@0: case 'name', i=i+1; name = varargin{i}; Daniel@0: otherwise argok=0; Daniel@0: end Daniel@0: else argok = 0; Daniel@0: end Daniel@0: if ~argok, disp(['(som_clstruct) Ignoring invalid argument #' num2str(i+1)]); end Daniel@0: i = i+1; Daniel@0: end Daniel@0: Daniel@0: if isempty(base), Daniel@0: dlen = clen; Daniel@0: base = 1:dlen; Daniel@0: else Daniel@0: dlen = length(base); Daniel@0: if any(base)>clen | any(base)<1, error('Incorrect base partition vector.'); end Daniel@0: end Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: %% analysis of hierarchy Daniel@0: Daniel@0: % order of base clusters Daniel@0: order = 2*clen-1; Daniel@0: nonleaves = 1; Daniel@0: while any(nonleaves), Daniel@0: j = nonleaves(1); Daniel@0: ch = Z(order(j)-clen,1:2); Daniel@0: if j==1, oleft = []; else oleft = order(1:(j-1)); end Daniel@0: if j==length(order), oright = []; else oright = order((j+1):length(order)); end Daniel@0: order = [oleft, ch, oright]; Daniel@0: nonleaves = find(order>clen); Daniel@0: end Daniel@0: Daniel@0: % base cluster indeces for each non-base cluster Daniel@0: basecl = cell(clen-1,1); Daniel@0: for i=1:clen-1, Daniel@0: c1 = Z(i,1); if c1>clen, c1 = basecl{c1-clen}; end Daniel@0: c2 = Z(i,2); if c2>clen, c2 = basecl{c2-clen}; end Daniel@0: basecl{i} = [c1 c2]; Daniel@0: end Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: %% set coordinates, color and height and make the struct Daniel@0: Daniel@0: % coordinates Daniel@0: if size(coord,1)==2*clen-1, % this is ok already Daniel@0: else Daniel@0: if size(coord,1)==0, % the default Daniel@0: [dummy,coord] = sort(order); Daniel@0: coord = coord'; Daniel@0: elseif size(coord,1)==dlen & dlen>clen, % coordinates given for original data Daniel@0: codata = coord; Daniel@0: coord = zeros(clen,size(coord,2)); Daniel@0: for i=1:clen, coord(i,:) = mean(codata(find(base==i),:),1); end Daniel@0: end Daniel@0: if size(coord,1)==clen, % average from base clusters Daniel@0: coord = [coord; zeros(clen-1,size(coord,2))]; Daniel@0: for i=1:clen-1, coord(i+clen,:) = mean(coord(basecl{i},:),1); end Daniel@0: else Daniel@0: error('Incorrect coordinate matrix.'); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % color Daniel@0: if size(color,1)==2*clen-1, % this is ok already Daniel@0: else Daniel@0: if size(color,1)==0, % the default Daniel@0: color(order,:) = hsv(length(order)); Daniel@0: elseif size(color,1)==dlen & dlen>clen, % colors given for original data Daniel@0: codata = color; Daniel@0: color = zeros(clen,3); Daniel@0: for i=1:clen, color(i,:) = mean(codata(find(base==i),:),1); end Daniel@0: end Daniel@0: if size(color,1)==clen, % average from base clusters Daniel@0: color = [color; zeros(clen-1,3)]; Daniel@0: for i=1:clen-1, color(i+clen,:) = mean(color(basecl{i},:),1); end Daniel@0: else Daniel@0: error('Incorrect color matrix.'); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: % height Daniel@0: if isempty(height), Daniel@0: height = [zeros(clen,1); Z(:,3)]; Daniel@0: elseif length(height)==clen-1, Daniel@0: if size(height,2)==clen-1, height = height'; end Daniel@0: height = [zeros(clen,1); height]; Daniel@0: elseif length(height)~=2*clen-1, Daniel@0: error('Incorrect height vector.'); Daniel@0: end Daniel@0: Daniel@0: % make the struct Daniel@0: sC = struct('type','som_clustering',... Daniel@0: 'name',name,'base',base,'tree',Z,... Daniel@0: 'color',color,'coord',coord,'height',height); Daniel@0: return; Daniel@0: Daniel@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Daniel@0: