function colors=som_colorcode(m, colorcode, scaling)

%SOM_COLOROCODE Calculates a heuristic color coding for the SOM grid
%
% colors=som_colorcode(m, colorcode, scaling) 
%
% INPUT ARGUMENTS ([]'s are optional)
%
%  m          (varies)  -map struct     
%                       -topol struct
%                       -cell array {str,[m1 m2]}  
%                         where str = 'hexa' or 'rect' and [m1 m2] = msize
%                       -Nx2 matrix of coordinates
% [colorcode] (string) 'rgb1','rgb2','rgb3','rgb4','hsv'  
%                        default: 'rgb1'
% [scaling]   (scalar) 0=off, 1=on, default is 1 (has effect only
%                       if m is a Nx2 matrix of coordinates) 
% OUTPUT ARGUMENTS    
%
%  colors   (matrix) RGB colors for each unit (or point), size Nx3
%
% The function gives a color coding by location for the map grid 
% (or arbitrary set of points). Map grid coordinates are always linearly 
% normalized to a unit square (x and y coordinates between [0,1]). 
% 
% If an arbitrary set of points (m is an Nx2 matrix) is given, the
% coordinates are normalized according to the input argumat 'scaling':
%  0: no scaling (data must be in range [0,1]) 
%  1: linear scaling for x- and y-coordinates between [0,1] is made
% 
% Following heuristic color codings are available:
%
% 'rgb1', 'rgb2' and 'rgb3' are simply slices of RGB cube  
%  Colors in cornes of the plane:  
%
% 'rgb1': green yellow  'rgb2': red  yellow 'rgb3': mixed_green orange
%         blue  magenta         blue cyan           ligth_blue  pink 
%
% The codings 'rgb4' and 'hsv' are more complex:
%
% 'rgb4': has 'rgb1' on the diagonal + additional colors in corners
%         (more resolution but visually strongly discontinuous) 
%
% 'hsv':  angle and radius from map centre are coded by hue and 
%         intensity (more resoluton but visually discontinuous)
%
% See also som_cplane, som_vis

%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% not available

% Copyright (c) 1999 by the SOM toolbox programming team.
% http://www.cis.hut.fi/projects/somtoolbox/             
% Proto 2.0 Johan 140799 (parts from juha (rgb4) juuso&ecco (hsv))

%%% Check arguments %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

error(nargchk(1, 3, nargin));   % check no. of input args is correct

%% Check m: map, topol, cell or data?

if vis_valuetype(m,{'nx2'}),
  p=m;  % explicit coordinates
  
else
  
  % map, topol, cell
  
  [tmp,ok,tmp]=som_set(m);
  if isstruct(m) & all(ok)
    switch m.type
    case 'som_topol'              % topol 
      msize=m.msize;
      lattice=m.lattice;
    case 'som_map'   
      msize=m.topol.msize;        % map
      lattice=m.topol.lattice;
    otherwise
      error('Invalid map or topol struct.');
    end
    
  % cell  
    
  elseif iscell(m) & vis_valuetype(size(m),{[1 2]}),
    if vis_valuetype(m{2},{[1 2]}) & vis_valuetype(m{1},{'string'}),
      lattice=m{1};    
      msize=m{2}; 
    else
      error('Invalid map size information.');
    end
  end

  %% Check map parameters
  
  switch lattice                   % lattice  
  case 'hexa' 
    ;
  case 'rect'
    ;
  otherwise
    error('Unknown lattice type');
  end
  
  if length(msize)>2                % dimension
    error('Only 2D maps allowed!');
  end
  
                                     
  % Calculate coordinates 
  p=som_unit_coords(msize,lattice,'sheet');

  % Set scaling to 1 as it is done always in this case
  scaling=1;   
end

% Check colorcode

if nargin < 2 | isempty(colorcode),
  colorcode='rgb1';
end
if ~ischar(colorcode)
  error('String value for colorcode mode expected.');
else
 switch colorcode
 case { 'rgb1', 'rgb2', 'rgb3' , 'rgb4' ,'hsv'}
  otherwise
    error([ 'Colorcode mode ' colorcode ' not implemented.']);
  end
end

% Check scaling

if nargin < 3 | isempty(scaling) 
  scaling=1;
end

if ~vis_valuetype(scaling,{'1x1'})
  error('Scaling should be 0 (off) or 1 (on).');
end

%% Action %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% scale coordintes between [0,1]

if scaling  
  n=size(p,1);
  mn=min(p);
  e=max(p)-mn;
  p=(p-repmat(mn,n,1))./repmat(e,n,1);
elseif sum(p(:,1)>1+p(:,1)<0+p(:,2)>1+p(:,2)<0),  
  error('Coordinates out of range [0,1].');
end

switch colorcode 
case 'rgb1'
  h(:,1)=p(:,1);
  h(:,2)=1-p(:,2);
  h(:,3)=p(:,2);
case 'rgb2'
  h(:,1)=p(:,1);
  h(:,2)=1-p(:,2);
  h(:,3)=1-p(:,1);
case 'rgb3'
  h(:,1)=p(:,1);
  h(:,2)=.5;
  h(:,3)=p(:,2);
case 'rgb4'  
 p=rgb4(p);
 h(:,1)=p(:,1);
 h(:,2)=1-p(:,2);
 h(:,3)=p(:,3);
case 'hsv'
  munits = n;
  Hsv = zeros(munits,3);
  for i=1:n, 
    dx = .5-p(i,1);
    dy = .5-p(i,2);
    r = sqrt(dx^2+dy^2);
    if r==0, 
      h=1; 
    elseif dx==0, 
      h=.5; %h=ay; 
    elseif dy==0, 
      h=.5; %h=ax; 
    else 
      h = min(abs(.5/(dx/r)),abs(.5/(dy/r))); 
    end
    
    if r==0, 
      angle = 0; 
    else 
      angle = acos(dx/r); 
      if dy<0, 
	angle = 2*pi-angle; 
      end
    end
    
    Hsv(i,1) = 1-sin(angle/4);
    Hsv(i,2) = 1;
    Hsv(i,3) = r/h; 
    h = hsv2rgb(Hsv);
  end
end


%% Build output %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

colors=h;

%% Subfunctions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% juha %%%%

function p=rgb4(coord)

for i=1:size(coord,1);
 p(i,:)=get_coords(coord(i,:))';
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function coords=get_coords(coords)

%GET_COORDS
%
% get_coords(coords)
%
% ARGUMENTS
%
% coords (1x2 or 2x1 vector) coords(1) is an x-coordinate and coords(2)
%                            y-coordinate.
%
%
% RETURNS
%
% coords (3x1 vector) x,y and z-coordinates.
%

if ~(all(size(coords) == [1 2]) | all(size(coords) == [2 1]))
  error('Argument ''coords'' must be an 2x1 or 1x2 vector.');
end

if all(size(coords) == [1 2])
  coords=coords';
end

if any(coords > 1) any(coords < 0)
  error('Coordinates must lay inside the interval [0,1].');
end

if coords(1) <= 1/(sqrt(2)+1),
  if coords(2) <= line3(coords(1))
    coords=coords_in_base(4,coords);
  elseif coords(2) <= line2(coords(1))
    coords=coords_in_base(1,coords);
  else
    coords=coords_in_base(2,coords);
  end
elseif coords(1) <= sqrt(2)/(sqrt(2)+1)
  if coords(2) <= line1(coords(1))
    coords=coords_in_base(3,coords);
  elseif coords(2) <= line2(coords(1))
    coords=coords_in_base(1,coords);
  else
    coords=coords_in_base(2,coords);
  end
else
  if coords(2) <= line1(coords(1)),
    coords=coords_in_base(3,coords);
  elseif coords(2) <= line4(coords(1))
    coords=coords_in_base(1,coords);
  else
    coords=coords_in_base(5,coords);
  end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function coords=coords_in_base(base_no,coords)

A=[0;1/(sqrt(2)+1)];
E=[1;1];
F=[0;0];
G=[1;0];
H=[0;1];

const=1+1/sqrt(2);

switch base_no
  case 1
    x=(coords-A)*const;
    coords=[(1/sqrt(2))*(x(1)-x(2));0.5*(x(1)+x(2));0.5*(x(1)+x(2))];
  case 2
    x=(coords-H)*const;
    coords=[0;x(1);1+x(2)];
  case 3
    x=(coords-G)*const;
    coords=[1;1+x(1);x(2)];
  case 4
    x=(coords-F)*const;
    coords=[0.5+(1/sqrt(2))*(x(1)-x(2));...
            0.5-(1/sqrt(2))*(x(1)+x(2));... 
            0];
  case 5
    x=(coords-E)*const;
    coords=[0.5+(1/sqrt(2))*(x(1)-x(2));...
            0.5-(1/sqrt(2))*(x(1)+x(2));...      
            1];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y=line1(x)
  
y = x-1/(sqrt(2)+1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y=line2(x)

y = x+1/(sqrt(2)+1);
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y=line3(x)

y = -x+1/(sqrt(2)+1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function y= line4(x)

y = -x+(2*sqrt(2)+1)/(sqrt(2)+1);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
