function [CVA] = spm_cva_ui(action,varargin) % VOI extraction of adjusted data and CVA % FORMAT [CVA] = spm_cva_ui('specify',xSPM,SPM,CVA) % % xSPM - structure containing specific SPM details % xSPM.Ic - indice of contrast (in SPM.xCon) % SPM - structure containing generic analysis details % % CVA.contrast - contrast name % CVA.name - CVA name % CVA.c - contrast weights % CVA.X - contrast subspace % CVA.Y - whitened and adjusted data % CVA.X0 - null space of contrast % % CVA.XYZ - locations of voxels (mm) % CVA.xyz - seed voxel location (mm) % CVA.VOX - dimension of voxels (mm) % % CVA.V - canonical vectors (data) % CVA.v - canonical variates (data) % CVA.W - canonical vectors (design) % CVA.w - canonical variates (design) % CVA.C - canonical contrast (design) % % CVA.chi - Chi-squared statistics testing D >= i % CVA.df - d.f. % CVA.p - p-values % % also saved in CVA_*.mat in the SPM working directory % % FORMAT [CVA] = spm_cva_ui('results',CVA) % Display the results of a CVA analysis %__________________________________________________________________________ % % This routine allows one to make inferences about effects that are % distributed in a multivariate fashion or pattern over voxels. It uses % conventional canonical variates (CVA) analysis (also know as canonical % correlation analysis, ManCova and linear discriminant analysis). CVA is % a complement to MVB, in that the predictor variables remain the design % matrix and the response variable is the imaging data in the usual way. % However, the multivariate aspect of this model allows one to test for % designed effects that are distributed over voxels and thereby increase % the sensitivity of the analysis. % % Because there is only one test, there is no multiple comparison problem. % The results are shown in term of the maximum intensity projection of the % (positive) canonical image or vector and the canonical variates based on % (maximally) correlated mixtures of the explanatory variables and data. % % CVA uses the generalised eigenvalue solution to the treatment and % residual sum of squares and products of a general linear model. The % eigenvalues (i.e., canonical values), after transformation, have a % chi-squared distribution and allow one to test the null hypothesis that % the mapping is D or more dimensional. This inference is shown as a bar % plot of p-values. The first p-value is formally identical to that % obtained using Wilks' Lambda and tests for the significance of any % mapping. % % This routine uses the current contrast to define the subspace of interest % and treats the remaining design as uninteresting. Conventional results % for the canonical values are used after the data (and design matrix) have % been whitened; using the appropriate ReML estimate of non-sphericity. % % CVA can be used for decoding because the model employed by CVA does not % care about the direction of the mapping (hence canonical correlation % analysis). However, one cannot test for mappings between nonlinear % mixtures of regional activity and some experimental variable (this is % what the MVB was introduced for). % % References: % % Characterizing dynamic brain responses with fMRI: a multivariate % approach. Friston KJ, Frith CD, Frackowiak RS, Turner R. NeuroImage. 1995 % Jun;2(2):166-72. % % A multivariate analysis of evoked responses in EEG and MEG data. Friston % KJ, Stephan KM, Heather JD, Frith CD, Ioannides AA, Liu LC, Rugg MD, % Vieth J, Keber H, Hunter K, Frackowiak RS. NeuroImage. 1996 Jun; % 3(3):167-174. %__________________________________________________________________________ % Copyright (C) 2008-2014 Wellcome Trust Centre for Neuroimaging % Karl Friston % $Id: spm_cva_ui.m 7081 2017-05-27 19:36:09Z karl $ %-Get figure handles %-------------------------------------------------------------------------- Finter = spm_figure('FindWin','Interactive'); spm_results_ui('Clear'); spm_input('!DeleteInputObj'); %-Review old analysis or proceed with a new one %-------------------------------------------------------------------------- if ~nargin || isempty(action) action = spm_input('Canonical Variates Analysis','!+1','b', ... {'New Analysis','Results'}, char({'specify','results'}), 1); if strcmpi(action,'results'), varargin = {}; end end switch lower(action) case 'specify' %================================================================== % C V A : S P E C I F Y %================================================================== if nargin > 1, xSPM = varargin{1}; end if nargin > 2, SPM = varargin{2}; end if nargin > 3, CVA = varargin{3}; end header = get(Finter,'Name'); set(Finter,'Name','Canonical Variates analysis') %-Contrast specification %------------------------------------------------------------------ con = SPM.xCon(xSPM.Ic).name; c = SPM.xCon(xSPM.Ic).c; c = full(c); %-VOI specification %------------------------------------------------------------------ try name = CVA.name; catch name = spm_input('name','-8','s',con); end name = ['CVA_' strrep(name,' ','_') '.mat']; %-Get current location {mm} %------------------------------------------------------------------ try xyzmm = CVA.xY.xyz; catch xyzmm = spm_results_ui('GetCoords'); end %-Specify search volume %------------------------------------------------------------------ try xY = CVA.xY; CVA = rmfield(CVA,'xY'); catch xY = []; end xY.xyz = xyzmm; Q = ones(1,size(SPM.xVol.XYZ, 2)); XYZmm = SPM.xVol.M(1:3,:)*[SPM.xVol.XYZ; Q]; [xY, XYZ, j] = spm_ROI(xY, XYZmm); %-Extract required data from results files %================================================================== spm('Pointer','Watch') %-Get explanatory variables (data) %------------------------------------------------------------------ Y = spm_get_data(SPM.xY.VY,SPM.xVol.XYZ(:,j)); if isempty(Y) spm('alert*',{'No voxels in this VOI';'Please use a larger volume'},... 'Canonical Variates analysis'); return end %-Remove serial correlations and get design (note X := W*X) %------------------------------------------------------------------ Y = SPM.xX.W*Y; X = SPM.xX.xKXs.X; %-Null-space %------------------------------------------------------------------ X0 = []; try, X0 = [X0 blkdiag(SPM.xX.K.X0)]; end %-drift terms try, X0 = [X0 spm_detrend(SPM.xGX.gSF)]; end %-global estimate %-Canonical Variate Analysis %================================================================== U = spm_mvb_U(Y,'compact',spm_svd([X0, X-X*c*pinv(c)]),XYZ); CVA = spm_cva(Y, X, X0, c, U); %-Save results %================================================================== M = SPM.xVol.M(1:3,1:3); %-voxels to mm matrix VOX = sqrt(diag(M'*M))'; %-voxel dimensions %-Assemble results %------------------------------------------------------------------ CVA.contrast = con; %-contrast name CVA.name = name; %-CVA name CVA.XYZ = XYZ; %-locations of voxels (mm) CVA.xyz = xyzmm; %-seed voxel location (mm) CVA.VOX = VOX; %-dimension of voxels (mm) CVA.U = U; %-dimension reduction (SVD) %-Save %------------------------------------------------------------------ save(fullfile(SPM.swd,name),'CVA', spm_get_defaults('mat.format')); assignin('base','CVA',CVA); %-Display results %------------------------------------------------------------------ spm_cva_ui('results',CVA); %-Reset title %------------------------------------------------------------------ set(Finter,'Name',header) spm('Pointer','Arrow') case 'results' %================================================================== % C V A : R E S U L T S %================================================================== %-Get CVA if necessary %------------------------------------------------------------------ if isempty(varargin) [CVA,sts] = spm_select(1,'mat',... 'Select CVA to display',[],[],'^CVA.*\.mat$'); if ~sts, return; end else CVA = varargin{1}; end if ischar(CVA) CVA = load(CVA); CVA = CVA.CVA; end %-Show results %------------------------------------------------------------------ spm_figure('GetWin','CVA'); %-Unpack %------------------------------------------------------------------ VOX = CVA.VOX; XYZ = CVA.XYZ; %-Maximum intensity projection (first canonical image) %------------------------------------------------------------------ subplot(2,2,1) spm_mip(CVA.V(:,1).*(CVA.V(:,1) > 0),XYZ(1:3,:),diag(VOX)); axis image title({'(Principal) canonical image',[CVA.name ':' CVA.contrast]}) %-Inference and canonical variates %------------------------------------------------------------------ Xstr{1} = 'Dimensionality'; Xstr{2} = ['Chi-squared: ' sprintf('%6.1f ', CVA.chi)]; Xstr{3} = [' df: ' sprintf('%6.0f ',CVA.df) ]; subplot(2,2,2) bar(log(CVA.p)); hold on plot([0 (length(CVA.p) + 1)],log(0.05)*[1 1],'r:','LineWidth',4), hold off xlabel(Xstr) ylabel('log p-value') axis square title({'Test of dimensionality';sprintf('minimum p = %.2e',min(CVA.p))}) subplot(2,2,3) plot(CVA.w,CVA.v,'.') xlabel('prediction') ylabel('response') axis square title('Canonical variates') %-Canonical contrast %------------------------------------------------------------------ i = find(CVA.p < 0.05); str = 'Significant canonical contrasts'; if isempty(i) i = 1; str = 'first canonical contrast'; end subplot(2,2,4) bar(CVA.C(:,i)) xlabel('Parameter') axis square title(str) otherwise error('Unknown action.'); end