function [f,dfdx,D,dfdu] = spm_fx_fmri(x,u,P,M)
% State equation for a dynamic [bilinear/nonlinear/Balloon] model of fMRI
% responses
% FORMAT [f,dfdx,D,dfdu] = spm_fx_fmri(x,u,P,M)
% x      - state vector
%   x(:,1) - excitatory neuronal activity            ue
%   x(:,2) - vascular signal                          s
%   x(:,3) - rCBF                                  ln(f)
%   x(:,4) - venous volume                         ln(v)
%   x(:,5) - deoyxHb                               ln(q)
%  [x(:,6) - inhibitory neuronal activity             ui
%
% f      - dx/dt
% dfdx   - df/dx
% dfdu   - df/du
% D      - delays
%
%__________________________________________________________________________
%
% References for hemodynamic & neuronal state equations:
% 1. Buxton RB, Wong EC & Frank LR. Dynamics of blood flow and oxygenation
%    changes during brain activation: The Balloon model. MRM 39:855-864,
%    1998.
% 2. Friston KJ, Mechelli A, Turner R, Price CJ. Nonlinear responses in
%    fMRI: the Balloon model, Volterra kernels, and other hemodynamics.
%    Neuroimage 12:466-477, 2000.
% 3. Stephan KE, Kasper L, Harrison LM, Daunizeau J, den Ouden HE,
%    Breakspear M, Friston KJ. Nonlinear dynamic causal models for fMRI.
%    Neuroimage 42:649-662, 2008.
% 4. Marreiros AC, Kiebel SJ, Friston KJ. Dynamic causal modelling for
%    fMRI: a two-state model.
%    Neuroimage. 2008 Jan 1;39(1):269-78.
%__________________________________________________________________________
% Copyright (C) 2002-2014 Wellcome Trust Centre for Neuroimaging

% Karl Friston & Klaas Enno Stephan
% $Id: spm_fx_fmri.m 6432 2015-05-09 12:58:12Z karl $

% options
%--------------------------------------------------------------------------
if nargin < 4, M = struct([]); end
if isfield(M,'symmetry'), symmetry = M.symmetry; else symmetry = 0; end


% Neuronal motion
%==========================================================================
P.A   = full(P.A);                       %    linear parameters
P.B   = full(P.B);                       % bi-linear parameters
P.C   = P.C/16;                          % exogenous parameters
P.D   = full(P.D);                       % nonlinear parameters


% implement differential state equation y = dx/dt (neuronal)
%--------------------------------------------------------------------------
f    = x;

% if there are five hidden states per region, only one is neuronal
%==========================================================================
if size(x,2) == 5
    
    
    % if P.A encodes the eigenvalues of the (average) connectivity matrix
    %======================================================================
    if isvector(P.A)
        
        % excitatory connections
        %------------------------------------------------------------------
        EE = spm_dcm_fmri_mode_gen(P.A,M.modes);
        
        % input dependent modulation
        %------------------------------------------------------------------
        for i = 1:size(P.B,3)
            EE = EE + u(i)*P.B(:,:,i);
        end
        
        % and nonlinear (state) terms
        %------------------------------------------------------------------
        for i = 1:size(P.D,3)
            EE = EE + x(i,1)*P.D(:,:,i);
        end
        
    else % otherwise average connections are encoded explicitly
        %==================================================================
        
        % input dependent modulation
        %------------------------------------------------------------------
        for i = 1:size(P.B,3)
            P.A(:,:,1) = P.A(:,:,1) + u(i)*P.B(:,:,i);
        end
        
        % and nonlinear (state) terms
        %------------------------------------------------------------------
        for i = 1:size(P.D,3)
            P.A(:,:,1) = P.A(:,:,1) + x(i,1)*P.D(:,:,i);
        end
        
        % combine forward and backward connections if necessary
        %------------------------------------------------------------------
        if size(P.A,3) > 1
            P.A  = exp(P.A(:,:,1)) - exp(P.A(:,:,2));
        end
        
        % one neuronal state per region: diag(A) is a log self-inhibition
        %------------------------------------------------------------------
        SE     = diag(P.A);
        EE     = P.A - diag(exp(SE)/2 + SE);
        
        % symmetry constraints for demonstration purposes
        %------------------------------------------------------------------
        if symmetry, EE = (EE + EE')/2; end
        
    end
    
    % flow
    %----------------------------------------------------------------------
    f(:,1) = EE*x(:,1) + P.C*u(:);
    
    
else  % otherwise two neuronal states per region
    %======================================================================
    
    
    % input dependent modulation
    %----------------------------------------------------------------------
    for i = 1:size(P.B,3)
        P.A(:,:,1) = P.A(:,:,1) + u(i)*P.B(:,:,i);
    end
    
    % and nonlinear (state) terms
    %----------------------------------------------------------------------
    for i = 1:size(P.D,3)
        P.A(:,:,1) = P.A(:,:,1) + x(i,1)*P.D(:,:,i);
    end
    
    % extrinsic (two neuronal states): enforce positivity
    %----------------------------------------------------------------------
    n     = size(P.A,1);            % number of regions
    EE    = exp(P.A(:,:,1))/8;
    IE    = diag(diag(EE));         % intrinsic inhibitory to excitatory
    EE    = EE - IE;                % extrinsic excitatory to excitatory
    EI    = eye(n,n);               % intrinsic excitatory to inhibitory
    SE    = eye(n,n)/2;             % intrinsic self-inhibition (excitatory)
    SI    = eye(n,n);               % intrinsic self-inhibition (inhibitory)
    
    % excitatory proportion
    %----------------------------------------------------------------------
    if size(P.A,3) > 1
        phi = spm_phi(P.A(:,:,2)*2);
        EI  = EI + EE.*(1 - phi);
        EE  = EE.*phi - SE;
    else
        EE  = EE - SE;
    end
    
    % motion - excitatory and inhibitory: f = dx/dt
    %----------------------------------------------------------------------
    f(:,1) = EE*x(:,1) - IE*x(:,6) + P.C*u(:);
    f(:,6) = EI*x(:,1) - SI*x(:,6);
    
end

% Hemodynamic motion
%==========================================================================

% hemodynamic parameters
%--------------------------------------------------------------------------
%   H(1) - signal decay                                   d(ds/dt)/ds)
%   H(2) - autoregulation                                 d(ds/dt)/df)
%   H(3) - transit time                                   (t0)
%   H(4) - exponent for Fout(v)                           (alpha)
%   H(5) - resting oxygen extraction                      (E0)
%   H(6) - ratio of intra- to extra-vascular components   (epsilon)
%          of the gradient echo signal
%--------------------------------------------------------------------------
H        = [0.64 0.32 2.00 0.32 0.4];

