diff toolboxes/MIRtoolbox1.3.2/somtoolbox/som_unit_coords.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/MIRtoolbox1.3.2/somtoolbox/som_unit_coords.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,252 @@
+function Coords = som_unit_coords(topol,lattice,shape)
+
+%SOM_UNIT_COORDS Locations of units on the SOM grid. 
+%
+% Co = som_unit_coords(topol, [lattice], [shape])
+% 
+%  Co = som_unit_coords(sMap);
+%  Co = som_unit_coords(sMap.topol);
+%  Co = som_unit_coords(msize, 'hexa', 'cyl');
+%  Co = som_unit_coords([10 4 4], 'rect', 'toroid');
+%
+%  Input and output arguments ([]'s are optional): 
+%   topol              topology of the SOM grid
+%             (struct) topology or map struct
+%             (vector) the 'msize' field of topology struct
+%   [lattice] (string) map lattice, 'rect' by default
+%   [shape]   (string) map shape, 'sheet' by default
+%
+%   Co        (matrix, size [munits k]) coordinates for each map unit    
+%
+% For more help, try 'type som_unit_coords' or check out online documentation.
+% See also SOM_UNIT_DISTS, SOM_UNIT_NEIGHS.
+
+%%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% som_unit_coords
+%
+% PURPOSE
+%
+% Returns map grid coordinates for the units of a Self-Organizing Map.
+%
+% SYNTAX
+%
+%  Co = som_unit_coords(sTopol);
+%  Co = som_unit_coords(sM.topol);
+%  Co = som_unit_coords(msize);
+%  Co = som_unit_coords(msize,'hexa');
+%  Co = som_unit_coords(msize,'rect','toroid');
+%
+% DESCRIPTION
+%
+% Calculates the map grid coordinates of the units of a SOM based on 
+% the given topology. The coordinates are such that they can be used to
+% position map units in space. In case of 'sheet' shape they can be 
+% (and are) used to measure interunit distances. 
+%
+% NOTE: for 'hexa' lattice, the x-coordinates of every other row are shifted 
+% by +0.5, and the y-coordinates are multiplied by sqrt(0.75). This is done 
+% to make distances of a unit to all its six neighbors equal. It is not 
+% possible to use 'hexa' lattice with higher than 2-dimensional map grids.
+%
+% 'cyl' and 'toroid' shapes: the coordinates are initially determined as 
+% in case of 'sheet' shape, but are then bended around the x- or the 
+% x- and then y-axes to get the desired shape. 
+% 
+% POSSIBLE BUGS
+%
+% I don't know if the bending operation works ok for high-dimensional
+% map grids. Anyway, if anyone wants to make a 4-dimensional
+% toroid map, (s)he deserves it.
+%
+% REQUIRED INPUT ARGUMENTS
+% 
+%  topol          Map grid dimensions.
+%        (struct) topology struct or map struct, the topology 
+%                 (msize, lattice, shape) of the map is taken from 
+%                 the appropriate fields (see e.g. SOM_SET)
+%        (vector) the vector which gives the size of the map grid
+%                 (msize-field of the topology struct).
+%  
+% OPTIONAL INPUT ARGUMENTS 
+% 
+%  lattice (string) The map lattice, either 'rect' or 'hexa'. Default
+%                   is 'rect'. 'hexa' can only be used with 1- or 
+%                   2-dimensional map grids.
+%  shape   (string) The map shape, either 'sheet', 'cyl' or 'toroid'. 
+%                   Default is 'sheet'. 
+%
+% OUTPUT ARGUMENTS
+%
+%  Co   (matrix) coordinates for each map units, size is [munits k] 
+%                where k is 2, or more if the map grid is higher
+%                dimensional or the shape is 'cyl' or 'toroid'
+%
+% EXAMPLES
+%
+% Simplest case:
+%  Co = som_unit_coords(sTopol);
+%  Co = som_unit_coords(sMap.topol);
+%  Co = som_unit_coords(msize);
+%  Co = som_unit_coords([10 10]);
+%
+% If topology is given as vector, lattice is 'rect' and shape is 'sheet'
+% by default. To change these, you can use the optional arguments:
+%  Co = som_unit_coords(msize, 'hexa', 'toroid');
+%
+% The coordinates can also be calculated for high-dimensional grids:
+%  Co = som_unit_coords([4 4 4 4 4 4]);
+%
+% SEE ALSO
+% 
+%  som_unit_dists    Calculate interunit distance along the map grid.
+%  som_unit_neighs   Calculate neighborhoods of map units.
+
+% Copyright (c) 1997-2000 by the SOM toolbox programming team.
+% http://www.cis.hut.fi/projects/somtoolbox/
+
+% Version 1.0beta juuso 110997
+% Version 2.0beta juuso 101199 070600
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check arguments 
+
+error(nargchk(1, 3, nargin));
+
+% default values
+sTopol = som_set('som_topol','lattice','rect');
+
+% topol
+if isstruct(topol), 
+  switch topol.type, 
+  case 'som_map', sTopol = topol.topol;
+  case 'som_topol', sTopol = topol;
+  end
+elseif iscell(topol), 
+  for i=1:length(topol), 
+    if isnumeric(topol{i}), sTopol.msize = topol{i}; 
+    elseif ischar(topol{i}),  
+      switch topol{i}, 
+      case {'rect','hexa'}, sTopol.lattice = topol{i}; 
+      case {'sheet','cyl','toroid'}, sTopol.shape = topol{i}; 
+      end
+    end
+  end
+else
+  sTopol.msize = topol;
+end
+if prod(sTopol.msize)==0, error('Map size is 0.'); end
+
+% lattice
+if nargin>1 & ~isempty(lattice) & ~isnan(lattice), sTopol.lattice = lattice; end
+
+% shape 
+if nargin>2 & ~isempty(shape) & ~isnan(shape), sTopol.shape = shape; end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Action
+
+msize = sTopol.msize;
+lattice = sTopol.lattice;
+shape = sTopol.shape;
+
+% init variables
+
+if length(msize)==1, msize = [msize 1]; end
+munits = prod(msize);
+mdim = length(msize);
+Coords = zeros(munits,mdim);
+
+% initial coordinates for each map unit ('rect' lattice, 'sheet' shape)
+k = [1 cumprod(msize(1:end-1))]; 
+inds = [0:(munits-1)]';
+for i = mdim:-1:1, 
+  Coords(:,i) = floor(inds/k(i)); % these are subscripts in matrix-notation
+  inds = rem(inds,k(i)); 
+end
+% change subscripts to coordinates (move from (ij)-notation to (xy)-notation)
+Coords(:,[1 2]) = fliplr(Coords(:,[1 2])); 
+
+% 'hexa' lattice
+if strcmp(lattice,'hexa'), 
+  % check
+  if mdim > 2, 
+    error('You can only use hexa lattice with 1- or 2-dimensional maps.');
+  end
+  % offset x-coordinates of every other row 
+  inds_for_row = (cumsum(ones(msize(2),1))-1)*msize(1); 
+  for i=2:2:msize(1), 
+    Coords(i+inds_for_row,1) = Coords(i+inds_for_row,1) + 0.5; 
+  end
+end
+
+% shapes
+switch shape, 
+case 'sheet', 
+  if strcmp(lattice,'hexa'), 
+    % this correction is made to make distances to all 
+    % neighboring units equal
+    Coords(:,2) = Coords(:,2)*sqrt(0.75); 
+  end
+
+case 'cyl', 
+  % to make cylinder the coordinates must lie in 3D space, at least
+  if mdim<3, Coords = [Coords ones(munits,1)]; mdim = 3; end
+
+  % Bend the coordinates to a circle in the plane formed by x- and 
+  % and z-axis. Notice that the angle to which the last coordinates
+  % are bended is _not_ 360 degrees, because that would be equal to 
+  % the angle of the first coordinates (0 degrees).
+
+  Coords(:,1)     = Coords(:,1)/max(Coords(:,1));
+  Coords(:,1)     = 2*pi * Coords(:,1) * msize(2)/(msize(2)+1);
+  Coords(:,[1 3]) = [cos(Coords(:,1)) sin(Coords(:,1))];
+                    
+case 'toroid', 
+
+  % NOTE: if lattice is 'hexa', the msize(1) should be even, otherwise 
+  % the bending the upper and lower edges of the map do not match 
+  % to each other
+  if strcmp(lattice,'hexa') & rem(msize(1),2)==1, 
+    warning('Map size along y-coordinate is not even.');
+  end
+
+  % to make toroid the coordinates must lie in 3D space, at least
+  if mdim<3, Coords = [Coords ones(munits,1)]; mdim = 3; end
+
+  % First bend the coordinates to a circle in the plane formed
+  % by x- and z-axis. Then bend in the plane formed by y- and
+  % z-axis. (See also the notes in 'cyl').
+
+  Coords(:,1)     = Coords(:,1)/max(Coords(:,1));
+  Coords(:,1)     = 2*pi * Coords(:,1) * msize(2)/(msize(2)+1);
+  Coords(:,[1 3]) = [cos(Coords(:,1)) sin(Coords(:,1))];
+
+  Coords(:,2)     = Coords(:,2)/max(Coords(:,2));
+  Coords(:,2)     = 2*pi * Coords(:,2) * msize(1)/(msize(1)+1);
+  Coords(:,3)     = Coords(:,3) - min(Coords(:,3)) + 1;
+  Coords(:,[2 3]) = Coords(:,[3 3]) .* [cos(Coords(:,2)) sin(Coords(:,2))];
+  
+end
+
+return;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% subfunctions
+
+function C = bend(cx,cy,angle,xishexa)
+
+  dx = max(cx) - min(cx);
+  if dx ~= 0, 
+    % in case of hexagonal lattice it must be taken into account that
+    % coordinates of every second row are +0.5 off to the right
+    if xishexa, dx = dx-0.5; end
+    cx = angle*(cx - min(cx))/dx; 
+  end    
+  C(:,1) = (cy - min(cy)+1) .* cos(cx);
+  C(:,2) = (cy - min(cy)+1) .* sin(cx);
+
+% end of bend
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+