function [me, st, md, no] = nanstats(D)

%NANSTATS NaN operations used by somtoolbox.
%
% [mean, std, median, nans] = nanstats(data)
%
% ARGUMENTS 
%
%  sData  (struct or matrix) data/map struct or data matrix, 
%          size dlen x dim
% RETURNS
%
%  me     (double) columnwise mean
%  st     (double) columnwise standard deviation
%  md     (double) columnwise median
%  no     (vector) columnwise number of samples (finite, not-NaN)

% Copyright (c) 1997,1998 by the SOM toolbox programming team.
% http://www.cis.hut.fi/projects/somtoolbox/

% Version 1.0beta ecco 150797, 190997
% Version 1.0gamma juuso 300798

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check arguments

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

if isstruct(D), 
  if strcmp(D.type,'som_map'), D = D.codebook;
  else D = D.data;
  end
end
[dlen dim] = size(D);
me = zeros(dim,1)+NaN;
md = me;
st = me;
no = me;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% computation

for i = 1:dim,
  ind = find(~isnan(D(:, i)) & ~isinf(D(:,i))); % indices of non-NaN/Inf elements
  n   = length(ind);                            % no of non-NaN/Inf elements

  me(i) = sum(D(ind, i)); % compute average
  if n == 0, me(i) = NaN; else me(i) = me(i) / n; end

  md(i) = median(D(ind, i)); % compute median

  st(i) = sum((me(i) - D(ind, i)).^2); % compute standard deviation
  if n == 0,     st(i) = NaN;
  elseif n == 1, st(i) = 0;
  else st(i) = sqrt(st(i) / (n - 1));
  end

  no(i) = n; % number of samples (finite, not-NaN)
end

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

