function [SAmeas, OutMatrix] = Morris_Measure_Groups(NumFact, Sample, Output, p, Group)
% [SAmeas, OutMatrix] = Morris_Measure_Groups(NumFact, Sample, Output, p, Group)
%
% Given the Morris sample matrix, the output values and the group matrix compute the Morris measures
% -------------------------------------------------------------------------
% INPUTS
% -------------------------------------------------------------------------
% Group [NumFactor, NumGroups] := Matrix describing the groups.
%   Each column represents one group.
%   The element of each column are zero if the factor is not in the
%   group. Otherwise it is 1.
%
% Sample := Matrix of the Morris sampled trajectories
%
% Output := Matrix of the output(s) values in correspondence of each point
%   of each trajectory
%
% k = Number of factors
% -------------------------------------------------------------------------
% OUTPUTS
% OutMatrix (NumFactor*NumOutputs, 3)= [Mu*, Mu, StDev]
%   for each output it gives the three measures of each factor
% -------------------------------------------------------------------------
%
% Written by Jessica Cariboni and Francesca Campolongo
% Joint Research Centre, The European Commission,
%

% Copyright © 2005 European Commission
% Copyright © 2012-2023 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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.
%
% Dynare 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.
%
% You should have received a copy of the GNU General Public License
% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.

if nargin==0
    skipline()
    disp('[SAmeas, OutMatrix] = Morris_Measure_Groups(NumFact, Sample, Output, p, Group);')
    return
end

if nargin < 5, Group=[]; end

NumGroups = size(Group,2);

if nargin < 4 || isempty(p)
    p = 4;
end
Delt = p/(2*p-2);

if NumGroups ~= 0
    sizea = NumGroups;      % Number of groups
else
    sizea = NumFact;
end

r=size(Sample,1)/(sizea+1);     % Number of trajectories
if NumGroups > 0
    OutMatrix = NaN(sizea*size(Output,2),1);
else
    OutMatrix = NaN(sizea*size(Output,2),3);
end

% For Each Output
for k=1:size(Output,2)
    OutValues=Output(:,k);

    % For each r trajectory
    for i=1:r
        % For each step j in the trajectory
        % Read the orientation matrix fact for the r-th sampling
        % Read the corresponding output values
        Single_Sample = Sample(i+(i-1)*sizea:i+(i-1)*sizea+sizea,:);
        Single_OutValues = OutValues(i+(i-1)*sizea:i+(i-1)*sizea+sizea,:);
        A = (Single_Sample(2:sizea+1,:)-Single_Sample(1:sizea,:))';
        Delta = A(find(A));

        % For each point of the fixed trajectory compute the values of the Morris function. The function
        % is partitioned in four parts, from order zero to order 4th.
        % SAmeas=NaN();
        for j=1:sizea   % For each point in the trajectory i.e for each factor
                        % matrix of factor which changes
            if NumGroups ~= 0
                AuxFind (:,1) = A(:,j);
                Change_factor = find(abs(AuxFind)>1e-010);
                % If we deal with groups we can only estimate the new mu*
                % measure since factors in the same groups can move in
                % opposite direction and the definition of the standard
                % Morris mu cannopt be applied.
                % In the new version the elementary effect is defined with
                % the absolute value.
                SAmeas(i,Change_factor') = abs((Single_OutValues(j) - Single_OutValues(j+1) )/Delt);
            else
                Change_factor(j,i) = find(Single_Sample(j+1,:)-Single_Sample(j,:));
                % If no groups --> we compute both the original and
                % modified measure
                if Delta(j) > 0                              %=> +Delta
                    SAmeas(Change_factor(j,i),i) = (Single_OutValues(j+1) - Single_OutValues(j) )/Delt; %(2/3);
                else                                         %=> -Delta
                    SAmeas(Change_factor(j,i),i) = (Single_OutValues(j) - Single_OutValues(j+1) )/Delt; %(2/3);
                end
            end
        end   %for j=1:sizea

    end     %for i=1:r

    if NumGroups ~= 0
        SAmeas = SAmeas';
    end

    % Compute Mu AbsMu and StDev
    if any(any(isnan(SAmeas)))
        AbsMu=NaN(NumFact,1);
        if NumGroups == 0
            Mu=NaN(NumFact,1);
            StDev=NaN(NumFact,1);
        end
        for j=1:NumFact
            SAm = SAmeas(j,:);
            SAm = SAm(find(~isnan(SAm)));
            rr=length(SAm);
            AbsMu(j,1) = sum(abs(SAm),2)/rr;
            if NumGroups == 0
                Mu(j,1) = sum(SAm,2)/rr;
                StDev(j,1) = sum((SAm - repmat(Mu(j),1,rr)).^2/(rr*(rr-1)),2).^0.5;
            end
        end
    else
        AbsMu = sum(abs(SAmeas),2)/r;
        if NumGroups == 0
            Mu = sum(SAmeas,2)/r;
            StDev = sum((SAmeas - repmat(Mu,1,r)).^2/(r*(r-1)),2).^0.5;
        end
    end

    % Define the output Matrix - if we have groups we cannot define the old
    % measure mu, only mu* makes sense
    if NumGroups > 0
        OutMatrix((k-1)*sizea+1:k*sizea,:) = AbsMu;
    else
        OutMatrix((k-1)*sizea+1:k*sizea,:) = [AbsMu, Mu, StDev];
    end
end     % For Each Output
