wolffd@0: function h=som_cplane(varargin) wolffd@0: wolffd@0: %SOM_CPLANE Visualize one 2D component plane, U-matrix or color plane. wolffd@0: % wolffd@0: % h=som_cplane(lattice, msize, color, [s], [pos]) wolffd@0: % h=som_cplane(topol, color, [s], [pos]) wolffd@0: % wolffd@0: % som_cplane('hexa', [10 5], 'none'); wolffd@0: % som_cplane('rect', [10 5], 'r'); wolffd@0: % som_cplane(sM.topol, sM.codebook(:,1)); wolffd@0: % U = som_umat(sM); som_cplane('hexaU',sM.topol.msize,U(:)); wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % lattice (string) 'hexa', 'rect' (component planes) wolffd@0: % 'hexaU', 'rectU' (corresponding U-matrices) wolffd@0: % (matrix) defines the patch (see function VIS_PATCH). wolffd@0: % msize (vector) 1x2 vector defines grid size (M=prod(msize)) wolffd@0: % (matrix) Mx2 matrix gives explicit coordinates for each node wolffd@0: % topol (struct) map or topology struct wolffd@0: % color color for the nodes wolffd@0: % (matrix) Mx1 matrix gives indexed colors for the units wolffd@0: % Mx3 matrix of RGB triples gives explicit wolffd@0: % color for each unit wolffd@0: % (Note: in case of U-matrix, the number of color wolffd@0: % values is 4*prod(msize)-2*sum(msize)+1, not prod(msize)) wolffd@0: % (string) ColorSpec gives the same color for each node wolffd@0: % 'none' draws black edges only. wolffd@0: % [s] (matrix) size Mx1, gives individual size scaling for each node wolffd@0: % (scalar) gives the same size for each node, default=1. wolffd@0: % Additional features: see 'type som_cplane' wolffd@0: % This argument is ignored if the lattice is 'rectU' or 'hexaU'. wolffd@0: % [pos] (vector) a 1x2 vector that determines position of origin, wolffd@0: % default is [1 1]. wolffd@0: % wolffd@0: % h (scalar) the object handle for the PATCH object wolffd@0: % wolffd@0: % Axis are set to the 'ij' mode with equal spacing and turned off if wolffd@0: % 'pos' is not given. If 'lattice' is 'rect', 'hexa', 'rectU' or wolffd@0: % 'hexaU' the node (a,b) has coordinates (a,b) (+pos), except on the wolffd@0: % even numbered rows on the 'hexa' and 'hexaU' grids where the wolffd@0: % coordinates are (a,b+0.5) (+pos). wolffd@0: % wolffd@0: % For more help, try 'type som_cplane' or check out online documentation. wolffd@0: % See also SOM_PIEPLANE, SOM_PLOTPLANE, SOM_BARPLANE, VIS_PATCH, wolffd@0: % SOM_VIS_COORDS wolffd@0: wolffd@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: % wolffd@0: % som_cplane wolffd@0: % wolffd@0: % PURPOSE wolffd@0: % wolffd@0: % Visualizes a 2D component plane or u-matrix wolffd@0: % wolffd@0: % SYNTAX wolffd@0: % wolffd@0: % h = som_cplane(topol, color) wolffd@0: % h = som_cplane(lattice, msize, color) wolffd@0: % h = som_cplane(lattice, msize, color) wolffd@0: % h = som_cplane(..., size) wolffd@0: % h = som_cplane(..., size, pos) wolffd@0: % wolffd@0: % DESCRIPTION wolffd@0: % wolffd@0: % Creates some basic visualizations of the SOM grid: the component plane and wolffd@0: % the unified distance matrix. The routine draws the SOM grid as a patch wolffd@0: % object according to the specifications given in the input arguments and wolffd@0: % returns its object handle. wolffd@0: % wolffd@0: % Each unit of the map is presented by a polygon whose color, size, shape wolffd@0: % and location can be specified in various ways. The usual procedure wolffd@0: % is to choose the lattice and map size used in the map training. Then wolffd@0: % the function creates the standard sheet shaped topological wolffd@0: % representation of the map grid with hexagonal or rectangular units. wolffd@0: % When the values from a map codebook component (or from SOM_UMAT) wolffd@0: % are given to the function it produces an indexed coloring for the wolffd@0: % units (as in SURF command). Another possibility is to give a fixed wolffd@0: % RGB color for each unit explicitly. wolffd@0: % wolffd@0: % Special effects (variable unit size, location or shape) can be produced wolffd@0: % giving different types of input variables. wolffd@0: % wolffd@0: % KNOWN BUGS wolffd@0: % wolffd@0: % Using 1x3 or 3x1 grids causes problem, as the MATLAB will treat the color wolffd@0: % information vector 1x3 or 3x1 as a single RGB triple. So, using indexed wolffd@0: % colors is not possible for this particular map size. wolffd@0: % wolffd@0: % It is not possible to specify explicit coordinates for map wolffd@0: % consistig of just one unit as then the msize is interpreted as wolffd@0: % map size. wolffd@0: % wolffd@0: % REQUIRED INPUT ARGUMENTS wolffd@0: % wolffd@0: % Note: M is the number of map units wolffd@0: % wolffd@0: % lattice The basic shape of the map units wolffd@0: % wolffd@0: % (string) 'hexa' or 'rect' creates standard component plane; wolffd@0: % 'hexaU' or 'rectU' creates standard u-matrix. wolffd@0: % (matrix) Lx2 matrix defines the cornes of an arbitary polygon to be used wolffd@0: % as the unit marker. (L is the number of patch vertex: L=6 for wolffd@0: % 'hexa' and L=4 for 'rect') wolffd@0: % wolffd@0: % msize The size of the map grid wolffd@0: % wolffd@0: % (vector) [n1 n2] vector defines the map size (height n1 units, width wolffd@0: % n2 units, total M=n1 x n2 units). The units will be placed to their wolffd@0: % topological locations to form a uniform hexagonal or rectangular grid. wolffd@0: % (matrix) Mx2 matrix defines arbitrary coordinates for the M units wolffd@0: % In this case the argument 'lattice' defines the unit form only. wolffd@0: % wolffd@0: % topol Topology of the map grid wolffd@0: % wolffd@0: % (struct) map or topology struct from which the topology is taken wolffd@0: % wolffd@0: % color Unit colors wolffd@0: % wolffd@0: % (string) (ColorSpec) gives the same color for each unit, 'none' wolffd@0: % draws black unit edges only. wolffd@0: % (vector) Mx1 column vector gives indexed color for each unit using the wolffd@0: % current colormap (see help colormap). wolffd@0: % (matrix) Mx3 matrix of RGB triples as rows gives each unit a fixed color. wolffd@0: % wolffd@0: % OPTIONAL INPUT ARGUMENTS wolffd@0: % wolffd@0: % Note: M is the number of map units. wolffd@0: % Note: if unspecified or given empty values ('' or []) default wolffd@0: % values are used for optional input arguments. wolffd@0: % wolffd@0: % s The size scaling factors for the units wolffd@0: % wolffd@0: % (scalar) scalar gives each unit the same size scaling: wolffd@0: % 0 unit disappears (edges can be seen as a dot). wolffd@0: % 1 by default unit has its normal size (ie. no scaling) wolffd@0: % >1 unit overlaps others wolffd@0: % (matrix) Mx1 double: each unit gets individual size scaling wolffd@0: % wolffd@0: % pos Position of origin wolffd@0: % wolffd@0: % (vector) This argument exists to be able drawing component planes wolffd@0: % in arbitrary locations in a figure. Note the operation: wolffd@0: % if this argument is given, the axis limits setting wolffd@0: % part in the routine is skipped and the limits setting wolffd@0: % will be left to be done by MATLAB's default wolffd@0: % operation. wolffd@0: % wolffd@0: % OUTPUT ARGUMENTS wolffd@0: % wolffd@0: % h (scalar) handle to the created patch object wolffd@0: % wolffd@0: % OBJECT TAGS wolffd@0: % wolffd@0: % One object handle is returned: field Tag is set to wolffd@0: % 'planeC' for component plane wolffd@0: % 'planeU' for U-matrix wolffd@0: % wolffd@0: % FEATURES wolffd@0: % wolffd@0: % There are some extra features in following arguments wolffd@0: % wolffd@0: % size wolffd@0: % - MxL matrix: radial scaling: the distance between wolffd@0: % the center of node m and its kth vertex is scaled by wolffd@0: % s(m,k). wolffd@0: % - Mx1x2 matrix: the uniform scaling is done separately for wolffd@0: % x- and y-directions wolffd@0: % - MxLx2 matrix: the scaling is done separately to x- and y- wolffd@0: % directions for each vertex. wolffd@0: % wolffd@0: % color wolffd@0: % Each vertex may be given individual color. wolffd@0: % The PATCH object interpolates the colors on the wolffd@0: % face if shading is turned to interp. wolffd@0: % - 1xMxL matrix: colormap index for each vertex wolffd@0: % - LxMx3 matrix: RGB color for each vertex wolffd@0: % wolffd@0: % Note: In both cases (size and color) the ordering of the patch wolffd@0: % vertices in the "built-in" patches is the following wolffd@0: % wolffd@0: % 'rect' 'hexa' wolffd@0: % 1 3 1 wolffd@0: % 2 4 5 2 wolffd@0: % 6 3 wolffd@0: % 4 wolffd@0: % wolffd@0: % The color interpolation result seem to depend on the order wolffd@0: % in which the patch vertices are defined. Anyway, it gives wolffd@0: % unfavourable results in our case especially with hexa grid: wolffd@0: % this is a MATLAB feature. wolffd@0: % wolffd@0: % EXAMPLES wolffd@0: % wolffd@0: % m=som_make(rand(100,4),'msize',[6 5]) % make a map wolffd@0: % wolffd@0: % % show the first variable plane using indexed color coding wolffd@0: % wolffd@0: % som_cplane(m.topol.lattice,m.topol.msize,m.codebook(:,1)); wolffd@0: % or som_cplane(m.topol,m.codebook(:,1)); wolffd@0: % or som_cplane(m,m.codebook(:,1)); wolffd@0: % wolffd@0: % % show the first variable using different sized black units wolffd@0: % wolffd@0: % som_cplane(m,'k',m.codebook(:,1)); wolffd@0: % wolffd@0: % % Show the u-matrix. First we have to calculate it. wolffd@0: % % Note: som_umat returns a matrix therefore we write u(:) to get wolffd@0: % % a vector which contains the values in the proper order. wolffd@0: % wolffd@0: % u=som_umat(m); wolffd@0: % som_cplane('hexaU', m.topol.msize, u(:)); wolffd@0: % wolffd@0: % % Show three first variables coded as RGB colors wolffd@0: % % and turn the unit edges off wolffd@0: % wolffd@0: % h=som_cplane(m, m.codebook(:,1:3),1) wolffd@0: % set(h,'edgecolor','none'); wolffd@0: % wolffd@0: % % Try this! (see section FEATURES) wolffd@0: % wolffd@0: % som_cplane('rect',[5 5],'none',rand(25,4)); wolffd@0: % som_cplane('rect',[5 5],rand(1,25,4)); wolffd@0: % wolffd@0: % SEE ALSO wolffd@0: % wolffd@0: % som_barplane Visualize the map prototype vectors as bar diagrams wolffd@0: % som_plotplane Visualize the map prototype vectors as line graphs wolffd@0: % som_pieplane Visualize the map prototype vectors as pie charts wolffd@0: % som_umat Compute unified distance matrix of self-organizing map wolffd@0: % vis_patch Define the basic patches used in som_cplane wolffd@0: % som_vis_coords The default 'hexa' and 'rect' coordinates in visualizations wolffd@0: wolffd@0: % Copyright (c) 1999-2000 by the SOM toolbox programming team. wolffd@0: % http://www.cis.hut.fi/projects/somtoolbox/ wolffd@0: wolffd@0: % Version 2.0beta Johan 061099 juuso 151199 juuso 070600 wolffd@0: wolffd@0: %%% Check & Init arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: [nargin, lattice, msize, color, s, pos]=vis_planeGetArgs(varargin{:}); wolffd@0: error(nargchk(3, 5, nargin)); % check no. of input args is correct wolffd@0: wolffd@0: %% Translation? wolffd@0: wolffd@0: if nargin < 5 | isempty(pos) wolffd@0: pos=NaN; % "no translation" flag wolffd@0: elseif ~vis_valuetype(pos,{'1x2'}), wolffd@0: error('Position of origin has to be given as an 1x2 vector.'); wolffd@0: end wolffd@0: wolffd@0: %% Patchform %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: switch class(lattice) wolffd@0: case 'char' % built-in patchforms wolffd@0: pos=pos-1; wolffd@0: switch lattice wolffd@0: case {'hexa', 'hexaU'} wolffd@0: patchform=vis_patch('hexa'); wolffd@0: case {'rect', 'rectU'} wolffd@0: patchform=vis_patch('rect'); wolffd@0: otherwise wolffd@0: error([ 'Lattice ' lattice ' not implemented!']); wolffd@0: end wolffd@0: case { 'double', 'sparse'} wolffd@0: if vis_valuetype(lattice,{'nx2'}), wolffd@0: patchform=lattice; % users patchform wolffd@0: lattice='rect'; wolffd@0: else wolffd@0: error('Patchform matrix has wrong size'); wolffd@0: end wolffd@0: otherwise wolffd@0: error('String or matrix expected for lattice.'); wolffd@0: end wolffd@0: wolffd@0: l=size(patchform,1); % number of vertices wolffd@0: planeType=lattice(end); % 'U' if umatrix otherwise something else wolffd@0: wolffd@0: if ~vis_valuetype(msize,{ '1x2', 'nx2'}), wolffd@0: error('msize has to be given as 1x2 or nx2 vectors.'); wolffd@0: end wolffd@0: wolffd@0: %% msize or coordinates %%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: if size(msize,1)>1 wolffd@0: % msize is coordinate matrix Nx2? wolffd@0: wolffd@0: if planeType == 'U', % don't accept u-matrix wolffd@0: error('U-matrix visualization doesn''t work with free coordinates.'); wolffd@0: end wolffd@0: wolffd@0: % set number of map unit and unit coordinates wolffd@0: munits=size(msize,1); wolffd@0: unit_coords=msize; msize=[munits 1]; wolffd@0: wolffd@0: if isnan(pos), % no translation is done here wolffd@0: pos=[0 0]; % using [0 0] in order to prevent wolffd@0: end % axis tightening in wolffd@0: % vis_PlaneAxisProperties (arbitary coords!) wolffd@0: else wolffd@0: % msize is built-in lattice wolffd@0: wolffd@0: unit_coords=som_vis_coords(lattice,msize); wolffd@0: wolffd@0: % Calculate matrices x and y which 'moves' nodes wolffd@0: % to the correct positions: wolffd@0: % For U-matrix, the size has to be recalculated wolffd@0: if planeType == 'U', wolffd@0: xdim=2*msize(1)-1;ydim=2*msize(2)-1; wolffd@0: else wolffd@0: xdim=msize(1);ydim=msize(2); wolffd@0: end wolffd@0: munits=xdim*ydim; wolffd@0: wolffd@0: % Feature warning wolffd@0: if munits == 3 wolffd@0: warning('Problems with 1x3 and 3x1 maps. See documentation.'); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: %% Color matrix %%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: if ~isnumeric(color) & ~ischar(color), wolffd@0: error('Color matrix is invalid.'); wolffd@0: else wolffd@0: d=size(color); wolffd@0: switch length(d) wolffd@0: case 2 %% Flat colors wolffd@0: if ischar(color) % Check for string 'none' wolffd@0: if strcmp(color,'none'), wolffd@0: color=NaN; wolffd@0: end wolffd@0: else wolffd@0: if ~(d(1)== 1 & d(2) == 3) & ... wolffd@0: ~(d(1) == munits & (d(2)==1 | d(2)==3)) wolffd@0: error('Color data matrix has wrong size.'); wolffd@0: elseif d(1)~=1 & d(2)==3 wolffd@0: if any(color>1 | color<0) wolffd@0: error('Color data matrix has invalid RGB values.'); wolffd@0: end wolffd@0: color=reshape(color,[1 munits 3]); % RGB colors wolffd@0: elseif d(2)==1 wolffd@0: color=color'; % indexed wolffd@0: end wolffd@0: end wolffd@0: case 3 %% Interpolated colors wolffd@0: if d(1) == 1 & d(2) == munits & d(3) == l, wolffd@0: color=reshape(color, l, munits); wolffd@0: elseif ~(d(1) == l & d(2) == munits & d(3) == 3) wolffd@0: error('Color data matrix has wrong size.'); wolffd@0: end wolffd@0: otherwise wolffd@0: error('Color data matrix has too many dimensions.'); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: %% Size matrix? %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: if nargin < 4 | isempty(s), wolffd@0: s=1; % default value for s (no scaling) wolffd@0: elseif ~isnumeric(s) wolffd@0: error('Size matrix is not numeric.'); wolffd@0: end wolffd@0: wolffd@0: %%Determine the type of size matrix wolffd@0: d=size(s); wolffd@0: switch length(d) wolffd@0: case 2 wolffd@0: if (d(1)==1 & d(2)==1), wolffd@0: % Each node gets the same, uniform scaling. wolffd@0: s=s'; sx=s; sy=s; wolffd@0: elseif (d(1)==munits & d(2)==l), wolffd@0: % Each vertex is scaled radially respetc to the wolffd@0: % node center. wolffd@0: s=s'; sx=s; sy=s; wolffd@0: elseif d(1)==munits & d(2)==1 wolffd@0: % Each node gets an individual uniform scaling. wolffd@0: sx=repmat(s',l,1); sy=sx; wolffd@0: else wolffd@0: error('Size matrix has wrong size.'); wolffd@0: end wolffd@0: case 3 wolffd@0: if d(1)==munits & d(2)==1 & d(3)==2, wolffd@0: % Each node is individually and uniformly wolffd@0: % scaled separately to x- and y-directions. wolffd@0: sx=repmat(shiftdim(s(:,:,1))',l,1); wolffd@0: sy=repmat(shiftdim(s(:,:,2))',l,1); wolffd@0: elseif d(1)==munits & d(2)==l & d(3)==2, wolffd@0: % Each vertex is scaled separately to x- and y-directions wolffd@0: % with respect to the node center. wolffd@0: sx=shiftdim(s(:,:,1))'; wolffd@0: sy=shiftdim(s(:,:,2))'; wolffd@0: else wolffd@0: error('Size matrix has wrong size.'); wolffd@0: end wolffd@0: otherwise wolffd@0: error('Size matrix has too many dimensions.'); wolffd@0: end wolffd@0: wolffd@0: % Size zero would cause division by zero. eps is as good (node disappears) wolffd@0: % I tried first NaN, it works well otherwise, but the node is wolffd@0: % then not on the axis and some commands may the work oddly. wolffd@0: % The edge may be visible, though. wolffd@0: wolffd@0: sx(sx==0)=eps; wolffd@0: sy(sy==0)=eps; wolffd@0: wolffd@0: % Rescale sizes for u-matrix wolffd@0: if planeType=='U', wolffd@0: sx=sx/2;sy=sy/2; wolffd@0: end wolffd@0: wolffd@0: %%%% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: % Making grid. %%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: % Translation for each patch wolffd@0: wolffd@0: x=repmat(unit_coords(:,1)',l,1); wolffd@0: y=repmat(unit_coords(:,2)',l,1); wolffd@0: wolffd@0: % patch vertex coordiantes wolffd@0: wolffd@0: nx=repmat(patchform(:,1),1,munits); wolffd@0: ny=repmat(patchform(:,2),1,munits); wolffd@0: wolffd@0: % NB: The hexagons are not uniform in order to get even wolffd@0: % y-coordinates for the nodes. This is handled by setting _axis scaling_ wolffd@0: % so that the hexa-nodes look like uniform hexagonals. See wolffd@0: % vis_PlaneAxisProperties wolffd@0: wolffd@0: %% Make and scale the final input for PATCH: wolffd@0: wolffd@0: % 1: combine translation and scaling of each patch wolffd@0: x=(x./sx+nx).*sx; y=(y./sy+ny).*sy; wolffd@0: wolffd@0: %% 2: translation of origin (pos) wolffd@0: if ~isnan(pos) wolffd@0: x=x+pos(1);y=y+pos(2); % move upper left corner wolffd@0: end % to pos wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: %% Set axes properties wolffd@0: %% Command view([0 90]) shows the map in 2D properly oriented wolffd@0: wolffd@0: ax=newplot; % set new plot wolffd@0: vis_PlaneAxisProperties(ax,lattice,msize,pos); wolffd@0: wolffd@0: %% Draw the map! wolffd@0: wolffd@0: if ~isnan(color) wolffd@0: h_=patch(x,y,color); wolffd@0: else wolffd@0: h_=patch(x,y,'k'); % empty grid wolffd@0: set(h_,'FaceColor','none'); wolffd@0: end wolffd@0: wolffd@0: %% Set object tag wolffd@0: wolffd@0: if planeType=='U' wolffd@0: set(h_,'Tag','planeU'); wolffd@0: else wolffd@0: set(h_,'Tag','planeC'); wolffd@0: end wolffd@0: wolffd@0: %%% Build output %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: if nargout>0, h=h_; end % Set h only, wolffd@0: % if there really is output wolffd@0: