% RSFIT - find p value for a given value in a given distribution
% using Ramberg-Schmeiser distribution
%
% Usage: >> p = rsfit(x, val)
% >> [p c l chi2] = rsfit(x, val, plot)
%
% Input:
% x - [float array] accumulation values
% val - [float] value to test
% plot - [0|1|2] plot fit. Using 2, the function avoids creating
% a new figure. Default: 0.
%
% Output:
% p - p value
% c - [mean var skewness kurtosis] distribution cumulants
% l - [4x float vector] Ramberg-Schmeiser distribution best fit
% parameters.
% chi2 - [float] chi2 for goodness of fit (based on 12 bins).
% Fit is significantly different from data histogram if
% chi2 > 19 (5%)
%
% Author: Arnaud Delorme, SCCN, 2003
%
% See also: RSADJUST, RSGET, RSPDFSOLV, RSPFUNC
%
% Reference: Ramberg, J.S., Tadikamalla, P.R., Dudewicz E.J., Mykkytka, E.F.
% A probability distribution and its uses in fitting data.
% Technimetrics, 1979, 21: 201-214.
% Copyright (C) 2003 Arnaud Delorme, SCCN, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
function [p, c, l, res] = rsfit(x, val, plotflag)
if nargin < 2
help rsfit;
return;
end
if nargin < 3
plotflag = 0;
end
% moments
% -------
m1 = mean(x);
m2 = sum((x-m1).^2)/length(x);
m3 = sum((x-m1).^3)/length(x);
m4 = sum((x-m1).^4)/length(x);
xmean = m1;
xvar = m2;
xskew = m3/(m2^1.5);
xkurt = m4/(m2^2);
c = [ xmean xvar xskew xkurt ];
if xkurt < 0
disp('rsfit error: Can not fit negative kurtosis');
save('/home/arno/temp/dattmp.mat', '-mat', 'x');
disp('data saved to disk in /home/arno/temp/dattmp.mat');
end
% find fit
% --------
try,
[sol tmp exitcode] = fminsearch('rspdfsolv', [0.1 0.1], optimset('TolX',1e-12, 'MaxFunEvals', 100000000), abs(xskew), xkurt);
catch, exitcode = 0; % did not converge
end
if ~exitcode
try, [sol tmp exitcode] = fminsearch('rspdfsolv', -[0.1 0.1], optimset('TolX',1e-12, 'MaxFunEvals', 100000000), abs(xskew), xkurt);
catch, exitcode = 0; end
end
if ~exitcode, error('No convergence'); end
if sol(2)*sol(1) == -1, error('Wrong sign for convergence'); end
%fprintf(' l-val:%f\n', sol);
res = rspdfsolv(sol, abs(xskew), xkurt);
l3 = sol(1);
l4 = sol(2);
%load res;
%[tmp indalpha3] = min( abs(rangealpha3 - xskew) );
%[tmp indalpha4] = min( abs(rangealpha4 - xkurt) );
%l3 = res(indalpha3,indalpha4,1);
%l4 = res(indalpha3,indalpha4,2);
%res = res(indalpha3,indalpha4,3);
% adjust fit
% ----------
[l1 l2 l3 l4] = rsadjust(l3, l4, xmean, xvar, xskew);
l = [l1 l2 l3 l4];
p = rsget(l, val);
% compute goodness of fit
% -----------------------
if nargout > 3 || plotflag
% histogram of value 12 bins
% --------------------------
[N X] = hist(x, 25);
interval = X(2)-X(1);
X = [X-interval/2 X(end)+interval/2]; % borders
% regroup bin with less than 5 values
% -----------------------------------
indices2rm = [];
for index = 1:length(N)-1
if N(index) < 5
N(index+1) = N(index+1) + N(index);
indices2rm = [ indices2rm index];
end
end
N(indices2rm) = [];
X(indices2rm+1) = [];
indices2rm = [];
for index = length(N):-1:2
if N(index) < 5
N(index-1) = N(index-1) + N(index);
indices2rm = [ indices2rm index];
end
end
N(indices2rm) = [];
X(indices2rm) = [];
% compute expected values
% -----------------------
for index = 1:length(X)-1
p1 = rsget( l, X(index+1));
p2 = rsget( l, X(index ));
expect(index) = length(x)*(p1-p2);
end
% value of X2
% -----------
res = sum(((expect - N).^2)./expect);
% plot fit
% --------
if plotflag
if plotflag ~= 2, figure('paperpositionmode', 'auto'); end
hist(x, 10);
% plot fit
% --------
xdiff = X(end)-X(1);
abscisia = linspace(X(1)-0.2*xdiff, X(end)+0.2*xdiff, 100);
%abscisia = (X(1:end-1)+X(2:end))/2;
expectplot = zeros(1,length(abscisia)-1);
for index = 2:length(abscisia);
p1 = rsget( l, abscisia(index-1));
p2 = rsget( l, abscisia(index ));
expectplot(index-1) = length(x)*(p2-p1);
% have to do this subtraction since this a cumulate density distribution
end
abscisia = (abscisia(2:end)+abscisia(1:end-1))/2;
hold on; plot(abscisia, expectplot, 'r');
% plot PDF
% ----------
pval = linspace(0,1, 102); pval(1) = []; pval(end) = [];
rp = l(1) + (pval.^l(3) - (1-pval).^l(4))/l(2);
fp = l(2)*1./(l(3).*(pval.^(l(3)-1)) + l(4).*((1-pval).^(l(4)-1)));
[maxval index] = max(expect);
[tmp closestind] = min(abs(rp - abscisia(index)));
fp = fp./fp(closestind)*maxval;
plot(rp, fp, 'g');
legend('Chi2 fit (some bins have been grouped)', 'Pdf', 'Data histogram' );
xlabel('Bins');
ylabel('# of data point per bin');
title (sprintf('Fit of distribution using Ramberg-Schmeiser distribution (Chi2 = %2.4g)', res));
end
end
return