178 lines
7.7 KiB
Mathematica
178 lines
7.7 KiB
Mathematica
|
classdef TFCEobj<handle
|
||
|
properties
|
||
|
%default values for H and E represpenting area under the curve
|
||
|
H=0;
|
||
|
E=1; %NB there is one E value per dimension.
|
||
|
D=[]; %A 2D (future N-D) matrix where dim1 is instance (i.e. independend TFCE's to be calculated,
|
||
|
%dim2 is time .
|
||
|
%In the future, dim 3, dim 4, and dim 5 could become space dimensions (more akin to smith et al)
|
||
|
nstep=100; %number of stepts to use over your range
|
||
|
hmax=100;
|
||
|
TFCE=[];
|
||
|
S=[]; %place holder for surrogate data
|
||
|
STFCE=[]; %place holder for TFCE values of surrogate data
|
||
|
P=struct('uncorrected',[]); %place holder for P values
|
||
|
end
|
||
|
%% put the public functions here
|
||
|
methods
|
||
|
function T=TFCEobj(varargin) %constructor
|
||
|
%% TFCE Object for performing Threshold free cluster enhancement
|
||
|
%
|
||
|
% Example usage: T = TFCEobj('D', X, 'H' 0, 'E', 1, 'HMAX', 1);
|
||
|
%
|
||
|
% Input parameter:
|
||
|
% - D / data = 2-dimensional data matrix
|
||
|
% - H = Height parameter in the TFCE
|
||
|
% - E = Extent parameter in the TFCE
|
||
|
% - HMAX = Hmax parameter
|
||
|
for k=1:2:nargin;
|
||
|
if k+1<=nargin;
|
||
|
switch varargin{k}
|
||
|
case {'D','d','data','DATA'}
|
||
|
T.D=varargin{k+1};
|
||
|
T.InitTFCE;
|
||
|
case {'H','h'}
|
||
|
T.H=varargin{k+1};
|
||
|
case {'E','e'}
|
||
|
T.E=varargin{k+1};
|
||
|
case {'n','N','nstep','NSTEP'}
|
||
|
T.nstep=varargin{k+1};
|
||
|
case {'hmax','HMAX'}
|
||
|
T.hmax=varargin{k+1};
|
||
|
|
||
|
otherwise
|
||
|
error('invalid name-value pair');
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
function set.hmax(T,hmax)
|
||
|
if ~isnumeric(hmax);error('use a numeric value for hmax');end
|
||
|
T.hmax=hmax;
|
||
|
T.Check_hmax;
|
||
|
end
|
||
|
function set.D(T,D)
|
||
|
if size(D,2)<2||size(D,1)==0; error('don''t be silly, now I''ve nothing to do');end
|
||
|
if any(~isnumeric(D)); error('data is not a numerica matrix');end
|
||
|
T.D=D;
|
||
|
end
|
||
|
function varargout=Surrogate(T,storeflag,n)
|
||
|
% Create surrogate data.
|
||
|
% function call S=T.Surrogate(n)
|
||
|
% n: number of surrogates to create
|
||
|
% S is a 3D matrix of size(D) by n
|
||
|
|
||
|
%build surrogate timecourses using the DVV toolbox by Danilo P. Mandic
|
||
|
%http://www.commsp.ee.ic.ac.uk/~mandic/dvv.htm
|
||
|
if isempty(n);n=25;end
|
||
|
if ~isnumeric(n);error('invalid number of surrogates to create');end
|
||
|
if isempty(storeflag);storeflag=false;end
|
||
|
if nargout<1&&~storeflag;error('don''t be silly. Now I''ve nowhere to store my results');end
|
||
|
S=zeros([size(T.D),n]);
|
||
|
% loop over instances
|
||
|
h=waitbar(0,'generating surrogate data');
|
||
|
for k=1:size(T.D,1);
|
||
|
S(k,:,:)=surrogate(T.D(k,:),n);
|
||
|
waitbar(k./size(T.D,1),h);
|
||
|
end
|
||
|
close(h);
|
||
|
if storeflag;
|
||
|
T.S=S;
|
||
|
end
|
||
|
if nargout==1;varargout{1}=S;end
|
||
|
end
|
||
|
function varargout=SurrogateTFCE(T,storeflag,n)
|
||
|
if nargout<1&&~storeflag;error('don''t be silly. Now I''ve nowhere to store my results');end
|
||
|
if isempty(T.S);
|
||
|
S=T.Surrogate(false,n);
|
||
|
else
|
||
|
S=T.S;
|
||
|
end
|
||
|
STFCE=zeros(size(S));
|
||
|
hsteps=linspace(0,T.hmax,T.nstep);
|
||
|
|
||
|
for k=1:size(S,3); %loop over surrogate data
|
||
|
for v=1:size(S,1);%loop over instances
|
||
|
STFCE(v,:,k)=T.TFCECore(squeeze(S(v,:,k)),hsteps);
|
||
|
end
|
||
|
end
|
||
|
if storeflag;T.STFCE=STFCE;end
|
||
|
if nargout==1;varargout{1}=STFCE;end
|
||
|
end
|
||
|
function Pvalues(T,n)
|
||
|
if isempty(T.TFCE);error('calculate TFCE before running stats');end;
|
||
|
PosCount=zeros(size(T.TFCE));
|
||
|
NegCount=zeros(size(T.TFCE));
|
||
|
Count=zeros(size(T.TFCE));
|
||
|
if isempty(T.STFCE) && ~isempty(T.S)
|
||
|
T.SurrogateTFCE;
|
||
|
end
|
||
|
if ~isempty(T.STFCE);
|
||
|
n=size(T.STFCE,3);
|
||
|
for k=1:n;
|
||
|
PosCount=PosCount+squeeze(T.STFCE(:,:,k))>T.TFCE;
|
||
|
NegCount=NegCount+squeeze(T.STFCE(:,:,k))<T.TFCE;
|
||
|
end
|
||
|
else
|
||
|
for k=1:n; %count over number of permutations;
|
||
|
T.Surrogate(true,1);
|
||
|
T.SurrogateTFCE(true);
|
||
|
PosCount=PosCount+squeeze(T.STFCE(:,:))>T.TFCE;
|
||
|
NegCount=NegCount+squeeze(T.STFCE(:,:))<T.TFCE;
|
||
|
end
|
||
|
end
|
||
|
T.P=struct('Pos_Uncorr',PosCount./n,...
|
||
|
'Neg_Uncorr',NegCount./n);
|
||
|
end
|
||
|
end
|
||
|
%% put the private functions here. NB during testing these will still be public
|
||
|
methods
|
||
|
function InitTFCE(T)
|
||
|
T.TFCE=zeros(size(T.D));
|
||
|
end
|
||
|
function TFCECalc(T)
|
||
|
hsteps=linspace(0,T.hmax,T.nstep);
|
||
|
for v=1:size(T.D,1);%loop over instances
|
||
|
I=T.D(v,:);
|
||
|
if any(~isfinite(I));continue;end%if NaN go to next one.
|
||
|
T.TFCE(v,:)=T.TFCECore(I,hsteps);
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
methods
|
||
|
%below are the support methods for the TFCE object. They won't alter any fields within the object
|
||
|
function Check_hmax(T)
|
||
|
m=max(T.D(:));
|
||
|
if ~isempty(m)
|
||
|
if T.hmax<m; warning('maximum value for integration set below the maximum value in T.D'); end
|
||
|
end
|
||
|
end
|
||
|
function TFCEtmp=TFCECore(T,I,hsteps)
|
||
|
%this function will actually calculate the TFCE values.
|
||
|
%It supports the function TFCECalc.
|
||
|
TFCEtmp=zeros(size(I));
|
||
|
for h=hsteps;
|
||
|
%% positive part
|
||
|
[L,n]=bwlabel(I>h); % find beta > h and get clusters %all numbers belonging to cluster 1 get a 1, to cluster 2 a 2 etc.
|
||
|
if n==0;
|
||
|
else
|
||
|
ind=1:numel(L);
|
||
|
S=sparse(L(logical(L)),ind(logical(L)),1);
|
||
|
% a bit of a trick, but it seems to work :-)
|
||
|
E=sum(repmat(diag(S*transpose(S)),1,size(S,2)).*S); %#ok<PROP>
|
||
|
TFCEtmp(logical(E))=TFCEtmp(logical(E))+E(logical(E)).^T.E*h.^T.H; %#ok<PROP> % get tfce value by tfce=tfce_h(-1)+h^ch*e^ce per voxel
|
||
|
end
|
||
|
%% negative part
|
||
|
[L2,n2]=bwlabel(I<-h);
|
||
|
if n2==0;
|
||
|
else
|
||
|
ind=1:numel(L2);
|
||
|
S=sparse(L2(logical(L2)),ind(logical(L2)),1);
|
||
|
% a bit of a trick, but it seems to work :-)
|
||
|
E2=sum(repmat(diag(S*transpose(S)),1,size(S,2)).*S);
|
||
|
TFCEtmp(logical(E2))=TFCEtmp(logical(E2))-E2(logical(E2)).^T.E*h.^T.H; % get tfce value by tfce=tfce_h(-1)+h^ch*e^ce per voxel
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|