function PlotSOM(Weight,shape,n,m)

% 様々なSOMを表示させる
% ニューロンの色は赤、結合線の色は青
%
% PlotSOM(Weight)
% PlotSOM(Weight,shape)
% PlotSOM(Weight,shape,n,m)
%
% Weight : Dim次元 M個のニューロンの重みベクトル (M x Dim)
% [shape](string)  :map shape, 'grid' by default
% 'grid' : SOMの配置が正方形(2-dimensional)の場合
%            SOMの行数m = 列数m 
% 
% 'rectangle' : SOMの配置が長方形の場合
%            n : SOMの"行"数     m : SOMの"列"数
% 
% 'rope'   : SOMの配置1-dimensionalの場合
%            紐状に繋がっており、円ではない
% 
% 'circle' : SOMの配置1-dimensionalの場合
% 'ring'     円に繋がっている（ニューロン1とmが繋がっている）
% 
% 'hex'    : SOMの配置が六角形(2-dimensional)
%
% === How to use ===
% 
% PlotSOM(Weight)は、正方形のSOMを表示させる。
% PlotSOM(Weight,'shape')は、shapeで指定した形のSOMを表示させる。
% ただし、shapeを長方形(rectangle)に指定したときは、
% PlotSOM(Weight,'rectangle',n,m)とし、
% SOMのニューロンの行数nと列数mを指定しなければならない。
%（つまり、長方形SOMはn*m個のニューロンを持つ。）
%
% n = m のとき、
% PlotSOM(Weight,'rectangle',n,m) は PlotSOM(Weight) と同じ。
%
% 注：3次元のSOMを表示させるためには、関数gplot3が必要です。
% gplot3をパスの通ったフォルダに置いてください。
% Download gplot3 : http://nlab.ee.tokushima-u.ac.jp/nlab/haruna/memo/gplot3.html
%
% 6 June 2007 Haruna MATSUSHITA
%

if nargin < 1;  error('???引数が必要です。もしくは足りません'); 
elseif nargin ==1; shape = 'grid';end
[M,Inputd] = size(Weight);   % M: ニューロンの個数      Inputd : 入力の次元
if Inputd >=4; error('4次元以上のSOMは表示できません！');end

% -- SOMの結合関係 NodeC を計算 ---
switch lower(shape)
    case {'grid', 'hex'}
        m = sqrt(M); 
        if m^2 ~= M; error('SOMが正方形の時、ニューロン数は整数の二乗でなくてはいけません。');end
        NodeC = connect(m,shape);
    case 'rectangle'
        if nargin <= 2; error('SOMの行数n、列数mを指定してください。');end
        if n < 2 | m < 2; warning('2D-SOMのニューロンは、nとmが2以上である必要があります。');end
        NodeC = connect(m,shape,n);
    otherwise
        NodeC = connect(M,shape);
end

% --- 関数GplotでSOMの結合関係と位置を取り出し、plotでSOMを表示 ---
if Inputd == 2
    [X,Y] = gplot(NodeC,Weight);
    plot(X,Y,'o-b','MarkerFaceColor','r','MarkerEdgeColor','none','MarkerSize',5)
    
elseif Inputd == 3
    [X,Y,Z] = gplot3(NodeC,Weight);
    plot3(X,Y,Z,'o-b','MarkerFaceColor','r','MarkerEdgeColor','none','MarkerSize',5)
end

% End Func


% ------ subfunction -------
function NodeC = connect(m,shape,n)

% Self-Organization Maps
% neuron の結合関係を計算する
% NodeC = connect(m)
% NodeC = connect(m,'shape')
% -- For shape == 'rectangle' --
% NodeC = connect(m,'shape',n)
%
% 'grid' : SOMの配置が正方形(2-dimensional)の場合
%            NodeC(1:m*m,1:m*m) = connect(m)
% 
% 'rectangle' : SOMの配置が長方形の場合
%            NodeC(1:n*m,1:n*m) = connect(m,'rectangle',n)
% 
% 'rope'   : SOMの配置1-dimensionalの場合
%            紐状に繋がっており、円ではない
% 
% 'circle' : SOMの配置1-dimensionalの場合
% 'ring'     円に繋がっている（ニューロン1とmが繋がっている）
%            NodeC(1:m,1:m) = connect(m)
% 
% 'hex'    : SOMの配置が六角形(2-dimensional)
% 
%  20 June 2006    Haruna MATSUSHITA

if nargin < 2; error('入力引数が足りません');end
switch lower(shape)
    case {'grid', 'square'} 
        n = m; 
end
    