% exponentiation of hemodynamic state variables
%--------------------------------------------------------------------------
x(:,3:5) = exp(x(:,3:5));

% signal decay
%--------------------------------------------------------------------------
sd       = H(1)*exp(P.decay);

% transit time
%--------------------------------------------------------------------------
tt       = H(3)*exp(P.transit);

% Fout = f(v) - outflow
%--------------------------------------------------------------------------
fv       = x(:,4).^(1/H(4));

% e = f(f) - oxygen extraction
%--------------------------------------------------------------------------
ff       = (1 - (1 - H(5)).^(1./x(:,3)))/H(5);


% implement differential state equation f = dx/dt (hemodynamic)
%--------------------------------------------------------------------------
f(:,2)   = x(:,1) - sd.*x(:,2) - H(2)*(x(:,3) - 1);
f(:,3)   = x(:,2)./x(:,3);
f(:,4)   = (x(:,3) - fv)./(tt.*x(:,4));
f(:,5)   = (ff.*x(:,3) - fv.*x(:,5)./x(:,4))./(tt.*x(:,5));
f        = f(:);


if nargout < 2, return, end


% Neuronal Jacobian
%==========================================================================
[n,m] = size(x);
if m == 5
    
    % one neuronal state per region
    %----------------------------------------------------------------------
    dfdx{1,1} = EE;
    for i = 1:size(P.D,3)
        D  = P.D(:,:,i) + diag((diag(EE) - 1).*diag(P.D(:,:,i)));
        dfdx{1,1}(:,i) = dfdx{1,1}(:,i) + D*x(:,1);
    end
    
else
    
    % two neuronal states: NB nonlinear (D) effects not implemented)
    %----------------------------------------------------------------------
    dfdx{1,1} = EE;
    dfdx{1,6} = - IE;
    dfdx{6,1} = EI;
    dfdx{6,6} = - SI;
    
end

% input
%==========================================================================
dfdu{1,1} = P.C;
for i = 1:size(P.B,3)
    B  = P.B(:,:,i) + diag((diag(EE) - 1).*diag(P.B(:,:,i)));
    dfdu{1,1}(:,i) = dfdu{1,1}(:,i) + B*x(:,1);
end
dfdu{2,1} = sparse(n*(m - 1),length(u(:)));


% Hemodynamic Jacobian
%==========================================================================
dfdx{2,1} = speye(n,n);
dfdx{2,2} = diag(-sd);
dfdx{2,3} = diag(-H(2)*x(:,3));
dfdx{3,2} = diag( 1./x(:,3));
dfdx{3,3} = diag(-x(:,2)./x(:,3));
dfdx{4,3} = diag( x(:,3)./(tt.*x(:,4)));
dfdx{4,4} = diag(-x(:,4).^(1/H(4) - 1)./(tt*H(4)) - (1./x(:,4).*(x(:,3) - x(:,4).^(1/H(4))))./tt);
dfdx{5,3} = diag((x(:,3) + log(1 - H(5)).*(1 - H(5)).^(1./x(:,3)) - x(:,3).*(1 - H(5)).^(1./x(:,3)))./(tt.*x(:,5)*H(5)));
dfdx{5,4} = diag((x(:,4).^(1/H(4) - 1)*(H(4) - 1))./(tt*H(4)));
dfdx{5,5} = diag((x(:,3)./x(:,5)).*((1 - H(5)).^(1./x(:,3)) - 1)./(tt*H(5)));


% concatenate
%--------------------------------------------------------------------------
dfdx      = spm_cat(dfdx);
dfdu      = spm_cat(dfdu);
D         = 1;
