function [hp,hn,hx,hs] = plotmat(X,varargin)
% plotmat  Visualise 2D matrix.
%
% Syntax
% =======
%
%     [POSH,NEGH,NANINFH,MAXH] = grfun.plotmat(X,...)
%
% Short-cut syntax
% =================
%
%     [POSH,NEGH,NANINFH,MAXH] = plotmat(X,...)
%
% Input arguments
% ================
%
% * `X` [ numeric ] - 2D matrix that will be visualised; ND matrices will
% be unfolded in 2nd dimension before plotting.
%
% Output arguments
% =================
%
% * `POSH` [ numeric ] - Handles to discs displaying non-negative entries.
%
% * `NEGH` [ numeric ] - Handles to discs displeying negative entries.
%
% * `NANINFH` [ numeric ] - Handles to NaN or Inf marks.
%
% * `MAXH` [ numeric ] - Handles to circles displaying maximum value.
%
% Options
% ========
%
% * `'colNames='` [ char | cellstr | *empty* ] - Names that will be given to
% the columns of the matrix.
%
% * `'rowNames='` [ char | cellstr | *empty* ] - Names that will be give to
% the row of the matrix.
%
% * `'maxCircle='` [ `true` | *`false`* ] - Displey a circle denoting the
% maximum value around each entry.
%
% * `'scale='` [ numeric | *`'auto'`* ] - Maximum value (positive) relative to
% which all matrix entries will be scaled; by default the scale is the
% maximum entry in the input matrix, `max(max(abs(X(isfinite(X))))`.
%
% Description
% ============
%
% Example
% ========
%

% -IRIS Toolbox.
% -Copyright (c) 2007-2012 Jaromir Benes.

    X = X(:,:);

    opt = passvalopt('grfun.plotmat',varargin{:});
    
    if ischar(opt.scale) && strcmpi(opt.scale,'auto')
        opt.scale = max(max(abs(X(isfinite(X)))));
    end
    
    if ~isfinite(opt.scale)
        opt.scale = 1;
    end
    
    % Bkw compatibility options:
    if ~isempty(opt.frame)
        opt.maxcircle = opt.frame;
    end

%**************************************************************************
    
    [nrow,ncol] = size(X);    
    radius = 0.45;
    X = X/opt.scale * radius;
    nanlength = 0.1;
    gray = 0.6*[1,1,1];
    
    hp = [];
    hn = [];
    hx = [];
    hs = [];
    status = ishold();
    
    for row = 1 : nrow
        for col = 1 : ncol
            x = X(row,col);
            if ~isfinite(x)
                hx(end+1) = ...
                    plot(col+[-1,1]*nanlength,1+nrow-row+[1,-1]*nanlength);
                hold('on');
                hx(end+1) = ...
                    plot(col+[-1,1]*nanlength,1+nrow-row+[-1,1]*nanlength);
            else
                h = grfun.plotcircle(col,1+nrow-row,abs(x),'fill',true);
                if x >= 0
                    hp(end+1) = h;
                else
                    hn(end+1) = h;
                end
                hold('on');
                hs(end+1) = ...
                    grfun.plotcircle(col,1+nrow-row,radius,'color',gray);
            end
        end
    end
    
    if ~status
        hold('off');
    end
    
    set(hp,'faceColor',[0,0,0.8],'edgeColor','none');
    set(hn,'faceColor',[0.8,0,0],'edgeColor','none');
    if ~opt.maxcircle
        set(hs,'lineStyle','none','marker','none');
    end
    set(hx,'lineWidth',1.5,'color',gray);
    axis('equal');
    set(gca(), ...
        'xAxisLocation','top', ...
        'xLim',[0,ncol+1], ...
        'yLim',[0,nrow+1], ...
        'xTick',1:ncol, ...
        'yTick',1:nrow, ...
        'xLimMode','manual', ...
        'yLimMode','manual', ...
        'xTickMode','manual', ...
        'yTickMode','manual');
    
    opt.rownames = getnames_(opt.rownames,nrow);
    if ~isempty(opt.rownames)
        set(gca,'yTickLabel',opt.rownames(nrow:-1:1));
    end
    
    opt.colnames = getnames_(opt.colnames,ncol);
    if ~isempty(opt.colnames)
        set(gca,'xTickLabel',opt.colnames(1:ncol));
    end
    
    set(gca,'xTickLabelMode','manual','yTickLabelMode','manual');
    
end

% Subfunctions follow.

% $ ***********************************************************************
function c = getnames_(c,n)
    if ischar(c)
        c = regexp(c,'[^,;]+','match');
        c = strtrim(c);
    end
    if isempty(c)
        c = {};
        return
    end
    if length(c) < n
        c(end+1:n) = {''};
    end
end
% $ getnames_().