%   [u,uBG,ierr,h,xx,ambd]=EQ_DIMv_2_0(x,n1,n2,n3,n4,randmode,sample_mult)
%
% TRANSFORMS PARAMETER SAMPLE DATA x TO ITS EQUIVALENT DIMENSION
%
% AUTHOR: S. Lasocki 06/2014 within IS-EPOS project.
%
% DESCRIPTION: An equivalent dimension u of a parameter x is u=FX^(–1)(x), 
%where FX^(–1)(X) is the inverse cumulative distribution function of X. 
% The distribution function of the parameter x, FX(x), is estimated by 
% means of the non-parametric, kernel estimation method. The background
% sample for the estimation can be either the whole vactor x or its user 
% determined part from n1 to n2. The smoothing factor of the kernel 
% estimator of F(x), h, is estimated using the least-squares 
% cross-validation for the Gaussian kernel function. The final form of the 
% kernel is the adaptive kernel.
% The kernel estimation cannot use samples with repeated values. When 
% needed the sample data are randomized within their round-off interval. 
% The round-off interval length - eps is the least non-zero difference 
% between sample data. Three randomization models are supported:
% (1) exponential distribution of x in [x0-eps/2, x0+eps/2], where x0
% is the sample data point and eps is the length of roud-off inteval. The 
% shape parameter of the exponential distribution is estimated from the 
% whole data sample assuming the exponential distribution. (2) normal 
% distribution N(x,eps) of x in [x0-eps/2, x0+eps/2]. (3) uniform 
% distribution of x in [x0-eps/2, x0+eps/2]. 
% Upon user's request the background sample - xx comprises the randomized 
% values of x trippled symmetrically with respect to the values min(x) and
% max(x),or doubled synetrically with respect to the value min(x) or
% max(x). Trippling/doubling should be carried out if the sample values are
% distinctly truncated from both/one side so that the assumption that the
% Weigthing factors row vector for the adaptive kernel is of the same size 
% as xx. 
% See: the references below for a more comprehensive description.
% 
% This is a beta version of the program. Further developments may appear.
%
% REFERENCES:
%Lasocki S. (2014) Geophys J Int. 197(2), 1224-1235, doi:10.1093/gji/ggu062
%Silverman B.W. (1986) Density Estimation for Statistics and Data Analysis, 
%   Chapman and Hall, London 
%Kijko A., Lasocki S., Graham G. (2001) Pure appl. geophys. 158, 1655-1665
%
% INPUT:
%   x - vector of earthquake parameter values
%   n1 - number of the first point defining the background sample
%   n2 - number of the last point defining the background sample
%   n3 - number of the first point defining the testing sample
%   n4 - number of the last point defining the testing sample
%   randmode - string determining the mode of data randomization: 
%           'no'   - no randomization, 
%           'exp'  - exponential randomization, 
%           'norm' - Gaussian randomization,
%           'uni'  - uniform randomization
%   sample_mult - string determining the way of sample multiplication: 
%           'no'   - no multiplication, 
%           'left' - dubbling from the left hand side, 
%           'right - doubbling from the right hand side, 
%           'both' - trippling from both sides.
%
% OUTPUT
%   u - vector of the transformed parameter values (testing sample)
%   uBG - vector of the transformed parameter values (background sample)
%   ierr - h-convergence indicator. ierr=0 if the estimation procedure of 
%       the optimal smoothing factor has converged (the zero of the h 
%       functional has been found, ierr=1 when multiple zeros of h 
%       functional were encountered - the largest h is accepted, ierr = 2 
%       when h functional did not zeroe - the approximate h value is taken.
%   h - kernel smoothing factor.
%   xx - the background sample for the transformation
%   ambd - the weigthing factors for the adaptive kernel
%
% LICENSE
%     This file is a part of the IS-EPOS e-PLATFORM.
%
%     This is free software: you can redistribute it and/or modify it under 
%     the terms of the GNU General Public License as published by the Free 
%     Software Foundation, either version 3 of the License, or 
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
%     See the GNU General Public License for more details.
% 
% ------------------------------------------------------------------------------------------------------------------------
% EXAMPLE TO RUN:
% x=exprnd(1,1000,1);
% [u,uBG,ierr,h,xx,ambd]=EQ_DIMv_2_0(x,1,1000,100,300,'no','no')
% ------------------------------------------------------------------------------------------------------------------------

function [u,uBG,ierr,h,xx,ambd]=EQ_DIMv_2_0(x,n1,n2,n3,n4,randmode,sample_mult)

% xx=x(n1:n2);                                                           %K16JUN2015

if ~strcmp(randmode,'no')
    eps=magn_accur(x);
%  xx=rand_sampl(xx,eps,randmode);
     x=rand_sampl(x,eps,randmode);                      %K16JUN2015

end
   xx=x(n1:n2);                                                             %K16JUN2015
   xt=x(n3:n4);                                                             %K24JAN2019
   
if strcmp(sample_mult,'both')
    x1=min(x);
    x2=max(x);
    xx = potrajanie(xx,x1,x2);
    [h,ierr]=hopt(xx);
    [ambd]=scaling(xx,h);
    [u] = EQ_DIM_trans_x1_x2(xt,xx,ambd,h,x1,x2);
    [uBG] = EQ_DIM_trans_x1_x2(xx,xx,ambd,h,x1,x2);         %K24JAN2019
end
    
if strcmp(sample_mult,'right')
    x0=max(x);
    xx = podwajanie(xx,x0);
    [h,ierr]=hopt(xx);
    [ambd]=scaling(xx,h);
    [u] = EQ_DIM_trans_inf_x2(xt,xx,ambd,h,x0);
    [uBG] = EQ_DIM_trans_inf_x2(xx,xx,ambd,h,x0);             %K24JAN2019
end
    
if strcmp(sample_mult,'left')
    x0=min(x);
    xx = podwajanie(xx,x0);
    [h,ierr]=hopt(xx);
    [ambd]=scaling(xx,h);
    [u] = EQ_DIM_trans_x1_inf(xt,xx,ambd,h,x0);
    [uBG] = EQ_DIM_trans_x1_inf(xx,xx,ambd,h,x0);               %K24JAN2019
end

if strcmp(sample_mult,'no')
    [h,ierr]=hopt(xx);
    [ambd]=scaling(xx,h);
    [u] = EQ_DIM_trans_inf_inf(xt,xx,ambd,h);
    [uBG] = EQ_DIM_trans_inf_inf(xx,xx,ambd,h);                  %K24JAN2019
end
end
    
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% --------------------------- FUNCTIONS ----------------------------%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% EPS
function [eps]=magn_accur(M)
x=sort(M);
d=x(2:length(x))-x(1:length(x)-1);
eps=min(d(d>0));
end

%% Sample multiplication
function x3 = potrajanie(x,x1,x2)
% Triples a sample 
%   If the sample x(i) is truncated from both sides in the interval 
%   [x1,x2] then the trippled sample is [-x(i)+2x1,x(i),-x(i)+2x2]
% x - is the column data vector
% x3 - is the column vector of data doubled and sorted in the ascending
% order
x3=[-x+2*x1
    x
    -x+2*x2];
%x3=sort(x3);                                                    % K31JAN2019 - deactivate ascending sorting
end

function x2 = podwajanie(x,x0)
% Doubles a sample
%   If the sample x(i) is is truncated from the left hand side and belongs 
% to the interval [x0,inf) or it is truncated from the right hand side and
% belongs to the interval (-inf,x0]
%   then the doubled sample is [-x(i)+2x0,x(i)]
% x - is the column data vector
% x2 - is the column vector of data doubled and sorted in the ascending
% order
x2=[-x+2*x0
    x];
%x2=sort(x2);                                                       % K31JAN2019 - deactivate ascending sorting
end


%% HOPT
function [h,ierr]=hopt(x)

%Estimation of the optimal smoothing factor by means of the least squares
%method
% x - column data vector
% The result is an optimal smoothing factor
% ierr=0 - convergence, ierr=1 - multiple h, ierr=2 - approximate h is used 
% The function calls the procedure FZERO for the function 'funct'
% NEW VERSION 2 - without a square matrix. Also equipped with extra zeros
% search

% MODIFIED JUNE 2014

ierr=0;
n=length(x);
x=sort(x);
interval=[0.000001 2*std(x)/n^0.2];
x1=funct(interval(1),x);
x2=funct(interval(2),x);
if x1*x2<0
    fun = @(t) funct(t,x);                                         % For Octave
    x0=interval;                                                      % ForOctave
    [hh(1),fval,exitflag]=fzero(fun,x0);                     % ForOctave

% Extra zeros search
    jj=1;
    for kk=2:7
        interval(1)=1.1*hh(jj);
        interval(2)=interval(1)+(kk-1)*hh(jj);
        x1=funct(interval(1),x);
        x2=funct(interval(2),x);
        if x1*x2<0
            jj=jj+1;
            fun=@(t) funct(t,x);                                   % ForOctave
            x0=interval;                                              % ForOctave
            [hh(jj),fval,exitflag]=fzero(fun,x0);             % ForOctave
        end
    end
    if jj>1;ierr=1;end
    h=max(hh);

   if exitflag==1;return;end

end
h=0.891836*(mean(x)-x(1))/(n^0.2);
ierr=2;
end

function [fct]=funct(t,x)
p2=1.41421356;
n=length(x);
yy=zeros(size(x));
for i=1:n,
   xij=(x-x(i)).^2/t^2;
   y=exp(-xij/4).*((xij/2-1)/p2)-2*exp(-xij/2).*(xij-1);
   yy(i)=sum(y);
end;
fct=sum(yy)-2*n;
clear xij y yy;
end

%% SCALING
function [ambd]=scaling(x,h)

% EVALUATES A VECTOR OF SCALING FACTORS FOR THE NONPARAMETRIC ADAPTATIVE
% ESTIMATION

% x - the n dimensional column vector of data values sorted in the ascending
% order
% h - the optimal smoothing factor
% ambd - the resultant n dimensional row vector of local scaling factors 

n=length(x);
c=sqrt(2*pi);
gau=zeros(1,n);
for i=1:n,
   gau(i)=sum(exp(-0.5*((x(i)-x)/h).^2))/c/n/h;
end
g=exp(mean(log(gau)));
ambd=sqrt(g./gau);
end


%% TRANS_EQ_DIM
function [x_tr] = EQ_DIM_trans_x1_x2(x,x_s,ambd,h,x1,x2)
%Transformation of the variable truncated within the interval [x1,x2]
%   x - the sample to be transformed
%   x_s - the background sample already trippled
%   ambd - weighting factors of adaptive kernel [1:length(x_s)]
%   h - optimal scaling factor for x_s
%   x_tr - the sample after transformation [1:length(x)]
%   x1 - left hand side truncation
%   x2 - right hand side truncation

n=length(x_s);
for i=1:length(x);
    if x(i)<x1; x_tr(i)=0;elseif x(i)>x2; x_tr(i)=1;
    else
       x_tr(i)=3*(Dystr_npr(x(i),x_s,ambd,h,n)-Dystr_npr(x1,x_s,ambd,h,n));    
    end
end
x_tr=x_tr';
end

function [x_tr] = EQ_DIM_trans_inf_inf(x,x_s,ambd,h)
%Transformation of the variable from (-inf,inf)
%   x - the sample to be transformed
%   x_s - the background sample already trippled
%   ambd - weighting factors of adaptive kernel [1:length(x_s)]
%   h - optimal scaling factor for x_s
%   x_tr - the sample after transformation [1:length(x)]

for i=1:length(x);
    x_tr(i)=Dystr_npr(x(i),x_s,ambd,h,length(x_s));                                
end
x_tr=x_tr';
end


function [x_tr] = EQ_DIM_trans_inf_x2(x,x_s,ambd,h,x2)
%Transformation of the variable from (-inf, x2]
%   x - the sample to be transformed
%   x_s - the background sample already trippled
%   ambd - weighting factors of adaptive kernel [1:length(x_s)]
%   h - optimal scaling factor for x_s
%   x_tr - the sample after transformation [1:length(x)]
%   x2 - right hand side truncation

for i=1:length(x);
    x_tr(i)=1.0;
    if x(i)<=x2
        x_tr(i)=2*Dystr_npr(x(i),x_s,ambd,h,length(x_s));                          % 
    end
end
x_tr=x_tr';
end

function [x_tr] = EQ_DIM_trans_x1_inf(x,x_s,ambd,h,x1)
%Transformation of the variable from [x1,inf)
%   x - the sample to be transformed
%   x_s - the background sample already trippled
%   ambd - weighting factors of adaptive kernel [1:length(x_s)]
%   h - optimal scaling factor for x_s
%   x_tr - the sample after transformation [1:length(x)]
%   x1 - left hand side truncation

n=length(x_s);
for i=1:length(x);
    x_tr(i)=0;
    if x(i)>=x1
        x_tr(i)=2*(Dystr_npr(x(i),x_s,ambd,h,n)-Dystr_npr(x1,x_s,ambd,h,n));                
    end
end
x_tr=x_tr';
end


%% Non-parameteric Adaptive cdf. random variables from (-inf,inf)
function [Fgau]=Dystr_npr(y,x,ambd,h,n)
   Fgau=sum(normcdf(((y-x)./ambd')./h))/n;
end

%% RAND_SAMPLE
function [x_corr]=rand_sampl(x,eps,randmode)

if strcmp(randmode,'exp')
    muhat = expfit(x-min(x));
    F1=1-exp(-(x-min(x)-0.5*eps)/muhat);
    F2=1-exp(-(x-min(x)+0.5*eps)/muhat);
    u=rand(size(x));
    w=u.*(F2-F1)+F1;
    x_corr=min(x)-log(1-w).*muhat;
end

if strcmp(randmode,'norm')
    F1=normcdf(x-0.5*eps,x,eps);
    F2=normcdf(x+0.5*eps,x,eps);
    u=rand(size(x));
    w=u.*(F2-F1)+F1;
    x_corr=norminv(w,x,eps);
end

if strcmp(randmode,'uni')
    r=rand(length(x),1);
    x_corr=x-0.5*eps+eps.*r;
end

end
