creates basis functions for each trial type {i} in struct BF{i} FORMAT [BF BFstr] = spm_get_bf(name,T,dt,Fstr,n_s [,n_c]) name - name{1 x n} name of trials or conditions T - time bins per scan dt - time bin length {seconds} Fstr - Prompt string (usually indicates session) n_s - Session number n_c - Condition number (optional) BF{i} - Array of basis functions for trial type {i} BFstr - description of basis functions specified _______________________________________________________________________ spm_get_bf prompts for basis functions to model event or epoch-related responses. The basis functions returned are unitary and orthonormal when defined as a function of peri-stimulus time in time-bins. It is at this point that the distinction between event and epoch-related responses enters. _______________________________________________________________________ @(#)spm_get_bf.m 2.20 Karl Friston 01/08/22 $Id$
0001 function [BF,BFstr] = pr_spm_get_bf(name,T,dt,Fstr,n_s,n_c) 0002 % creates basis functions for each trial type {i} in struct BF{i} 0003 % FORMAT [BF BFstr] = spm_get_bf(name,T,dt,Fstr,n_s [,n_c]) 0004 % 0005 % name - name{1 x n} name of trials or conditions 0006 % T - time bins per scan 0007 % dt - time bin length {seconds} 0008 % Fstr - Prompt string (usually indicates session) 0009 % n_s - Session number 0010 % n_c - Condition number (optional) 0011 % 0012 % BF{i} - Array of basis functions for trial type {i} 0013 % BFstr - description of basis functions specified 0014 %_______________________________________________________________________ 0015 % 0016 % spm_get_bf prompts for basis functions to model event or epoch-related 0017 % responses. The basis functions returned are unitary and orthonormal 0018 % when defined as a function of peri-stimulus time in time-bins. 0019 % It is at this point that the distinction between event and epoch-related 0020 % responses enters. 0021 %_______________________________________________________________________ 0022 % @(#)spm_get_bf.m 2.20 Karl Friston 01/08/22 0023 % 0024 % $Id$ 0025 0026 0027 %-GUI setup 0028 %----------------------------------------------------------------------- 0029 spm_help('!ContextHelp',mfilename) 0030 0031 %-Condition arguments 0032 %----------------------------------------------------------------------- 0033 if nargin < 6, n_c = []; end 0034 0035 0036 % if no trials 0037 %----------------------------------------------------------------------- 0038 n = length(name); 0039 if ~n 0040 BF = {}; 0041 BFstr = 'none'; 0042 return 0043 end 0044 0045 % determine sort of basis functions 0046 %----------------------------------------------------------------------- 0047 Rtype = {'events',... 0048 'epochs',... 0049 'mixed'}; 0050 if n == 1 0051 Rtype = Rtype(1:2); 0052 spm_input(name{1},1,'d',Fstr) 0053 else 0054 spm_input(Fstr,1,'d') 0055 end 0056 0057 Rov = spm_input('are these trials',2,'b',Rtype); 0058 Fstr=''; 0059 0060 switch Rov 0061 0062 % assemble basis functions {bf} 0063 %=============================================================== 0064 case 'events' 0065 0066 % model event-related responses 0067 %--------------------------------------------------------------- 0068 Ctype = { 0069 'hrf (alone)',... 0070 'hrf (with time derivative)',... 0071 'hrf (with time and dispersion derivatives)',... 0072 'basis functions (Fourier set)',... 0073 'basis functions (Fourier set with Hanning)',... 0074 'basis functions (Gamma functions)',... 0075 'basis functions (Gamma functions with derivatives)',... 0076 'basis functions (Finite Impulse Response)'}; 0077 str = 'Select basis set'; 0078 Cov = spm_input(str,2,'m',Ctype); 0079 BFstr = Ctype{Cov}; 0080 0081 0082 % create basis functions 0083 %--------------------------------------------------------------- 0084 if Cov == 4 | Cov == 5 0085 0086 % Windowed (Hanning) Fourier set 0087 %------------------------------------------------------- 0088 str = 'window length {secs}'; 0089 pst = spm_input(str,3,'e',32); 0090 pst = [0:dt:pst]'; 0091 pst = pst/max(pst); 0092 h = spm_input('order',4,'e',4); 0093 0094 0095 % hanning window 0096 %------------------------------------------------------- 0097 if Cov == 4 0098 g = ones(size(pst)); 0099 else 0100 g = (1 - cos(2*pi*pst))/2; 0101 end 0102 0103 % zeroth and higher terms 0104 %------------------------------------------------------- 0105 bf = g; 0106 for i = 1:h 0107 bf = [bf g.*sin(i*2*pi*pst)]; 0108 bf = [bf g.*cos(i*2*pi*pst)]; 0109 end 0110 0111 elseif Cov == 6 | Cov == 7 0112 0113 0114 % Gamma functions alone 0115 %------------------------------------------------------- 0116 pst = [0:dt:32]'; 0117 dx = 0.01; 0118 bf = spm_gamma_bf(pst); 0119 0120 % Gamma functions and derivatives 0121 %------------------------------------------------------- 0122 if Cov == 7 0123 bf = [bf (spm_gamma_bf(pst - dx) - bf)/dx]; 0124 end 0125 0126 0127 elseif Cov == 8 0128 0129 0130 % Finite Impulse Response 0131 %------------------------------------------------------- 0132 bin = spm_input('bin size (seconds)',3,'e',2); 0133 nb = spm_input('number of bins',4,'e',8); 0134 0135 bf = kron(eye(nb),ones(round(bin/dt),1)); 0136 0137 0138 elseif Cov == 1 | Cov == 2 | Cov == 3 0139 0140 0141 % hrf and derivatives 0142 %------------------------------------------------------- 0143 [bf p] = pr_spm_hrf(dt); 0144 0145 % add time derivative 0146 %------------------------------------------------------- 0147 if Cov == 2 | Cov == 3 0148 0149 dp = 1; 0150 p(6) = p(6) + dp; 0151 D = (bf(:,1) - pr_spm_hrf(dt,p))/dp; 0152 bf = [bf D(:)]; 0153 p(6) = p(6) - dp; 0154 0155 % add dispersion derivative 0156 %----------------------------------------------- 0157 if Cov == 3 0158 0159 dp = 0.01; 0160 p(3) = p(3) + dp; 0161 D = (bf(:,1) - pr_spm_hrf(dt,p))/dp; 0162 bf = [bf D(:)]; 0163 end 0164 end 0165 end 0166 0167 0168 % Orthogonalize and fill in basis function structure 0169 %--------------------------------------------------------------- 0170 bf = pr_spm_orth(bf); 0171 for i = 1:n 0172 BF{i} = bf; 0173 end 0174 0175 0176 % assemble basis functions {bf} 0177 %=============================================================== 0178 case 'epochs' 0179 0180 0181 % covariates of interest - Type 0182 %--------------------------------------------------------------- 0183 Ctype = {'basis functions (Discrete Cosine Set)',... 0184 'basis functions (Mean & exponential decay)',... 0185 'fixed response (Half-sine)',... 0186 'fixed response (Box-car)'}; 0187 str = 'Select type of response'; 0188 Cov = spm_input(str,2,'m',Ctype); 0189 0190 BFstr = Ctype{Cov}; 0191 0192 % convolve with HRF? 0193 %--------------------------------------------------------------- 0194 if Cov == 1 0195 str = 'number of basis functions'; 0196 h = spm_input(str,3,'e',2); 0197 end 0198 0199 % convolve with HRF? 0200 %--------------------------------------------------------------- 0201 HRF = spm_input('convolve with hrf',3,'b','yes|no',[1 0]); 0202 0203 % ask for temporal differences 0204 %--------------------------------------------------------------- 0205 str = 'add temporal derivatives'; 0206 TD = spm_input(str,4,'b','yes|no',[1 0]); 0207 0208 0209 % Assemble basis functions for each trial type 0210 %--------------------------------------------------------------- 0211 for i = 1:n 0212 0213 str = ['epoch length {scans} for ' name{i}]; 0214 W = spm_input(str,'+1','r','',1); 0215 pst = [1:W*T]' - 1; 0216 pst = pst/max(pst); 0217 0218 % Discrete cosine set 0219 %------------------------------------------------------- 0220 if Cov == 1 0221 0222 bf = []; 0223 for j = 0:(h - 1) 0224 bf = [bf cos(j*pi*pst)]; 0225 end 0226 0227 % Mean and exponential 0228 %------------------------------------------------------- 0229 elseif Cov == 2 0230 0231 bf = [ones(size(pst)) exp(-pst/4)]; 0232 0233 % Half sine wave 0234 %------------------------------------------------------- 0235 elseif Cov == 3 0236 0237 bf = sin(pi*pst); 0238 0239 % Box car 0240 %------------------------------------------------------- 0241 elseif Cov == 4 0242 0243 bf = ones(size(pst)); 0244 0245 end 0246 0247 % convolve with hemodynamic response function - hrf 0248 %------------------------------------------------------- 0249 if HRF 0250 hrf = pr_spm_hrf(dt); 0251 [p q] = size(bf); 0252 D = []; 0253 for j = 1:q 0254 D = [D conv(bf(:,j),hrf)]; 0255 end 0256 bf = D; 0257 end 0258 0259 % add temporal differences if specified 0260 %------------------------------------------------------- 0261 if TD 0262 bf = [bf [diff(bf); zeros(1,size(bf,2))]/dt]; 0263 end 0264 0265 % Orthogonalize and fill in Sess structure 0266 %------------------------------------------------------- 0267 BF{i} = pr_spm_orth(bf); 0268 end 0269 0270 0271 % mixed event and epoch model 0272 %=============================================================== 0273 case 'mixed' 0274 for i = 1:n 0275 BF(i) = pr_spm_get_bf(name(i),T,dt,'',n_s,i); 0276 end 0277 BFstr = 'mixed'; 0278 end 0279 0280 0281 0282 %======================================================================= 0283 %- S U B - F U N C T I O N S 0284 %======================================================================= 0285 0286 0287 % compute Gamma functions functions 0288 %----------------------------------------------------------------------- 0289 function bf = spm_gamma_bf(u) 0290 % returns basis functions used for Volterra expansion 0291 % FORMAT bf = spm_gamma_bf(u); 0292 % u - times {seconds} 0293 % bf - basis functions (mixture of Gammas) 0294 %_______________________________________________________________________ 0295 u = u(:); 0296 bf = []; 0297 for i = 2:4 0298 m = 2^i; 0299 s = sqrt(m); 0300 bf = [bf spm_Gpdf(u,(m/s)^2,m/s^2)]; 0301 end