wolffd@0: function colors=som_colorcode(m, colorcode, scaling) wolffd@0: wolffd@0: %SOM_COLORCODE Calculates a heuristic color coding for the SOM grid wolffd@0: % wolffd@0: % colors = som_colorcode(m, colorcode, scaling) wolffd@0: % wolffd@0: % Input and output arguments ([]'s are optional): wolffd@0: % m (struct) map or topol struct wolffd@0: % (cell array) of form {str,[m1 m2]} where wolffd@0: % str = 'hexa' or 'rect' and [m1 m2] = msize wolffd@0: % (matrix) size N x 2, unit coordinates wolffd@0: % [colorcode] (string) 'rgb1' (default),'rgb2','rgb3','rgb4','hsv' wolffd@0: % [scaling] (scalar) 1=on (default), 0=off. Has effect only wolffd@0: % if m is a Nx2 matrix of coordinates: wolffd@0: % controls whether these are scaled to wolffd@0: % range [0,1] or not. wolffd@0: % wolffd@0: % colors (matrix) size N x 3, RGB colors for each unit (or point) wolffd@0: % wolffd@0: % The function gives a color coding by location for the map grid wolffd@0: % (or arbitrary set of points). Map grid coordinates are always linearly wolffd@0: % normalized to a unit square (x and y coordinates between [0,1]), except wolffd@0: % if m is a Nx2 matrix and scaling=0. In that case too, the coordinates wolffd@0: % must be in range [0,1]. wolffd@0: % wolffd@0: % Following heuristic color codings are available: wolffd@0: % wolffd@0: % 'rgb1' slice of RGB-cube so that green - yellow wolffd@0: % the corners have colors: | | wolffd@0: % blue - magenta wolffd@0: % wolffd@0: % 'rgb2' slice of RGB-cube so that red - yellow wolffd@0: % the corners have colors: | | wolffd@0: % blue - cyan wolffd@0: % wolffd@0: % 'rgb3' slice of RGB-cube so that mixed_green - orange wolffd@0: % the corners have colors: | | wolffd@0: % light_blue - pink wolffd@0: % wolffd@0: % 'rgb4' has 'rgb1' on the diagonal + additional colors in corners wolffd@0: % (more resolution but visually strongly discontinuous) wolffd@0: % wolffd@0: % 'hsv' angle and radius from map centre are coded by hue and wolffd@0: % intensity (more resoluton but visually discontinuous) wolffd@0: % wolffd@0: % See also SOM_CPLANE, SOM_SHOW, SOM_CLUSTERCOLOR, SOM_KMEANSCOLOR, wolffd@0: % SOM_BMUCOLOR. wolffd@0: wolffd@0: % Contributed to SOM Toolbox 2.0, February 11th, 2000 by Johan Himberg wolffd@0: % Copyright (c) by Johan Himberg wolffd@0: % http://www.cis.hut.fi/projects/somtoolbox/ wolffd@0: wolffd@0: % Version 2.0 Johan 140799 wolffd@0: wolffd@0: %%% Check arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: error(nargchk(1, 3, nargin)); % check no. of input args is correct wolffd@0: wolffd@0: %% Check m: map, topol, cell or data? wolffd@0: wolffd@0: if vis_valuetype(m,{'nx2'}), wolffd@0: p=m; % explicit coordinates wolffd@0: wolffd@0: else wolffd@0: wolffd@0: % map, topol, cell wolffd@0: wolffd@0: [tmp,ok,tmp]=som_set(m); wolffd@0: if isstruct(m) & all(ok) wolffd@0: switch m.type wolffd@0: case 'som_topol' % topol wolffd@0: msize=m.msize; wolffd@0: lattice=m.lattice; wolffd@0: case 'som_map' wolffd@0: msize=m.topol.msize; % map wolffd@0: lattice=m.topol.lattice; wolffd@0: otherwise wolffd@0: error('Invalid map or topol struct.'); wolffd@0: end wolffd@0: wolffd@0: % cell wolffd@0: wolffd@0: elseif iscell(m) & vis_valuetype(size(m),{[1 2]}), wolffd@0: if vis_valuetype(m{2},{[1 2]}) & vis_valuetype(m{1},{'string'}), wolffd@0: lattice=m{1}; wolffd@0: msize=m{2}; wolffd@0: else wolffd@0: error('Invalid map size information.'); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: %% Check map parameters wolffd@0: wolffd@0: switch lattice % lattice wolffd@0: case 'hexa' wolffd@0: ; wolffd@0: case 'rect' wolffd@0: ; wolffd@0: otherwise wolffd@0: error('Unknown lattice type'); wolffd@0: end wolffd@0: wolffd@0: if length(msize)>2 % dimension wolffd@0: error('Only 2D maps allowed!'); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: % Calculate coordinates wolffd@0: p=som_unit_coords(msize,lattice,'sheet'); wolffd@0: wolffd@0: % Set scaling to 1 as it is done always in this case wolffd@0: scaling=1; wolffd@0: end wolffd@0: wolffd@0: % Check colorcode wolffd@0: wolffd@0: if nargin < 2 | isempty(colorcode), wolffd@0: colorcode='rgb1'; wolffd@0: end wolffd@0: if ~ischar(colorcode) wolffd@0: error('String value for colorcode mode expected.'); wolffd@0: else wolffd@0: switch colorcode wolffd@0: case { 'rgb1', 'rgb2', 'rgb3' , 'rgb4' ,'hsv'} wolffd@0: otherwise wolffd@0: error([ 'Colorcode mode ' colorcode ' not implemented.']); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: % Check scaling wolffd@0: wolffd@0: if nargin < 3 | isempty(scaling) wolffd@0: scaling=1; wolffd@0: end wolffd@0: wolffd@0: if ~vis_valuetype(scaling,{'1x1'}) wolffd@0: error('Scaling should be 0 (off) or 1 (on).'); wolffd@0: end wolffd@0: wolffd@0: %% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: % scale coordintes between [0,1] wolffd@0: wolffd@0: if scaling wolffd@0: n=size(p,1); wolffd@0: mn=min(p); wolffd@0: e=max(p)-mn; wolffd@0: p=(p-repmat(mn,n,1))./repmat(e,n,1); wolffd@0: elseif sum(p(:,1)>1+p(:,1)<0+p(:,2)>1+p(:,2)<0), wolffd@0: error('Coordinates out of range [0,1].'); wolffd@0: end wolffd@0: wolffd@0: switch colorcode wolffd@0: case 'rgb1' wolffd@0: h(:,1)=p(:,1); wolffd@0: h(:,2)=1-p(:,2); wolffd@0: h(:,3)=p(:,2); wolffd@0: case 'rgb2' wolffd@0: h(:,1)=p(:,1); wolffd@0: h(:,2)=1-p(:,2); wolffd@0: h(:,3)=1-p(:,1); wolffd@0: case 'rgb3' wolffd@0: h(:,1)=p(:,1); wolffd@0: h(:,2)=.5; wolffd@0: h(:,3)=p(:,2); wolffd@0: case 'rgb4' wolffd@0: p=rgb4(p); wolffd@0: h(:,1)=p(:,1); wolffd@0: h(:,2)=1-p(:,2); wolffd@0: h(:,3)=p(:,3); wolffd@0: case 'hsv' wolffd@0: munits = n; wolffd@0: Hsv = zeros(munits,3); wolffd@0: for i=1:n, wolffd@0: dx = .5-p(i,1); wolffd@0: dy = .5-p(i,2); wolffd@0: r = sqrt(dx^2+dy^2); wolffd@0: if r==0, wolffd@0: h=1; wolffd@0: elseif dx==0, wolffd@0: h=.5; %h=ay; wolffd@0: elseif dy==0, wolffd@0: h=.5; %h=ax; wolffd@0: else wolffd@0: h = min(abs(.5/(dx/r)),abs(.5/(dy/r))); wolffd@0: end wolffd@0: wolffd@0: if r==0, wolffd@0: angle = 0; wolffd@0: else wolffd@0: angle = acos(dx/r); wolffd@0: if dy<0, wolffd@0: angle = 2*pi-angle; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: Hsv(i,1) = 1-sin(angle/4); wolffd@0: Hsv(i,2) = 1; wolffd@0: Hsv(i,3) = r/h; wolffd@0: h = hsv2rgb(Hsv); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: %% Build output %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: colors=h; wolffd@0: wolffd@0: %% Subfunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% juha %%%% wolffd@0: wolffd@0: function p=rgb4(coord) wolffd@0: wolffd@0: for i=1:size(coord,1); wolffd@0: p(i,:)=get_coords(coord(i,:))'; wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function coords=get_coords(coords) wolffd@0: wolffd@0: %GET_COORDS wolffd@0: % wolffd@0: % get_coords(coords) wolffd@0: % wolffd@0: % ARGUMENTS wolffd@0: % wolffd@0: % coords (1x2 or 2x1 vector) coords(1) is an x-coordinate and coords(2) wolffd@0: % y-coordinate. wolffd@0: % wolffd@0: % wolffd@0: % RETURNS wolffd@0: % wolffd@0: % coords (3x1 vector) x,y and z-coordinates. wolffd@0: % wolffd@0: wolffd@0: if ~(all(size(coords) == [1 2]) | all(size(coords) == [2 1])) wolffd@0: error('Argument ''coords'' must be an 2x1 or 1x2 vector.'); wolffd@0: end wolffd@0: wolffd@0: if all(size(coords) == [1 2]) wolffd@0: coords=coords'; wolffd@0: end wolffd@0: wolffd@0: if any(coords > 1) any(coords < 0) wolffd@0: error('Coordinates must lay inside the interval [0,1].'); wolffd@0: end wolffd@0: wolffd@0: if coords(1) <= 1/(sqrt(2)+1), wolffd@0: if coords(2) <= line3(coords(1)) wolffd@0: coords=coords_in_base(4,coords); wolffd@0: elseif coords(2) <= line2(coords(1)) wolffd@0: coords=coords_in_base(1,coords); wolffd@0: else wolffd@0: coords=coords_in_base(2,coords); wolffd@0: end wolffd@0: elseif coords(1) <= sqrt(2)/(sqrt(2)+1) wolffd@0: if coords(2) <= line1(coords(1)) wolffd@0: coords=coords_in_base(3,coords); wolffd@0: elseif coords(2) <= line2(coords(1)) wolffd@0: coords=coords_in_base(1,coords); wolffd@0: else wolffd@0: coords=coords_in_base(2,coords); wolffd@0: end wolffd@0: else wolffd@0: if coords(2) <= line1(coords(1)), wolffd@0: coords=coords_in_base(3,coords); wolffd@0: elseif coords(2) <= line4(coords(1)) wolffd@0: coords=coords_in_base(1,coords); wolffd@0: else wolffd@0: coords=coords_in_base(5,coords); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function coords=coords_in_base(base_no,coords) wolffd@0: wolffd@0: A=[0;1/(sqrt(2)+1)]; wolffd@0: E=[1;1]; wolffd@0: F=[0;0]; wolffd@0: G=[1;0]; wolffd@0: H=[0;1]; wolffd@0: wolffd@0: const=1+1/sqrt(2); wolffd@0: wolffd@0: switch base_no wolffd@0: case 1 wolffd@0: x=(coords-A)*const; wolffd@0: coords=[(1/sqrt(2))*(x(1)-x(2));0.5*(x(1)+x(2));0.5*(x(1)+x(2))]; wolffd@0: case 2 wolffd@0: x=(coords-H)*const; wolffd@0: coords=[0;x(1);1+x(2)]; wolffd@0: case 3 wolffd@0: x=(coords-G)*const; wolffd@0: coords=[1;1+x(1);x(2)]; wolffd@0: case 4 wolffd@0: x=(coords-F)*const; wolffd@0: coords=[0.5+(1/sqrt(2))*(x(1)-x(2));... wolffd@0: 0.5-(1/sqrt(2))*(x(1)+x(2));... wolffd@0: 0]; wolffd@0: case 5 wolffd@0: x=(coords-E)*const; wolffd@0: coords=[0.5+(1/sqrt(2))*(x(1)-x(2));... wolffd@0: 0.5-(1/sqrt(2))*(x(1)+x(2));... wolffd@0: 1]; wolffd@0: end wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function y=line1(x) wolffd@0: wolffd@0: y = x-1/(sqrt(2)+1); wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function y=line2(x) wolffd@0: wolffd@0: y = x+1/(sqrt(2)+1); wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function y=line3(x) wolffd@0: wolffd@0: y = -x+1/(sqrt(2)+1); wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wolffd@0: wolffd@0: function y= line4(x) wolffd@0: wolffd@0: y = -x+(2*sqrt(2)+1)/(sqrt(2)+1); wolffd@0: wolffd@0: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%