wolffd@0: function Ud = som_unit_dists(topol,lattice,shape) wolffd@0: wolffd@0: %SOM_UNIT_DISTS Distances between unit-locations on the map grid. wolffd@0: % wolffd@0: % Ud = som_unit_dists(topol,[lattice],[shape]) wolffd@0: % wolffd@0: % Ud = som_unit_dists(sMap); wolffd@0: % Ud = som_unit_dists(sMap.topol); wolffd@0: % Ud = som_unit_dists(msize, 'hexa', 'cyl'); wolffd@0: % Ud = som_unit_dists([10 4 4], 'rect', 'toroid'); wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % topol topology of the SOM grid wolffd@0: % (struct) topology or map struct wolffd@0: % (vector) the 'msize' field of topology struct wolffd@0: % [lattice] (string) map lattice, 'rect' by default wolffd@0: % [shape] (string) map shape, 'sheet' by default wolffd@0: % wolffd@0: % Ud (matrix, size [munits munits]) distance from each map unit wolffd@0: % to each map unit wolffd@0: % wolffd@0: % For more help, try 'type som_unit_dists' or check out online documentation. wolffd@0: % See also SOM_UNIT_COORDS, SOM_UNIT_NEIGHS. wolffd@0: wolffd@0: %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: % wolffd@0: % som_unit_dists wolffd@0: % wolffd@0: % PURPOSE wolffd@0: % wolffd@0: % Returns interunit distances between the units of a Self-Organizing Map wolffd@0: % along the map grid. wolffd@0: % wolffd@0: % SYNTAX wolffd@0: % wolffd@0: % Ud = som_unit_dists(sTopol); wolffd@0: % Ud = som_unit_dists(sM.topol); wolffd@0: % Ud = som_unit_dists(msize); wolffd@0: % Ud = som_unit_dists(msize,'hexa'); wolffd@0: % Ud = som_unit_dists(msize,'rect','toroid'); wolffd@0: % wolffd@0: % DESCRIPTION wolffd@0: % wolffd@0: % Calculates the distances between the units of a SOM based on the wolffd@0: % given topology. The distance are euclidian and they are measured wolffd@0: % along the map grid (in the output space). wolffd@0: % wolffd@0: % In case of 'sheet' shape, the distances can be measured directly wolffd@0: % from the unit coordinates given by SOM_UNIT_COORDS. wolffd@0: % wolffd@0: % In case of 'cyl' and 'toroid' shapes this is not so. In these cases wolffd@0: % the coordinates are calculated as in the case of 'sheet' shape and wolffd@0: % the shape is then taken into account by shifting the map grid into wolffd@0: % different positions. wolffd@0: % wolffd@0: % Consider, for example, a 4x3 map. The basic position of map units wolffd@0: % is shown on the left (with '1' - 'C' each denoting one map unit). wolffd@0: % In case of a 'cyl' shape, units on the left and right edges are wolffd@0: % neighbors, so for this purpose the map is copied on the left and wolffd@0: % right sides of the map, as on right. wolffd@0: % wolffd@0: % basic left basic right wolffd@0: % ------- ------- ------- ------- wolffd@0: % 1 5 9 1 5 9 1 5 9 1 5 9 wolffd@0: % 2 6 a 2 6 a 2 6 a 2 6 a wolffd@0: % 3 7 b 3 7 b 3 7 b 3 7 b wolffd@0: % 4 8 c 4 8 c 4 8 c 4 8 c wolffd@0: % wolffd@0: % For the 'toroid' shape a similar trick is done, except that the wolffd@0: % copies are placed all around the basic position: wolffd@0: % wolffd@0: % 1 5 9 1 5 9 1 5 9 wolffd@0: % 2 6 a 2 6 a 2 6 a wolffd@0: % 3 7 b 3 7 b 3 7 b wolffd@0: % 4 8 c 4 8 c 4 8 c wolffd@0: % 1 5 9 1 5 9 1 5 9 wolffd@0: % 2 6 a 2 6 a 2 6 a wolffd@0: % 3 7 b 3 7 b 3 7 b wolffd@0: % 4 8 c 4 8 c 4 8 c wolffd@0: % 1 5 9 1 5 9 1 5 9 wolffd@0: % 2 6 a 2 6 a 2 6 a wolffd@0: % 3 7 b 3 7 b 3 7 b wolffd@0: % 4 8 c 4 8 c 4 8 c wolffd@0: % wolffd@0: % From this we can see that the distance from unit '1' is 1 to units wolffd@0: % '9','2','4' and '5', and sqrt(2) to units 'C','A','8' and '6'. Notice wolffd@0: % that in the case of a 'hexa' lattice and 'toroid' shape, the size wolffd@0: % of the map in y-direction should be even. The reason can be clearly wolffd@0: % seen from the two figures below. On the left the basic positions for wolffd@0: % a 3x3 map. If the map is copied above itself, it can be seen that the wolffd@0: % lattice is broken (on the right): wolffd@0: % wolffd@0: % basic positions example of broken lattice wolffd@0: % --------------- ------------------------- wolffd@0: % 1 4 7 wolffd@0: % 2 5 8 wolffd@0: % 3 6 9 wolffd@0: % 1 4 7 1 4 7 wolffd@0: % 2 5 8 2 5 8 wolffd@0: % 3 6 9 3 6 9 wolffd@0: % wolffd@0: % wolffd@0: % REQUIRED INPUT ARGUMENTS wolffd@0: % wolffd@0: % topol Map grid dimensions. wolffd@0: % (struct) topology struct or map struct, the topology wolffd@0: % (msize, lattice, shape) of the map is taken from wolffd@0: % the appropriate fields (see e.g. SOM_SET) wolffd@0: % (vector) the vector which gives the size of the map grid wolffd@0: % (msize-field of the topology struct). wolffd@0: % wolffd@0: % OPTIONAL INPUT ARGUMENTS wolffd@0: % wolffd@0: % lattice (string) The map lattice, either 'rect' or 'hexa'. Default wolffd@0: % is 'rect'. 'hexa' can only be used with 1- or wolffd@0: % 2-dimensional map grids. wolffd@0: % shape (string) The map shape, either 'sheet', 'cyl' or 'toroid'. wolffd@0: % Default is 'sheet'. wolffd@0: % wolffd@0: % OUTPUT ARGUMENTS wolffd@0: % wolffd@0: % Ud (matrix) distances from each map unit to each other map unit, wolffd@0: % size is [munits munits] wolffd@0: % wolffd@0: % EXAMPLES wolffd@0: % wolffd@0: % Simplest case: wolffd@0: % Ud = som_unit_dists(sTopol); wolffd@0: % Ud = som_unit_dists(sMap.topol); wolffd@0: % Ud = som_unit_dists(msize); wolffd@0: % Ud = som_unit_dists([10 10]); wolffd@0: % wolffd@0: % If topology is given as vector, lattice is 'rect' and shape is 'sheet' wolffd@0: % by default. To change these, you can use the optional arguments: wolffd@0: % Ud = som_unit_dists(msize, 'hexa', 'toroid'); wolffd@0: % wolffd@0: % The distances can also be calculated for high-dimensional grids: wolffd@0: % Ud = som_unit_dists([4 4 4 4 4 4]); wolffd@0: % wolffd@0: % SEE ALSO wolffd@0: % wolffd@0: % som_unit_coords Calculate grid coordinates. wolffd@0: % som_unit_neighs Calculate neighborhoods of map units. wolffd@0: wolffd@0: % Copyright (c) 1997-2000 by the SOM toolbox programming team. wolffd@0: % http://www.cis.hut.fi/projects/somtoolbox/ wolffd@0: wolffd@0: % Version 1.0beta juuso 110997 wolffd@0: % Version 2.0beta juuso 101199 170400 070600 130600 wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% Check arguments wolffd@0: wolffd@0: error(nargchk(1, 3, nargin)); wolffd@0: wolffd@0: % default values wolffd@0: sTopol = som_set('som_topol','lattice','rect'); wolffd@0: wolffd@0: % topol wolffd@0: if isstruct(topol), wolffd@0: switch topol.type, wolffd@0: case 'som_map', sTopol = topol.topol; wolffd@0: case 'som_topol', sTopol = topol; wolffd@0: end wolffd@0: elseif iscell(topol), wolffd@0: for i=1:length(topol), wolffd@0: if isnumeric(topol{i}), sTopol.msize = topol{i}; wolffd@0: elseif ischar(topol{i}), wolffd@0: switch topol{i}, wolffd@0: case {'rect','hexa'}, sTopol.lattice = topol{i}; wolffd@0: case {'sheet','cyl','toroid'}, sTopol.shape = topol{i}; wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: else wolffd@0: sTopol.msize = topol; wolffd@0: end wolffd@0: if prod(sTopol.msize)==0, error('Map size is 0.'); end wolffd@0: wolffd@0: % lattice wolffd@0: if nargin>1 & ~isempty(lattice) & ~isnan(lattice), sTopol.lattice = lattice; end wolffd@0: wolffd@0: % shape wolffd@0: if nargin>2 & ~isempty(shape) & ~isnan(shape), sTopol.shape = shape; end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: %% Action wolffd@0: wolffd@0: msize = sTopol.msize; wolffd@0: lattice = sTopol.lattice; wolffd@0: shape = sTopol.shape; wolffd@0: wolffd@0: munits = prod(msize); wolffd@0: Ud = zeros(munits,munits); wolffd@0: wolffd@0: % free topology wolffd@0: if strcmp(lattice,'free'), wolffd@0: N1 = sTopol.connection; wolffd@0: Ud = som_neighborhood(N1,Inf); wolffd@0: end wolffd@0: wolffd@0: % coordinates of map units when the grid is spread on a plane wolffd@0: Coords = som_unit_coords(msize,lattice,'sheet'); wolffd@0: wolffd@0: % width and height of the grid wolffd@0: dx = max(Coords(:,1))-min(Coords(:,1)); wolffd@0: if msize(1)>1, dx = dx*msize(1)/(msize(1)-1); else dx = dx+1; end wolffd@0: dy = max(Coords(:,2))-min(Coords(:,2)); wolffd@0: if msize(2)>1, dy = dy*msize(2)/(msize(2)-1); else dy = dy+1; end wolffd@0: wolffd@0: % calculate distance from each location to each other location wolffd@0: switch shape, wolffd@0: case 'sheet', wolffd@0: for i=1:(munits-1), wolffd@0: inds = [(i+1):munits]; wolffd@0: Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))'; wolffd@0: Ud(i,inds) = sqrt(sum(Dco.^2)); wolffd@0: end wolffd@0: wolffd@0: case 'cyl', wolffd@0: for i=1:(munits-1), wolffd@0: inds = [(i+1):munits]; wolffd@0: Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))'; wolffd@0: dist = sum(Dco.^2); wolffd@0: % The cylinder shape is taken into account by adding and substracting wolffd@0: % the width of the map (dx) from the x-coordinate (ie. shifting the wolffd@0: % map right and left). wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; %East (x+dx) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; %West (x-dx) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: Ud(i,inds) = sqrt(dist); wolffd@0: end wolffd@0: wolffd@0: case 'toroid', wolffd@0: for i=1:(munits-1), wolffd@0: inds = [(i+1):munits]; wolffd@0: Dco = (Coords(inds,:) - Coords(ones(munits-i,1)*i,:))'; wolffd@0: dist = sum(Dco.^2); wolffd@0: % The toroid shape is taken into account as the cylinder shape was wolffd@0: % (see above), except that the map is shifted also vertically. wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; %East (x+dx) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; %West (x+dx) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(2,:) = DcoS(2,:) + dy; %South (y+dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(2,:) = DcoS(2,:) - dy; %North (y-dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; DcoS(2,:) = DcoS(2,:) - dy; %NorthEast (x+dx, y-dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) + dx; DcoS(2,:) = DcoS(2,:) + dy; %SouthEast (x+dx, y+dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; DcoS(2,:) = DcoS(2,:) + dy; %SouthWest (x-dx, y+dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: DcoS = Dco; DcoS(1,:) = DcoS(1,:) - dx; DcoS(2,:) = DcoS(2,:) - dy; %NorthWest (x-dx, y-dy) wolffd@0: dist = min(dist,sum(DcoS.^2)); wolffd@0: Ud(i,inds) = sqrt(dist); wolffd@0: end wolffd@0: wolffd@0: otherwise, wolffd@0: error (['Unknown shape: ', shape]); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: Ud = Ud + Ud'; wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%