-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspm_dcm_mtf.m
192 lines (150 loc) · 5.71 KB
/
spm_dcm_mtf.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
function [S,K,s,w,t,dfdx] = spm_dcm_mtf(P,M,U)
% computes transfer functions using the system's eigenspectrum
% FORMAT [S,K,s,w,t,dfdx] = spm_dcm_mtf(P,M,[U])
%
% P - model parameters
% M - model (with flow M.f and expansion point M.x and M.u)
% U - induces expansion around steady state (from spm_dcm_neural_x(P,M))
%
% S - modulation transfer functions (complex)
% K - Volterra kernels (real)
% s - eigenspectrum (complex)
% w - frequencies (Hz) = M.Hz
% t - time (seconds) = M.pst
% dfdx - Jacobian
%
% This routine uses the eigensolution of a dynamical systems Jacobian to
% complete the first-order Volterra terminals and transfer functions in
% peristimulus and frequency space respectively. The advantage of using
% the-solution is that unstable modes (eigenvectors of the Jacobian) can be
% conditioned (suppressed). Furthermore, this provides for a
% computationally efficient and transparent evaluation of the transfer
% functions that draws on linear signal processing theory in frequency
% space.
%__________________________________________________________________________
% Copyright (C) 2012 Wellcome Trust Centre for Neuroimaging
% Karl Friston
% $Id: spm_dcm_mtf.m 6856 2016-08-10 17:55:05Z karl $
% get local linear approximation
%==========================================================================
% solve for steady-state - if required
%--------------------------------------------------------------------------
if nargin > 2
M.x = spm_dcm_neural_x(P,M);
end
% check expansion points
%--------------------------------------------------------------------------
try, M.x; catch, M.x = spm_dcm_x_neural(P,M.dipfit.model); end
try, M.u; catch, M.u = sparse(M.m,1); end
% frequencies and peristimulus time of interest
%--------------------------------------------------------------------------
w = (1:64)';
t = (0:64 - 1)'/64;
try, w = M.Hz(:); end
try, t = M.pst(:); end
try, t = M.dt*(1:M.N)'; end
% delay operator - if not specified already
%--------------------------------------------------------------------------
if isfield(M,'D')
dfdx = spm_diff(M.f,M.x,M.u,P,M,1);
dfdu = spm_diff(M.f,M.x,M.u,P,M,2);
D = M.D;
else
if nargout(M.f) == 4
[f,dfdx,D,dfdu] = feval(M.f,M.x,M.u,P,M);
elseif nargout(M.f) == 3
[f,dfdx,D] = feval(M.f,M.x,M.u,P,M);
dfdu = spm_diff(M.f,M.x,M.u,P,M,2);
elseif nargout(M.f) == 2
[f,dfdx] = feval(M.f,M.x,M.u,P,M);
dfdu = spm_diff(M.f,M.x,M.u,P,M,2);
D = 1;
else
dfdx = spm_diff(M.f,M.x,M.u,P,M,1);
dfdu = spm_diff(M.f,M.x,M.u,P,M,2);
D = 1;
end
end
% Jacobian and eigenspectrum
%==========================================================================
if nargout(M.g) == 2
[g,dgdx] = feval(M.g,M.x,M.u,P,M);
else
dgdx = spm_diff(M.g,M.x,M.u,P,M,1);
end
dfdx = D*dfdx;
dfdu = D*dfdu;
try
[v,s] = eig(full(dfdx),'nobalance');
catch
v = eye(size(dfdx));
s = NaN(size(dfdx));
end
s = diag(s);
% condition unstable eigenmodes
%--------------------------------------------------------------------------
if max(w) > 1
s = 1j*imag(s) + real(s) - exp(real(s));
else
s = 1j*imag(s) + min(real(s),-1/32);
end
% Transfer functions
%==========================================================================
% transfer functions (FFT of kernel)
%--------------------------------------------------------------------------
nw = size(w,1); % number of frequencies
nt = size(t,1); % number of time bins
ng = size(dgdx,1); % number of outputs
nu = size(dfdu,2); % number of inputs
nk = size(v,2); % number of modes
S = zeros(nw,ng,nu);
K = zeros(nt,ng,nu);
% derivatives over modes
%--------------------------------------------------------------------------
dgdv = dgdx*v;
dvdu = pinv(v)*dfdu;
for j = 1:nu
for i = 1:ng
for k = 1:nk
% transfer functions (FFT of kernel)
%--------------------------------------------------------------
Sk = 1./(1j*2*pi*w - s(k));
S(:,i,j) = S(:,i,j) + dgdv(i,k)*dvdu(k,j)*Sk;
% kernels
%--------------------------------------------------------------
if nargout > 1
Kk = exp(s(k)*t);
K(:,i,j) = K(:,i,j) + real(dgdv(i,k)*dvdu(k,j)*Kk);
end
end
end
end
return
% NOTES: internal consistency with explicit Fourier transform of kernels
%==========================================================================
% augment and bi-linearise (with intrinsic delays)
%--------------------------------------------------------------------------
M.D = D;
[M0,M1,L] = spm_bireduce(M,P);
% project onto spatial modes
%--------------------------------------------------------------------------
try, L = M.U'*L; end
% kernels
%--------------------------------------------------------------------------
N = length(t);
dt = (t(2) - t(1));
[K0,K1] = spm_kernels(M0,M1,L,N,dt);
% Transfer functions (FFT of kernel)
%--------------------------------------------------------------------------
S1 = fft(K1)*dt;
w1 = ((1:N) - 1)/(N*dt);
j = w1 < max(w);
S1 = S1(j,1,1);
w1 = w1(j);
subplot(2,2,1), plot(t,K(:,1,1),t,K1(:,1,1));
title('kernels','fontsize',16)
xlabel('peristimulus time')
subplot(2,2,2), plot(w,real(S(:,1,1)), w1,real(S1(:,1,1))); hold on
subplot(2,2,2), plot(w,imag(S(:,1,1)),':',w1,imag(S1(:,1,1)),':'); hold off
title('transfer functions','fontsize',16)
xlabel('frequency');