function additional_checks_v4(R, pars, opts)

%ADDITIONAL_CHECKS Perform additional checks over input to ENTROPY.

%   Copyright (C) 2009 Cesare Magri
%   Version 4.0.0

% -------
% LICENSE
% -------
% This software is distributed free under the condition that:
%
% 1. it shall not be incorporated in software that is subsequently sold;
%
% 2. the authorship of the software shall be acknowledged and the following
%    article shall be properly cited in any publication that uses results
%    generated by the software:
%
%      Magri C, Whittingstall K, Singh V, Logothetis NK, Panzeri S: A
%      toolbox for the fast information analysis of multiple-site LFP, EEG
%      and spike train recordings. BMC Neuroscience 2009 10(1):81;
%
% 3.  this notice shall remain in place in each source file.


disp('===== OPTIONS SUMMARY =========================================')
% Recap of selected options
disp(['  - method: ' pars.method]);
disp(['  - bias correction: ' opts.bias]);
disp(['  - btsp repetitions: ' num2str(pars.btsp)]);
disp('===== ADDITIONAL WARNINGS =====================================')

warningFlag = false;

% Are there wrong fields in the outpt list? -------------------------------
NselectedOutputOpts = any(pars.HR)   + ...
                      any(pars.HRS)  + ...
                      any(pars.HlR)  + ...
                      any(pars.HlRS) + ...
                      any(pars.HiR)  + ...
                      any(pars.HiRS) + ...
                      any(pars.ChiR) + ...
                      any(pars.HshR) + ...
                      any(pars.HshR);
                  
if pars.lengthVarargin>NselectedOutputOpts
    warningFlag = true;
    msg = 'Unknown selection in the output options list.';
    warning('addChecks:unknownOutputOption', msg);
end

numberOfFields = length(fieldnames(opts));
% Are there unused fields in the options structure? -----------------------
if pars.numberOfSpecifiedOptions + 3<numberOfFields
    warningFlag = true;
    msg = 'Number of fields in the options structure greater than number of specified options.';
    warning('addChecks:UnusedFields', msg);
end

mask = build_logical_mask(pars.Nt, max(pars.Nt), pars.Ns);
% Has the binning been properly done (for direct method only) -------------
if strcmp(pars.method,'dr')

    % 1. Are response values integers only?
    if sum(sum(abs(R(:, mask) - fix(abs(R(:, mask)))),2),3) ~= 0
        msg = ['Method ''' pars.method ''' requires the responses to be discretized into (non-negative) integers.'];
        error('addChecks:Binning:RnotBinned', msg);
    end

    % 2. Have all cells been binned using the same number of bins?
    Nb = max(R(:,mask),[],2);
    if length(unique(Nb))~=1
        warningFlag = true;
        msg = ['Note: the following warning holds only for responses which are continuous in nature:'...
               'Different number of bins appear to have been used for discretizing different responses.'];
        warning('addChecks:Binning:NbNotConstant', msg);
    end
    
    % 3. Does R include all values from 0 to Nb as a response?
    for c=1:pars.Nc
        uniqueR = unique(R(c,mask));
        for bin=1:Nb(c)
            if ~any(uniqueR==bin)
                warningFlag = true;
                msg = ['Note: the following warning holds only for responses which are continuous in nature:'...
                       'Trials appear not to include all values from 0 up to the selcted number of bins.\n'...
                       'Some bias correction procedures may be affected by accidental null response counts.'];
                warning('addChecks:Binning:allBinsNotIncludedAsResponse', msg);
            end
        end
    end
end


% Do non-trials all have the same value? ----------------------------------
if any(~mask(:))
    if length(unique(R(:,~mask)))~=1
        msg = 'Non-trials appear to have non-unique values.';
        warning('addChecks:NonTrials:nonUniqueValue', msg)
    end
end


% Bias correction 'pt' can only be used with 'dr' method ------------------
if pars.biasCorrNum==2 && ~strcmpi(pars.method, 'dr')
    warningFlag = true;
    msg = 'Bias correction ''pt'' can only be used with method ''dr''.';
    error('addChecks:ptAndNonDrMethod', msg);
end

% Bias corection 'gsb' can only be used with 'gs' method ------------------
if pars.biasCorrNum==3 && ~strcmpi(pars.method, 'gs')
    warningFlag = true;
    msg = 'Bias correction ''gsb'' can only be used with method ''gs''.';
    error('addChecks:gsbAndNonGsMethod', msg);
end


% If no warning was found -------------------------------------------------
if ~warningFlag
    disp('No error or warning.');
end

% Done
disp('===============================================================')


function warningFlag = H_ind_checks(output_opt, pars, warningFlag)
%WARNINGFLAG Perform checks for H_ind() entropies

if ~strcmpi(pars.method, 'dr')
    warningFlag = true;
    msg = ['Only method opt ''dr'' can be used with output opt ''' output_opt ''': returning null value'];
    warning(['addChecks:' output_opt ':nonDrMethod'], msg);
end

if ~any(pars.biasCorrNum==[0 1])
    warningFlag = true;
    msg = ['Only bias correction opt ''qe'' can be used with output opt ''' output_opt ''': returning naive estimate'];
    warning(['addChecks:' output_opt ':nonQeBiasCorr'], msg);
end;