function p = kde(points,ks,weights,typeS)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% kde(points,ksize[,weights][,type]) -- nonparametric density estimate of a pdf
%
% points is the [Ndim x Npoints] array of kernel locations
% ksize may be a scalar, [Ndim x 1], [Ndim x Npoints], or
% a string (for data-based methods; see @kde/ksize for allowed methods)
% weights is [1 x Npoints] and need not be pre-normalized
% type can be one of: 'Gaussian', 'Laplacian', 'Epanetchnikov'
% (only 1st letter required) (Gaussian by default)
%
% See also: ksize, getPoints, getBW, getWeights, getType
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (C) 2003 Alexander Ihler; distributable under GPL -- see README.txt
type = 0;
kstype = [];
if ((nargin == 1) & isa(points,'kde'))
% CONSTRUCTOR FROM KDE-TYPE
type = points.type; weights = getWeights(points);
if (size(points.bandwidth,2)>2*points.N), ks = getBW(points,1:getNpts(points));
else ks = getBW(points,1); end;
if (type == 0), ks = ks.^2; end;
points = getPoints(points);
elseif (nargin == 1) % ugh, needed for deserialization
for i=1:numel(points)
p(i) = class(points(i), 'kde');
end
p = reshape(p, size(points));
return
else if (nargin > 0)
% CONSTRUCTOR FROM RAW DATA
error(nargchk(2,4,nargin));
if (isa(ks,'char')) kstype = ks; ks =1; end;
if (size(ks,1) == 1) ks = repmat(ks,[size(points,1),1]); end;
if (nargin < 3) weights = ones(1,size(points,2)); end;
if (isempty(weights)) weights = ones(1,size(points,2)); end;
if (nargin < 4) typeS = 'g';
else typeS = lower(typeS); typeS = typeS(1); end;
switch(typeS)
case 'l', type = 2;
case 'e', type = 1;
case 'g', type = 0; ks = ks.^2;
otherwise, error('Type must be one of (G)aussian, (L)aplacian, or (E)panetchnikov');
end;
weights = weights/sum(weights);
% Check matrix sizes:
[D,N] = size(points);
if any(size(weights)~=[1,N]) error('Weights must be [1xNpoints] (or empty)'); end;
bwsize = size(ks);
if (any(bwsize~=[1,1]) && any(bwsize~=[D,1]) && any(bwsize~=[D,N]))
error('Bandwidth must be scalar, [Dx1], [DxN], or an automatic selection method');
end;
else
% EMPTY CONSTRUCTOR
points = []; ks = []; weights = [];
end; end;
p = BallTreeDensity(points,weights,ks,type);
p = class(p,'kde');
if (length(kstype))
p = ksize(p,kstype);
end;