Mercurial > hg > camir-aes2014
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 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +