annotate toolboxes/MIRtoolbox1.3.2/somtoolbox/som_unit_coords.m @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function Coords = som_unit_coords(topol,lattice,shape)
Daniel@0 2
Daniel@0 3 %SOM_UNIT_COORDS Locations of units on the SOM grid.
Daniel@0 4 %
Daniel@0 5 % Co = som_unit_coords(topol, [lattice], [shape])
Daniel@0 6 %
Daniel@0 7 % Co = som_unit_coords(sMap);
Daniel@0 8 % Co = som_unit_coords(sMap.topol);
Daniel@0 9 % Co = som_unit_coords(msize, 'hexa', 'cyl');
Daniel@0 10 % Co = som_unit_coords([10 4 4], 'rect', 'toroid');
Daniel@0 11 %
Daniel@0 12 % Input and output arguments ([]'s are optional):
Daniel@0 13 % topol topology of the SOM grid
Daniel@0 14 % (struct) topology or map struct
Daniel@0 15 % (vector) the 'msize' field of topology struct
Daniel@0 16 % [lattice] (string) map lattice, 'rect' by default
Daniel@0 17 % [shape] (string) map shape, 'sheet' by default
Daniel@0 18 %
Daniel@0 19 % Co (matrix, size [munits k]) coordinates for each map unit
Daniel@0 20 %
Daniel@0 21 % For more help, try 'type som_unit_coords' or check out online documentation.
Daniel@0 22 % See also SOM_UNIT_DISTS, SOM_UNIT_NEIGHS.
Daniel@0 23
Daniel@0 24 %%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 25 %
Daniel@0 26 % som_unit_coords
Daniel@0 27 %
Daniel@0 28 % PURPOSE
Daniel@0 29 %
Daniel@0 30 % Returns map grid coordinates for the units of a Self-Organizing Map.
Daniel@0 31 %
Daniel@0 32 % SYNTAX
Daniel@0 33 %
Daniel@0 34 % Co = som_unit_coords(sTopol);
Daniel@0 35 % Co = som_unit_coords(sM.topol);
Daniel@0 36 % Co = som_unit_coords(msize);
Daniel@0 37 % Co = som_unit_coords(msize,'hexa');
Daniel@0 38 % Co = som_unit_coords(msize,'rect','toroid');
Daniel@0 39 %
Daniel@0 40 % DESCRIPTION
Daniel@0 41 %
Daniel@0 42 % Calculates the map grid coordinates of the units of a SOM based on
Daniel@0 43 % the given topology. The coordinates are such that they can be used to
Daniel@0 44 % position map units in space. In case of 'sheet' shape they can be
Daniel@0 45 % (and are) used to measure interunit distances.
Daniel@0 46 %
Daniel@0 47 % NOTE: for 'hexa' lattice, the x-coordinates of every other row are shifted
Daniel@0 48 % by +0.5, and the y-coordinates are multiplied by sqrt(0.75). This is done
Daniel@0 49 % to make distances of a unit to all its six neighbors equal. It is not
Daniel@0 50 % possible to use 'hexa' lattice with higher than 2-dimensional map grids.
Daniel@0 51 %
Daniel@0 52 % 'cyl' and 'toroid' shapes: the coordinates are initially determined as
Daniel@0 53 % in case of 'sheet' shape, but are then bended around the x- or the
Daniel@0 54 % x- and then y-axes to get the desired shape.
Daniel@0 55 %
Daniel@0 56 % POSSIBLE BUGS
Daniel@0 57 %
Daniel@0 58 % I don't know if the bending operation works ok for high-dimensional
Daniel@0 59 % map grids. Anyway, if anyone wants to make a 4-dimensional
Daniel@0 60 % toroid map, (s)he deserves it.
Daniel@0 61 %
Daniel@0 62 % REQUIRED INPUT ARGUMENTS
Daniel@0 63 %
Daniel@0 64 % topol Map grid dimensions.
Daniel@0 65 % (struct) topology struct or map struct, the topology
Daniel@0 66 % (msize, lattice, shape) of the map is taken from
Daniel@0 67 % the appropriate fields (see e.g. SOM_SET)
Daniel@0 68 % (vector) the vector which gives the size of the map grid
Daniel@0 69 % (msize-field of the topology struct).
Daniel@0 70 %
Daniel@0 71 % OPTIONAL INPUT ARGUMENTS
Daniel@0 72 %
Daniel@0 73 % lattice (string) The map lattice, either 'rect' or 'hexa'. Default
Daniel@0 74 % is 'rect'. 'hexa' can only be used with 1- or
Daniel@0 75 % 2-dimensional map grids.
Daniel@0 76 % shape (string) The map shape, either 'sheet', 'cyl' or 'toroid'.
Daniel@0 77 % Default is 'sheet'.
Daniel@0 78 %
Daniel@0 79 % OUTPUT ARGUMENTS
Daniel@0 80 %
Daniel@0 81 % Co (matrix) coordinates for each map units, size is [munits k]
Daniel@0 82 % where k is 2, or more if the map grid is higher
Daniel@0 83 % dimensional or the shape is 'cyl' or 'toroid'
Daniel@0 84 %
Daniel@0 85 % EXAMPLES
Daniel@0 86 %
Daniel@0 87 % Simplest case:
Daniel@0 88 % Co = som_unit_coords(sTopol);
Daniel@0 89 % Co = som_unit_coords(sMap.topol);
Daniel@0 90 % Co = som_unit_coords(msize);
Daniel@0 91 % Co = som_unit_coords([10 10]);
Daniel@0 92 %
Daniel@0 93 % If topology is given as vector, lattice is 'rect' and shape is 'sheet'
Daniel@0 94 % by default. To change these, you can use the optional arguments:
Daniel@0 95 % Co = som_unit_coords(msize, 'hexa', 'toroid');
Daniel@0 96 %
Daniel@0 97 % The coordinates can also be calculated for high-dimensional grids:
Daniel@0 98 % Co = som_unit_coords([4 4 4 4 4 4]);
Daniel@0 99 %
Daniel@0 100 % SEE ALSO
Daniel@0 101 %
Daniel@0 102 % som_unit_dists Calculate interunit distance along the map grid.
Daniel@0 103 % som_unit_neighs Calculate neighborhoods of map units.
Daniel@0 104
Daniel@0 105 % Copyright (c) 1997-2000 by the SOM toolbox programming team.
Daniel@0 106 % http://www.cis.hut.fi/projects/somtoolbox/
Daniel@0 107
Daniel@0 108 % Version 1.0beta juuso 110997
Daniel@0 109 % Version 2.0beta juuso 101199 070600
Daniel@0 110
Daniel@0 111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 112 %% Check arguments
Daniel@0 113
Daniel@0 114 error(nargchk(1, 3, nargin));
Daniel@0 115
Daniel@0 116 % default values
Daniel@0 117 sTopol = som_set('som_topol','lattice','rect');
Daniel@0 118
Daniel@0 119 % topol
Daniel@0 120 if isstruct(topol),
Daniel@0 121 switch topol.type,
Daniel@0 122 case 'som_map', sTopol = topol.topol;
Daniel@0 123 case 'som_topol', sTopol = topol;
Daniel@0 124 end
Daniel@0 125 elseif iscell(topol),
Daniel@0 126 for i=1:length(topol),
Daniel@0 127 if isnumeric(topol{i}), sTopol.msize = topol{i};
Daniel@0 128 elseif ischar(topol{i}),
Daniel@0 129 switch topol{i},
Daniel@0 130 case {'rect','hexa'}, sTopol.lattice = topol{i};
Daniel@0 131 case {'sheet','cyl','toroid'}, sTopol.shape = topol{i};
Daniel@0 132 end
Daniel@0 133 end
Daniel@0 134 end
Daniel@0 135 else
Daniel@0 136 sTopol.msize = topol;
Daniel@0 137 end
Daniel@0 138 if prod(sTopol.msize)==0, error('Map size is 0.'); end
Daniel@0 139
Daniel@0 140 % lattice
Daniel@0 141 if nargin>1 & ~isempty(lattice) & ~isnan(lattice), sTopol.lattice = lattice; end
Daniel@0 142
Daniel@0 143 % shape
Daniel@0 144 if nargin>2 & ~isempty(shape) & ~isnan(shape), sTopol.shape = shape; end
Daniel@0 145
Daniel@0 146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 147 %% Action
Daniel@0 148
Daniel@0 149 msize = sTopol.msize;
Daniel@0 150 lattice = sTopol.lattice;
Daniel@0 151 shape = sTopol.shape;
Daniel@0 152
Daniel@0 153 % init variables
Daniel@0 154
Daniel@0 155 if length(msize)==1, msize = [msize 1]; end
Daniel@0 156 munits = prod(msize);
Daniel@0 157 mdim = length(msize);
Daniel@0 158 Coords = zeros(munits,mdim);
Daniel@0 159
Daniel@0 160 % initial coordinates for each map unit ('rect' lattice, 'sheet' shape)
Daniel@0 161 k = [1 cumprod(msize(1:end-1))];
Daniel@0 162 inds = [0:(munits-1)]';
Daniel@0 163 for i = mdim:-1:1,
Daniel@0 164 Coords(:,i) = floor(inds/k(i)); % these are subscripts in matrix-notation
Daniel@0 165 inds = rem(inds,k(i));
Daniel@0 166 end
Daniel@0 167 % change subscripts to coordinates (move from (ij)-notation to (xy)-notation)
Daniel@0 168 Coords(:,[1 2]) = fliplr(Coords(:,[1 2]));
Daniel@0 169
Daniel@0 170 % 'hexa' lattice
Daniel@0 171 if strcmp(lattice,'hexa'),
Daniel@0 172 % check
Daniel@0 173 if mdim > 2,
Daniel@0 174 error('You can only use hexa lattice with 1- or 2-dimensional maps.');
Daniel@0 175 end
Daniel@0 176 % offset x-coordinates of every other row
Daniel@0 177 inds_for_row = (cumsum(ones(msize(2),1))-1)*msize(1);
Daniel@0 178 for i=2:2:msize(1),
Daniel@0 179 Coords(i+inds_for_row,1) = Coords(i+inds_for_row,1) + 0.5;
Daniel@0 180 end
Daniel@0 181 end
Daniel@0 182
Daniel@0 183 % shapes
Daniel@0 184 switch shape,
Daniel@0 185 case 'sheet',
Daniel@0 186 if strcmp(lattice,'hexa'),
Daniel@0 187 % this correction is made to make distances to all
Daniel@0 188 % neighboring units equal
Daniel@0 189 Coords(:,2) = Coords(:,2)*sqrt(0.75);
Daniel@0 190 end
Daniel@0 191
Daniel@0 192 case 'cyl',
Daniel@0 193 % to make cylinder the coordinates must lie in 3D space, at least
Daniel@0 194 if mdim<3, Coords = [Coords ones(munits,1)]; mdim = 3; end
Daniel@0 195
Daniel@0 196 % Bend the coordinates to a circle in the plane formed by x- and
Daniel@0 197 % and z-axis. Notice that the angle to which the last coordinates
Daniel@0 198 % are bended is _not_ 360 degrees, because that would be equal to
Daniel@0 199 % the angle of the first coordinates (0 degrees).
Daniel@0 200
Daniel@0 201 Coords(:,1) = Coords(:,1)/max(Coords(:,1));
Daniel@0 202 Coords(:,1) = 2*pi * Coords(:,1) * msize(2)/(msize(2)+1);
Daniel@0 203 Coords(:,[1 3]) = [cos(Coords(:,1)) sin(Coords(:,1))];
Daniel@0 204
Daniel@0 205 case 'toroid',
Daniel@0 206
Daniel@0 207 % NOTE: if lattice is 'hexa', the msize(1) should be even, otherwise
Daniel@0 208 % the bending the upper and lower edges of the map do not match
Daniel@0 209 % to each other
Daniel@0 210 if strcmp(lattice,'hexa') & rem(msize(1),2)==1,
Daniel@0 211 warning('Map size along y-coordinate is not even.');
Daniel@0 212 end
Daniel@0 213
Daniel@0 214 % to make toroid the coordinates must lie in 3D space, at least
Daniel@0 215 if mdim<3, Coords = [Coords ones(munits,1)]; mdim = 3; end
Daniel@0 216
Daniel@0 217 % First bend the coordinates to a circle in the plane formed
Daniel@0 218 % by x- and z-axis. Then bend in the plane formed by y- and
Daniel@0 219 % z-axis. (See also the notes in 'cyl').
Daniel@0 220
Daniel@0 221 Coords(:,1) = Coords(:,1)/max(Coords(:,1));
Daniel@0 222 Coords(:,1) = 2*pi * Coords(:,1) * msize(2)/(msize(2)+1);
Daniel@0 223 Coords(:,[1 3]) = [cos(Coords(:,1)) sin(Coords(:,1))];
Daniel@0 224
Daniel@0 225 Coords(:,2) = Coords(:,2)/max(Coords(:,2));
Daniel@0 226 Coords(:,2) = 2*pi * Coords(:,2) * msize(1)/(msize(1)+1);
Daniel@0 227 Coords(:,3) = Coords(:,3) - min(Coords(:,3)) + 1;
Daniel@0 228 Coords(:,[2 3]) = Coords(:,[3 3]) .* [cos(Coords(:,2)) sin(Coords(:,2))];
Daniel@0 229
Daniel@0 230 end
Daniel@0 231
Daniel@0 232 return;
Daniel@0 233
Daniel@0 234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 235 %% subfunctions
Daniel@0 236
Daniel@0 237 function C = bend(cx,cy,angle,xishexa)
Daniel@0 238
Daniel@0 239 dx = max(cx) - min(cx);
Daniel@0 240 if dx ~= 0,
Daniel@0 241 % in case of hexagonal lattice it must be taken into account that
Daniel@0 242 % coordinates of every second row are +0.5 off to the right
Daniel@0 243 if xishexa, dx = dx-0.5; end
Daniel@0 244 cx = angle*(cx - min(cx))/dx;
Daniel@0 245 end
Daniel@0 246 C(:,1) = (cy - min(cy)+1) .* cos(cx);
Daniel@0 247 C(:,2) = (cy - min(cy)+1) .* sin(cx);
Daniel@0 248
Daniel@0 249 % end of bend
Daniel@0 250
Daniel@0 251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Daniel@0 252