switch lower(shape)
    case {'grid','rectangle'}
        if n <= 1 | m <= 1; NodeC = ones(n*m,n*m);
        else
            NodeC = zeros(n*m,n*m);
            for i = 1:n*m           % neuron の番号
                if i <= m                       % 上段(一行目)のニューロン
                    NodeC(i+m,i) = 1;
                    if mod(i,m) == 1            % 左端のニューロン
                        NodeC(i+1,i) = 1;
                    elseif mod(i,m) == 0        % 右端のニューロン 
                        NodeC(i-1,i) = 1;
                    else
                        NodeC(i+1,i) = 1;
                        NodeC(i-1,i) = 1;
                    end
                elseif i > m*(n-1)                % 下段(最終行)のニューロン
                    NodeC(i-m,i) = 1;
                    if mod(i,m) == 1            % 左端のニューロン
                        NodeC(i+1,i) = 1;
                    elseif mod(i,m) == 0        % 右端のニューロン
                        NodeC(i-1,i) = 1;
                    else
                        NodeC(i+1,i) = 1;
                        NodeC(i-1,i) = 1;
                    end
                else
                    NodeC(i+m,i) = 1;
                    NodeC(i-m,i) = 1;
                    if mod(i,m) == 1            % 左端のニューロン
                        NodeC(i+1,i) = 1;
                    elseif mod(i,m) == 0        % 右端のニューロン
                        NodeC(i-1,i) = 1;
                    else
                        NodeC(i+1,i) = 1;
                        NodeC(i-1,i) = 1;
                    end
                end
            end
        end
        
   case 'rope'
       NodeC = zeros(m,m);
       for i = 1:m           % neuron の番号  
           if i == 1               % 左端のニューロン
               NodeC(i+1,i) = 1;    
           elseif i == m         % 右端のニューロン
               NodeC(i-1,i) = 1;
           else
               NodeC(i-1,i) = 1;
               NodeC(i+1,i) = 1;
           end
       end
       
   case {'circle','ring'}
       NodeC = zeros(m,m);
       for i = 1:m           % neuron の番号  
           if i == 1               % 左端のニューロン
               NodeC(i+1,i) = 1;
               NodeC(m,i) = 1;
           elseif i == m         % 右端のニューロン
               NodeC(i-1,i) = 1;
               NodeC(1,i) = 1;
           else
               NodeC(i-1,i) = 1;
               NodeC(i+1,i) = 1;
           end
       end
       
   case 'hex'
       NodeC = zeros(m*m,m*m);
       for i = 1:m           % neuron の番号
           for k = 1:m
               now = (m*(i-1)+k);
               if i ==1                       % 上段(一行目)のニューロン
                   NodeC(now+m,now) = 1;
                   if k == 1            % 左端のニューロン
                       NodeC(now+1,now) = 1;
                       NodeC(now+m+1,now) = 1;
                   elseif k == m        % 右端のニューロン 
                       NodeC(now-1,now) = 1;
                   else
                       NodeC(now+1,now) = 1;
                       NodeC(now-1,now) = 1;
                       NodeC(now+m+1,now) = 1;
                   end
               elseif i == m                % 下段(最終行)のニューロン
                   NodeC(now-m,now) = 1;
                   if mod(i,2) == 0
                       if k == 1            % 左端のニューロン
                           NodeC(now+1,now) = 1;
                       elseif k == m        % 右端のニューロン
                           NodeC(now-1,now) = 1;
                           NodeC(now-m-1,now) = 1;
                       else
                           NodeC(now+1,now) = 1;
                           NodeC(now-1,now) = 1;
                           NodeC(now-m-1,now) = 1;
                           
                       end                    
                   else
                       if k == 1            % 左端のニューロン
                           NodeC(now+1,now) = 1;
                           NodeC(now-m+1,now) = 1;
                       elseif k == m        % 右端のニューロン
                           NodeC(now-1,now) = 1;
                       else
                           NodeC(now+1,now) = 1;
                           NodeC(now-1,now) = 1;
                           NodeC(now-m+1,now) = 1;
                       end
                   end
               else
                   NodeC(now+m,now) = 1;
                   NodeC(now-m,now) = 1;
                   if mod(i,2) == 0
                       if k == 1            % 左端のニューロン
                           NodeC(now+1,now) = 1;
                       elseif k == m        % 右端のニューロン
                           NodeC(now-1,now) = 1;
                           NodeC(now-m-1,now) = 1;
                           NodeC(now+m-1,now) = 1;                        
                       else
                           NodeC(now+1,now) = 1;
                           NodeC(now-1,now) = 1;
                           NodeC(now+m-1,now) = 1;
                           NodeC(now-m-1,now) = 1;
                       end
                   else
                       if k == 1            % 左端のニューロン
                           NodeC(now+1,now) = 1;
                           NodeC(now-m+1,now) = 1;
                           NodeC(now+m+1,now) = 1;  
                       elseif k == m        % 右端のニューロン
                           NodeC(now-1,now) = 1;                      
                       else
                           NodeC(now+1,now) = 1;
                           NodeC(now-1,now) = 1;
                           NodeC(now+m+1,now) = 1;
                           NodeC(now-m+1,now) = 1;
                       end
                   end
               end
           end
       end
end