Created
June 11, 2014 10:08
-
-
Save swederik/e23c3726ce311fab0bf7 to your computer and use it in GitHub Desktop.
CONN functional connectivity toolbox ROI-to-voxel stats exporting on Mac OSX (conn_vproject.m)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function [dataplot,infoplot,data1plot]=conn_vproject(a,b,c,d,views,projection,thres,res,box,select,mat,threshold,data1plot,spmfile,voxeltovoxel) | |
%%%%% | |
% Slight modification to CONN functional connectivity toolbox to fix stats exporting on Mac OSX | |
% uicontextmenu appears broken on OSX. May be due to resolution issues on retina macbooks? | |
%%%%% | |
%CONN_VPROJECT Volume display | |
% | |
if numel(a)==1 && ishandle(a), % callbacks from UI objects | |
init=0; | |
GCF=gcf; | |
if isstruct(b), ARG=b; end; | |
OPTION=c; | |
if nargin>3, OPTION2=d; else OPTION2=''; end | |
if isempty(OPTION), return; end | |
DATA=get(GCF,'userdata'); | |
a=DATA.a; | |
b=DATA.b; | |
c=DATA.c; | |
d=DATA.d; | |
projection=DATA.projection; | |
thres=DATA.thres; | |
threshold=DATA.threshold; | |
res=DATA.res; | |
box=DATA.box; | |
views=DATA.views; | |
select=DATA.select; | |
mat=DATA.mat; | |
spmfile=DATA.spmfile; | |
if isfield(DATA,'voxeltovoxel'), voxeltovoxel=DATA.voxeltovoxel; else voxeltovoxel=0; end | |
data1plot=[]; | |
if isstruct(OPTION), | |
else, | |
switch(OPTION), | |
case 'buttondown', | |
xlim=get(DATA.axes,'xlim');ylim=get(DATA.axes,'ylim');xpos=get(DATA.axes,'currentpoint'); | |
if xpos(1,1)>=xlim(1)&&xpos(1,1)<=xlim(2)&&xpos(1,2)>=ylim(1)&&xpos(1,2)<=ylim(2), | |
DATA.buttondown=get(0,'pointerlocation'); | |
DATA.selectiontype=get(GCF,'selectiontype'); | |
set(GCF,'windowbuttonmotionfcn',{@conn_vproject,'buttonmotion'},'userdata',DATA); | |
res=DATA.res*3/2; | |
box=1; | |
else, DATA.buttondown=[]; set(GCF,'userdata',DATA); return; end | |
case 'buttonup', | |
p1=DATA.buttondown; | |
if ~isempty(p1), | |
p2=get(0,'pointerlocation')-p1; | |
if strcmp(DATA.selectiontype,'extend'), | |
ang=-.005*(p2(2)+p2(1));projection([1,2],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,2],:); | |
else, | |
%ang=.01*p2(2);projection([2,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([2,3],:); | |
ang=-.01*p2(1);projection([1,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,3],:); | |
end | |
DATA.projection=projection; | |
set(GCF,'windowbuttonmotionfcn',[],'userdata',DATA); | |
else, return; end | |
case 'buttonmotion', | |
p1=DATA.buttondown; | |
p2=get(0,'pointerlocation')-p1; | |
if strcmp(DATA.selectiontype,'extend'), | |
ang=-.005*(p2(2)+p2(1));projection([1,2],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,2],:); | |
else, | |
%ang=.01*p2(2);projection([2,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([2,3],:); | |
ang=-.01*p2(1);projection([1,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,3],:); | |
end | |
res=DATA.res*3/2; | |
box=1; | |
case 'resolution', | |
res=str2num(get(DATA.handles(2),'string')); | |
if isempty(res), res=DATA.res; end | |
set(DATA.handles(2),'string',num2str(res)); | |
DATA.res=res; | |
set(GCF,'userdata',DATA); | |
init=-1; | |
case 'threshold', | |
threshold=str2num(get(DATA.handles(4),'string')); | |
if isempty(threshold), threshold=DATA.threshold; end | |
set(DATA.handles(4),'string',num2str(threshold)); | |
DATA.threshold=threshold; | |
set(GCF,'userdata',DATA); | |
init=-1; | |
case 'keypress', | |
switch(lower(ARG.Character)), | |
case 'y', | |
DATA.rotation=DATA.rotation+[10,0,0]*(2*(length(ARG.Modifier)>0)-1); | |
case 'x', | |
DATA.rotation=DATA.rotation+[0,10,0]*(2*(length(ARG.Modifier)>0)-1); | |
case 'z', | |
DATA.rotation=DATA.rotation+[0,0,10]*(2*(length(ARG.Modifier)>0)-1); | |
otherwise, | |
return; | |
end | |
ang=-.01*DATA.rotation(1);projection([1,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,3],:); | |
ang=.01*DATA.rotation(2);projection([2,3],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([2,3],:); | |
ang=-.01*DATA.rotation(3);projection([1,2],:)=[cos(ang),sin(ang);-sin(ang),cos(ang)]*projection([1,2],:); | |
DATA.rotation=[0,0,0]; | |
DATA.projection=projection; | |
set(GCF,'windowbuttonmotionfcn',[],'userdata',DATA); | |
case 'selectroi' | |
selectcluster=get(DATA.handles(8),'value'); | |
if selectcluster>length(DATA.clusters), select=[]; else, select=DATA.clusters{selectcluster}; end | |
DATA.select=select; DATA.selectcluster=selectcluster; set(GCF,'userdata',DATA); | |
init=-2; | |
case 'vox-thr', | |
temp=str2num(get(DATA.handles(2),'string')); | |
if ~isempty(temp), thres{1}=temp; else, set(DATA.handles(2),'string',num2str(thres{1})); end | |
thres{2}=get(DATA.handles(3),'value'); | |
DATA.selectcluster=[]; | |
DATA.thres=thres;set(GCF,'userdata',DATA); | |
init=-1; | |
case 'clu-thr', | |
temp=str2num(get(DATA.handles(5),'string')); | |
if ~isempty(temp), thres{3}=temp; else, set(DATA.handles(5),'string',num2str(thres{3})); end | |
thres{4}=get(DATA.handles(6),'value'); | |
DATA.selectcluster=[]; | |
if thres{4}>4, set(DATA.handles(4),'string','peak threshold: peak p ='); | |
elseif thres{4}==1, set(DATA.handles(4),'string','cluster threshold: cluster k ='); | |
else set(DATA.handles(4),'string','cluster threshold: cluster p <'); | |
end | |
DATA.thres=thres;set(GCF,'userdata',DATA); | |
init=-1; | |
case 'export_mask', | |
if isempty(OPTION2) | |
[filename,filepath]=uiputfile('*.img;*.nii','Save mask as',fileparts(spmfile)); | |
else | |
[filepath,filename_name,filename_ext]=fileparts(OPTION2); | |
filename=[filename_name,filename_ext]; | |
end | |
if ischar(filename), | |
[nill,filename_name,filename_ext]=fileparts(filename); | |
if isempty(filename_ext), filename=[filename,'.img']; end | |
V=struct('mat',mat{1},'dim',size(b(:,:,:,1)),'dt',[spm_type('float32') spm_platform('bigend')],'fname',fullfile(filepath,filename)); | |
V=spm_write_vol(V,abs(d).*double(b(:,:,:,end)>0)); | |
fprintf('Mask file saved as %s\n',V.fname); | |
V=struct('mat',mat{1},'dim',size(b(:,:,:,1)),'pinfo',[1;0;0],'dt',[spm_type('uint32') spm_platform('bigend')],'fname',fullfile(filepath,[filename_name,'.ROIs.img'])); | |
btemp=zeros(size(b(:,:,:,1))); | |
for nbtemp=1:numel(DATA.clusters), btemp(DATA.clusters{nbtemp})=nbtemp; end | |
V=spm_write_vol(V,btemp); | |
fprintf('ROI file saved as %s\n',V.fname); | |
fh=fopen(fullfile(filepath,[filename_name,'.ROIs.txt']),'wt'); | |
for nbtemp=1:numel(DATA.clusters), | |
fprintf(fh,'%+d ',[DATA.xyzpeak{nbtemp},1]*DATA.mat{1}(1:3,:)'); | |
fprintf(fh,'\n'); | |
end | |
fclose(fh); | |
[peaks,peaks_idx,C]=conn_peaks({d,mat{1}}); | |
peaks_suprathreshold=b(peaks_idx+size(b,1)*size(b,2)*size(b,3))>0; | |
%peaks_F=d(peaks_idx); | |
%peaks_p=exp(-b(peaks_idx(peaks_suprathreshold))); | |
%dof=mat{3}; | |
save(fullfile(filepath,[filename_name,'.PEAKS.MAT']),'peaks','peaks_suprathreshold');%,'peaks_F','peaks_p','dof'); | |
%fprintf('Peaks file saved as %s\n',fullfile(filepath,[filename_name,'.PEAKS.MAT'])); | |
if ~isempty(C) | |
V=struct('mat',mat{1},'dim',size(C),'pinfo',[1;0;0],'dt',[spm_type('uint32') spm_platform('bigend')],'fname',fullfile(filepath,[filename_name,'.SEGs.img'])); | |
V=spm_write_vol(V,C); | |
fprintf('Segmentation file saved as %s\n',V.fname); | |
fh=fopen(fullfile(filepath,[filename_name,'.SEGs.txt']),'wt'); | |
for nbtemp=1:numel(peaks_idx), | |
fprintf(fh,'%+d ',peaks(nbtemp,:)); | |
fprintf(fh,'\n'); | |
end | |
fclose(fh); | |
end | |
end | |
return; | |
case 'export_list' | |
% Added function for export list button | |
% uicontextmenu on MacOSX seems not to fire | |
cbo = DATA.handles(8); | |
header = get(DATA.handles(7),'string'); | |
conn_exportlist(cbo,'',header); | |
return; | |
case 'surface_view' | |
filename=fullfile(fileparts(spmfile),'results.img'); | |
conn_vproject(gcf,[],'export_mask',filename); | |
conn_mesh_display(filename,''); | |
return; | |
case 'volume_view' | |
filename=fullfile(fileparts(spmfile),'results.img'); | |
conn_vproject(gcf,[],'export_mask',filename); | |
conn_mesh_display('',filename,[],[],[],.5); | |
return; | |
case 'spm_view' | |
[spmfile_path,spmfile_name]=fileparts(spmfile); | |
cwd=pwd;cd(spmfile_path); | |
load(spmfile,'SPM'); | |
spm defaults fmri; | |
[hReg,xSPM,SPM] = spm_results_ui('setup',SPM); | |
assignin('base','hReg',hReg); | |
assignin('base','xSPM',xSPM); | |
assignin('base','SPM',SPM); | |
figure(spm_figure('GetWin','Interactive')); | |
cd(cwd); | |
return; | |
case 'cluster_view' | |
filename=fullfile(fileparts(spmfile),'results.img'); | |
conn_vproject(gcf,[],'export_mask',filename); | |
[spmfile_path,spmfile_name]=fileparts(spmfile); | |
cwd=pwd;cd(spmfile_path); | |
filename=fullfile(fileparts(spmfile),'results.ROIs.img'); | |
conn_rex(spmfile,filename,'output_type','saverex','level','clusters','select_clusters',0,'steps',{'extract','results'},'s',[],'gui',1); | |
%roi_extract(spmfile,fullfile(filepath,filename),'output_type','text','select_clusters','each','steps',{'extract'}); | |
cd(cwd); | |
return; | |
case 'cluster_import', | |
filename=fullfile(fileparts(spmfile),'results.img'); | |
conn_vproject(gcf,[],'export_mask',filename); | |
[spmfile_path,spmfile_name]=fileparts(spmfile); | |
cwd=pwd;cd(spmfile_path); | |
filename=fullfile(fileparts(spmfile),'results.ROIs.img'); | |
htfig=msgbox('Loading connectivity values. Please wait',''); | |
[y,name]=conn_rex(spmfile,filename,'level','clusters'); | |
if ishandle(htfig), delete(htfig); end | |
name=regexprep(name,'^results\.ROIs\.','cluster '); | |
temp=load(DATA.spmfile,'SPM'); | |
if isfield(temp.SPM.xX,'SelectedSubjects')&&~rem(size(y,1),nnz(temp.SPM.xX.SelectedSubjects)) | |
ty=zeros(size(y,1)/nnz(temp.SPM.xX.SelectedSubjects)*numel(temp.SPM.xX.SelectedSubjects),size(y,2)); | |
ty(repmat(logical(temp.SPM.xX.SelectedSubjects),size(y,1)/nnz(temp.SPM.xX.SelectedSubjects),1),:)=y; | |
y=ty; | |
end | |
conn_importl2covariate(name,num2cell(y,1)); | |
cd(cwd); | |
return; | |
case 'connectome', | |
optionDistancePeaks=12; % minimum distance between extracted peaks (mm) | |
switch(DATA.side) | |
case 1, [peaks,peaks_idx]=conn_peaks({d,mat{1}},optionDistancePeaks); | |
case 2, [peaks,peaks_idx]=conn_peaks({-d,mat{1}},optionDistancePeaks); | |
case 3, [peaks,peaks_idx]=conn_peaks({abs(d),mat{1}},optionDistancePeaks); | |
end | |
if 0 % one peak per cluster | |
peaks_C=zeros(size(d)); | |
for n1=1:numel(DATA.clusters), peaks_C(DATA.clusters{n1})=n1; end | |
withinClusterPeak=zeros(numel(DATA.clusters)+1,1); | |
withinClusterPeak(1+peaks_C(flipud(peaks_idx)))=flipud(peaks_idx); | |
otherwithinClusterPeak=find(peaks_C(peaks_idx)>0&~ismember(peaks_idx,withinClusterPeak(2:end))); | |
peaks_idx(otherwithinClusterPeak)=[]; | |
peaks(otherwithinClusterPeak,:)=[]; | |
end | |
peaks_suprathreshold=b(peaks_idx+size(b,1)*size(b,2)*size(b,3))>0; | |
[spmfile_path,spmfile_name]=fileparts(spmfile); | |
save(fullfile(spmfile_path,'PEAKS.mat'),'peaks','peaks_suprathreshold'); | |
conn_process('extract_connectome',peaks(peaks_suprathreshold,:),[peaks(peaks_suprathreshold,:);peaks(~peaks_suprathreshold,:)],-1); | |
return | |
% ROI=conn_process('results_connectome',spmfile_path,-1); | |
% save(fullfile(spmfile_path,'ROI.mat'),'ROI'); | |
% conn_displayroi('initfile','results_roi',0,fullfile(spmfile_path,'ROI.mat')); | |
%conn_displayroi('initfile','results_connectome',0,spmfile_path,peaks_suprathreshold,fullfile(spmfile_path,'ROI.mat')); | |
%conn_displayroi('init','results_connectome',0,spmfile_path,peaks_suprathreshold); | |
case 'switch', | |
side=get(DATA.handles(11),'value'); | |
if side~=DATA.side, | |
switch(side), | |
case 1, b=c; | |
case 2, b=1-c; | |
case 3, b=2*min(c,1-c); | |
end | |
%b(b==0)=nan; | |
b=-log(max(eps,b)); | |
DATA.side=side; | |
%b=-log(1-exp(-DATA.b(:,:,:,1))); | |
%DATA.side=-DATA.side; | |
init=-1; | |
DATA.selectcluster=[]; | |
end | |
otherwise, | |
return | |
end | |
end | |
else, %called not from UI | |
init=1; | |
if nargin<11 || isempty(mat), mat={eye(4),numel(a)}; end | |
if nargin<10 || isempty(select), select=[]; end | |
if nargin<9 || isempty(box), box=0; end | |
if nargin<8 || isempty(res), res=1; end | |
if nargin<7 || isempty(thres), thres={.05,1,1,1}; end | |
if nargin<6 || isempty(projection), projection=[-1,0,0;0,0,-1;0,-1,0]; end; | |
%if nargin<3 || isempty(projection), projection=[-0.3529,0.9347,-0.0429;0.0247,-0.0365,-0.9990;-0.9353,-0.3537,-0.0103]; end | |
if nargin<5 || isempty(views), views='full'; end | |
if nargin<4, d=[]; end | |
if nargin<3, c=[]; end | |
if nargin<2, b=[]; end | |
if nargin<1 || isempty(a), a=spm_read_vols(spm_vol(fullfile(fileparts(which('spm')),'apriori','grey.nii'))); end | |
if nargin<12 || isempty(threshold), if isempty(b), threshold=[nanmean(a(:))]; else, threshold=[nanmean(a(:)),2]; end; end | |
if nargin<13 || isempty(data1plot), data1plot=[]; end | |
if nargin<14 || isempty(spmfile), spmfile=[]; end | |
if nargin<15 || isempty(voxeltovoxel), voxeltovoxel=0; end | |
GCF=gcf; | |
if ~strcmp(views,'none'), | |
a(:,:,[1,end],1)=0;a(:,[1,end],:,1)=0;a([1,end],:,:,1)=0; | |
clf; | |
DATA.a=a; | |
DATA.b=b; | |
DATA.c=c; | |
DATA.d=d; | |
DATA.projection=projection; | |
DATA.thres=thres; | |
DATA.threshold=threshold; | |
DATA.res=res; | |
DATA.box=box; | |
DATA.views=views; | |
DATA.rotation=[0,0,0]; | |
DATA.selectcluster=[]; | |
DATA.select=select; | |
DATA.mat=mat; | |
DATA.clusters={[]}; | |
DATA.side=1; | |
DATA.spmfile=spmfile; | |
DATA.voxeltovoxel=voxeltovoxel; | |
DATA.peakFDR=0; | |
end | |
end | |
if init>0, % initialize | |
%map=[gray(64).^2;.5*repmat([1,1,0],[64,1])+.5*((gray(64).^2)*diag([1,1,0]));.5*repmat([1,0,0],[64,1])+.5*((gray(64).^2)*diag([1,0,0]))]; | |
%map=[.5+.5*(gray(64).^2);.5*repmat([1,1,0],[64,1])+.5*((gray(64).^.5)*diag([1,1,0]));.5*repmat([0,0,1],[64,1])+.5*((gray(64).^.5)*diag([0,0,1]))];map(1,:)=1; | |
map=[.25+.75*(gray(64).^2)*diag([1,1,1]);0*repmat([1,1,1],[64,1])+1*((gray(64).^1)*diag([1,0,0]));.25*repmat([1,1,0],[64,1])+.75*((gray(64).^.5)*diag([1,1,0]))];map(1,:)=.25; | |
switch(views), | |
case 'full', | |
clf; | |
if isempty(b), | |
DATA.handles=[uicontrol('style','text','units','norm','position',[.6,.95,.1,.05],'string','resolution','backgroundcolor','w','foregroundcolor','b'),... | |
uicontrol('style','edit','units','norm','position',[.7,.95,.1,.05],'string',num2str(DATA.res),'callback',{@conn_vproject,'resolution'},'backgroundcolor','w','foregroundcolor','k'),... | |
uicontrol('style','text','units','norm','position',[.8,.95,.1,.05],'string','threshold','backgroundcolor','w','foregroundcolor','b'),... | |
uicontrol('style','edit','units','norm','position',[.9,.95,.1,.05],'string',num2str(DATA.threshold),'callback',{@conn_vproject,'threshold'},'backgroundcolor','w','foregroundcolor','b')]; | |
DATA.axes=subplot(122); set(DATA.axes,'units','norm','position',[.55,.1,.4,.8],'visible','off'); | |
set(GCF,'name','Volume display','numbertitle','off','color','w','units','norm','position',[.1,.5,.8,.4],'interruptible','off','busyaction','cancel','windowbuttondownfcn',{@conn_vproject,'buttondown'},'windowbuttonupfcn',{@conn_vproject,'buttonup'},'windowbuttonmotionfcn',[],'keypressfcn',{@conn_vproject,'keypress'},'colormap',map,'userdata',DATA); | |
else | |
uicontrol('style','frame','units','norm','position',[.39,.87,.45,.11],'backgroundcolor',.9*[1,1,1]); | |
DATA.handles=[... | |
uicontrol('style','text','units','norm','position',[.40,.92,.15,.04],'string','height thr: voxel p <','fontname','arial','fontsize',8,'foregroundcolor','k','backgroundcolor',.9*[1,1,1]),... | |
uicontrol('style','edit','units','norm','position',[.55,.93,.05,.03],'string',num2str(thres{1}),'fontname','arial','fontsize',8,'callback',{@conn_vproject,'vox-thr'},'tooltipstring','Height-threshold value: False-positive threshold value for each voxel'),... | |
uicontrol('style','popupmenu','units','norm','position',[.625,.935,.1,.03],'string',{'p-uncorrected','p-FDR corrected'},'fontname','arial','fontsize',8,'callback',{@conn_vproject,'vox-thr'},'value',thres{2},'tooltipstring','False-positive control type for individual voxels'),... | |
uicontrol('style','text','units','norm','position',[.4,.88,.15,.04],'string','cluster thr: cluster p <','fontname','arial','fontsize',8,'foregroundcolor','k','backgroundcolor',.9*[1,1,1]),... | |
uicontrol('style','edit','units','norm','position',[.55,.89,.05,.03],'string',num2str(thres{3}),'fontname','arial','fontsize',8,'callback',{@conn_vproject,'clu-thr'},'tooltipstring','Extent threshold value: False-positive threshold value for individual clusters (based on cluster size)'),... | |
uicontrol('style','popupmenu','units','norm','position',[.625,.895,.1,.03],'string',{'cluster k-value','cluster p-FWE corrected','cluster p-FDR corrected','cluster p-uncorrected','peak p-FWE corrected','peak p-FDR corrected','peak p-uncorrected'},'fontname','arial','fontsize',8,'callback',{@conn_vproject,'clu-thr'},'value',thres{4},'tooltipstring','False-positive control type for individual clusters'),... | |
uicontrol('style','text','units','norm','position',[.05,.40,.925,.025],'string',sprintf('%18s%15s%15s%15s%15s%15s%15s%15s','Clusters (x,y,z)','k','cluster p-FWE','cluster p-FDR','cluster p-unc','peak p-FWE','peak p-FDR','peak p-unc'),'fontname','arial','fontsize',8,'backgroundcolor','w','foregroundcolor','b','horizontalalignment','left','fontname','monospaced','fontsize',8),... | |
uicontrol('style','listbox','units','norm','position',[.05,.06,.925,.34],'string','','backgroundcolor','w','foregroundcolor','k','horizontalalignment','left','fontname','monospaced','fontsize',8,'callback',{@conn_vproject,'selectroi'}),... | |
uicontrol('style','pushbutton','units','norm','position',[.875,.885,.1,.04],'string','Surface display','fontname','arial','fontsize',8,'callback',{@conn_vproject,'surface_view'},'tooltipstring','Displays results projected to cortical surface'),... | |
0,... | |
uicontrol('style','popupmenu','units','norm','position',[.875,.945,.1,.03],'string',{'positive contrast','negative contrast','two-sided'},'fontname','arial','fontsize',8,'callback',{@conn_vproject,'switch'},'tooltipstring','Analysis results directionality'),... | |
uicontrol('style','listbox','units','norm','position',[.62,.45,.355,.28],'string','','fontname','arial','fontsize',9,'visible','off','backgroundcolor','w','foregroundcolor','k','horizontalalignment','left','max',2),... | |
uicontrol('style','text','units','norm','position',[.725,.92,.1,.04],'string','','fontname','arial','fontsize',8,'horizontalalignment','right','foregroundcolor','k','backgroundcolor',.9*[1,1,1]),... | |
uicontrol('style','text','units','norm','position',[.725,.88,.1,.04],'string','','fontname','arial','fontsize',8,'horizontalalignment','right','foregroundcolor','k','backgroundcolor',.9*[1,1,1]),... | |
uicontrol('style','pushbutton','units','norm','position',[.875,.02,.1,.04],'string','Explore clusters','fontname','arial','fontsize',8,'callback',{@conn_vproject,'cluster_view'},'tooltipstring','Explores results within each significant cluster (using REX)'),... | |
uicontrol('style','pushbutton','units','norm','position',[.875,.765,.1,.04],'string','Export mask','fontname','arial','fontsize',8,'callback',{@conn_vproject,'export_mask'},'tooltipstring','Exports mask of supra-threshold voxels'),... | |
uicontrol('style','pushbutton','units','norm','position',[.875,.845,.1,.04],'string','Volume display','fontname','arial','fontsize',8,'callback',{@conn_vproject,'volume_view'},'tooltipstring','Displays results on 3d brain'),... | |
uicontrol('style','pushbutton','units','norm','position',[.775,.02,.1,.04],'string','Import values','fontname','arial','fontsize',8,'callback',{@conn_vproject,'cluster_import'},'tooltipstring','Imports average cluster connectivity values for each subject into CONN toolbox as second-level covariates')]; | |
uicontrol('style','pushbutton','units','norm','position',[.875,.805,.1,.04],'string','SPM display','fontname','arial','fontsize',8,'callback',{@conn_vproject,'spm_view'},'tooltipstring','Displays results in SPM'),... | |
%uicontrol('style','pushbutton','units','norm','position',[.875,.845,.1,.04],'string','export stats','fontname','arial','fontsize',12,'callback',{@conn_vproject,'export_stats'}),... | |
% This sets up the export button | |
uicontrol('style','pushbutton','units','norm','position',[.875,.705,.1,.04],'string','Export list','fontname','arial','fontsize',12,'callback',{@conn_vproject,'export_list'}),... %%% LIZETTE ADDED THIS LINE!! | |
%uicontrol('style','text','units','norm','position',[.2,.30,.1,.025],'string','k','backgroundcolor','k','foregroundcolor','y','horizontalalignment','left'),... | |
%uicontrol('style','text','units','norm','position',[.3,.30,.1,.025],'string','voxel p-unc','backgroundcolor','k','foregroundcolor','y','horizontalalignment','left'),... | |
%uicontrol('style','text','units','norm','position',[.4,.30,.1,.025],'string','voxel p-cor','backgroundcolor','k','foregroundcolor','y','horizontalalignment','left'),... | |
%uicontrol('style','listbox','units','norm','position',[.2,.05,.1,.25],'string','','backgroundcolor','k','foregroundcolor','w','horizontalalignment','left'),... | |
%uicontrol('style','listbox','units','norm','position',[.3,.05,.1,.25],'string','','backgroundcolor','k','foregroundcolor','w','horizontalalignment','left'),... | |
%uicontrol('style','listbox','units','norm','position',[.4,.05,.1,.25],'string','','backgroundcolor','k','foregroundcolor','w','horizontalalignment','left')]; | |
if DATA.mat{6}~='T', set(DATA.handles(11),'value',3,'enable','off'); end; | |
if ~isfield(DATA,'peakFDR')||~DATA.peakFDR, | |
set(DATA.handles(6),'string',{'cluster k-value','cluster p-FWE corrected','cluster p-FDR corrected','cluster p-uncorrected','peak p-FWE corrected','peak p-uncorrected'}); | |
set(DATA.handles(7),'string',sprintf('%18s%15s%15s%15s%15s%15s%15s','Clusters (x,y,z)','k','cluster p-FWE','cluster p-FDR','cluster p-unc','peak p-FWE','peak p-unc')); | |
end | |
hc1=uicontextmenu; | |
uimenu(hc1,'Label','Export table','callback',@(varargin)conn_exportlist(DATA.handles(8),'',get(DATA.handles(7),'string'))); | |
set(DATA.handles(8),'uicontextmenu',hc1); | |
hc1=uicontextmenu; | |
uimenu(hc1,'Label','Export table','callback',@(varargin)conn_exportlist(DATA.handles(12))); | |
set(DATA.handles(12),'uicontextmenu',hc1); | |
%uicontrol('style','pushbutton','units','norm','position',[.775,.02,.1,.04],'string','Export table','fontname','arial','fontsize',8,'callback',@(varargin)conn_exportlist(DATA.handles(12)),'tooltipstring','Exports table'),... | |
%hc1=uicontextmenu; | |
%uimenu(hc1,'Label','Export stats','callback',{@conn_vproject,'export_stats'}); | |
%set(DATA.handles(8),'uicontextmenu',hc1); | |
if voxeltovoxel | |
DATA.handles(10)=uicontrol('style','pushbutton','units','norm','position',[.875,.845,.1,.04],'string','post-hoc peak analyses','fontname','arial','fontsize',8,'callback',{@conn_vproject,'connectome'}); | |
end | |
%if DATA.mat{6}~='T'||isempty(DATA.mat{2}), %enable Fcluster% | |
% delete(DATA.handles(6)); DATA.handles(6)=uicontrol('style','popupmenu','units','norm','position',[.625,.895,.1,.03],'string',{'peak p-FDR corrected','extent k-value'},'fontname','arial','fontsize',8,'callback',{@conn_vproject,'clu-thr'},'value',min(2,thres{4})); | |
%end | |
%if isempty(DATA.mat{2}), set(DATA.handles(6),'visible','off','value',4); DATA.thres{4}=4; DATA.thres{3}=10; thres=DATA.thres; set(DATA.handles(5),'string',num2str(thres{3})); set(DATA.handles(4),'string','extent threshold: cluster k ='); end | |
DATA.axes=subplot(222);set(DATA.axes,'units','norm','position',[.40,.45,.2,.38],'visible','off');%[.55,.35,.4,.6],'visible','off'); | |
h0=get(0,'screensize'); | |
set(GCF,'name',['Volume display ',DATA.spmfile],'numbertitle','off','color','w','units','pixels','position',[2,h0(4)-min(540,.7*h0(3))-48,h0(3)-2,min(540,.7*h0(3))],'interruptible','off','busyaction','cancel','windowbuttondownfcn',{@conn_vproject,'buttondown'},'windowbuttonupfcn',{@conn_vproject,'buttonup'},'windowbuttonmotionfcn',[],'keypressfcn',{@conn_vproject,'keypress'},'colormap',map,'userdata',DATA); | |
end | |
case '3d', | |
clf; | |
DATA.handles=[uicontrol('style','text','units','norm','position',[0,0,.1,.05],'string','resolution','backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','edit','units','norm','position',[.1,0,.1,.05],'string',num2str(DATA.res),'callback',{@conn_vproject,'resolution'},'backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','text','units','norm','position',[.2,0,.1,.05],'string','threshold','backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','edit','units','norm','position',[.3,0,.1,.05],'string',num2str(DATA.threshold),'callback',{@conn_vproject,'threshold'},'backgroundcolor','k','foregroundcolor','w')]; | |
DATA.axes=gca;set(DATA.axes,'visible','off'); | |
set(GCF,'name','Volume display','numbertitle','off','color','w','interruptible','off','busyaction','cancel','windowbuttondownfcn',{@conn_vproject,'buttondown'},'windowbuttonupfcn',{@conn_vproject,'buttonup'},'windowbuttonmotionfcn',[],'keypressfcn',{@conn_vproject,'keypress'},'colormap',map,'userdata',DATA); | |
case 'orth', | |
clf; | |
DATA.handles=[uicontrol('style','text','units','norm','position',[0,0,.1,.05],'string','resolution','backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','edit','units','norm','position',[.1,0,.1,.05],'string',num2str(DATA.res),'callback',{@conn_vproject,'resolution'},'backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','text','units','norm','position',[.2,0,.1,.05],'string','threshold','backgroundcolor','k','foregroundcolor','w'),... | |
uicontrol('style','edit','units','norm','position',[.3,0,.1,.05],'string',num2str(DATA.threshold),'callback',{@conn_vproject,'threshold'},'backgroundcolor','k','foregroundcolor','w')]; | |
DATA.axes=gca;set(DATA.axes,'visible','off'); | |
%DATA.axes=gca; | |
set(GCF,'color','w','windowbuttondownfcn',[],'windowbuttonupfcn',[],'windowbuttonmotionfcn',[],'keypressfcn',[],'colormap',map,'userdata',DATA); | |
case 'none', | |
if ~nargout, DATA.axes=gca;set(DATA.axes,'visible','off'); end | |
%DATA.axes=gca; | |
%set(GCF,'color','w','userdata',DATA); | |
end | |
end | |
% display | |
if strcmp(views,'full'), | |
if init~=0, % redraws orth views | |
if ~isempty(b),%length(threshold)>1, | |
if isempty(DATA.clusters)||init~=-2, % compute/display stats | |
bnew=b(:,:,:,1);bnew(~a)=nan;%bnew(a<=threshold(1))=nan; | |
[bnew,txt,xyzpeak,clusters,clusternames,ithres]=vproject_display(bnew,threshold,thres,mat,DATA.side,DATA.d,DATA.peakFDR); | |
b(:,:,:,2)=bnew; threshold(3)=0;%.5; | |
%for n1=1:4, set(DATA.handles(8+n1),'string',strvcat(txt{n1})); end | |
set(DATA.handles(8),'string',strvcat(txt,' '),'value',max(1,min(size(txt,1)+1,get(DATA.handles(8),'value')))); | |
DATA.stdprojections=cell(1,4); | |
DATA.txt=txt; | |
DATA.clusternames=clusternames; | |
DATA.ithres=ithres; | |
else | |
clusters=DATA.clusters; | |
xyzpeak=DATA.xyzpeak; | |
clusternames=DATA.clusternames; | |
end | |
if isfield(DATA,'selectcluster'), selectcluster=DATA.selectcluster;else, selectcluster=get(DATA.handles(8),'value'); end | |
if selectcluster<=length(clusters), select=clusters{selectcluster}; clusternames=clusternames{selectcluster}.txt; | |
elseif (isempty(selectcluster)||selectcluster==length(clusters)+1)&&~isempty(clusternames), select=[]; clusternames=clusternames{length(clusters)+1}.txt; | |
else, select=[]; clusternames=[]; end | |
end | |
%M={[-1,0,0;0,0,-1;0,-1,0],[0,-1,0;0,0,-1;-1,0,0],[-1,0,0;0,1,0;0,0,1]}; | |
M={[1,0,0;0,0,-1;0,1,0],[0,-1,0;0,0,-1;1,0,0],[1,0,0;0,-1,0;0,0,-1]}; | |
set(GCF,'pointer','watch'); drawnow | |
if ~isfield(DATA,'stdprojections') || init==-1, DATA.stdprojections=cell(1,4); end | |
tplot={};infoplot={};for n1=1:3, [tplot{n1},infoplot{n1},DATA.stdprojections{n1}]=conn_vproject(a,b,c,d,'none',M{n1},thres,res,0,select,mat,threshold,DATA.stdprojections{n1}); end; | |
%tplot=[tplot{1},tplot{2};tplot{3},ones(size(tplot{3},1),size(tplot{2},2))]; | |
tplot=cat(1,cat(2,tplot{1},tplot{2}),cat(2,tplot{3},tplot{1}(1)*ones([size(tplot{3},1),size(tplot{2},2),size(tplot{2},3)]))); | |
if ~isempty(b), h=subplot(3,4,1); set(h,'units','norm','position',[.05,.45,.3,.5]); else, h=subplot(3,4,1); set(h,'units','norm','position',[.05,.1,.4,.8]);end | |
%pres=.5;image(1:pres:size(tplot,2),1:pres:size(tplot,1),round(max((ceil(tplot(1:pres:end,1:pres:end)/64)-1)*64+1,convn(convn(tplot(1:pres:end,1:pres:end),conn_hanning(7)/4,'same'),conn_hanning(7)'/4,'same'))));axis equal; axis off; | |
pres=.25; | |
conf=conn_hanning(2/pres+1);conf=conf/sum(conf); | |
temp=convn(convn(tplot(round(1:pres:end),round(1:pres:end),:),conf,'same'),conf','same'); | |
image(1:pres:size(tplot,2),1:pres:size(tplot,1),temp);axis equal; axis off; | |
%image(round(convn(convn(tplot(round(1:.5:end),round(1:.5:end),:),conn_hanning(3)/2,'same'),conn_hanning(3)'/2,'same')));axis equal; axis off; | |
%image(tplot);axis equal; axis off; | |
data1plot=DATA.stdprojections{4}; | |
if ~isempty(clusternames),set(DATA.handles(12),'string',clusternames,'value',1,'visible','on');else, set(DATA.handles(12),'string','','value',1,'visible','off');end | |
if numel(DATA.mat{3})>1, set(DATA.handles(13),'string',[DATA.mat{6},'(',num2str(DATA.mat{3}(1)),',',num2str(DATA.mat{3}(2)),')','_min = ',num2str(DATA.ithres(1),'%0.2f')]); | |
else set(DATA.handles(13),'string',[DATA.mat{6},'(',num2str(DATA.mat{3}),')','_min = ',num2str(DATA.ithres(1),'%0.2f')]); | |
end | |
set(DATA.handles(14),'string',['k_min =',num2str(DATA.ithres(2))]); | |
if ~isempty(b), | |
DATA.b=b;DATA.threshold=threshold;DATA.xyzpeak=xyzpeak;DATA.infoplot=infoplot;DATA.select=select;DATA.clusters=clusters; | |
%set(GCF,'userdata',DATA); | |
end | |
end | |
%subplot(122);conn_vproject(a,'none',projection,threshold,res,box); | |
%if ~isempty(b), DATA.axes=subplot(222); else, DATA.axes=subplot(122); end | |
set(DATA.axes,'visible','off'); | |
%views='none'; | |
set(GCF,'pointer','arrow');%,'userdata',DATA); | |
end | |
if strcmp(views,'orth'), | |
%M={[-1,0,0;0,0,-1;0,-1,0],[0,-1,0;0,0,-1;-1,0,0],[-1,0,0;0,1,0;0,0,1]}; | |
M={[1,0,0;0,0,-1;0,1,0],[0,1,0;0,0,-1;1,0,0],[1,0,0;0,1,0;0,0,-1]}; | |
set(GCF,'pointer','watch'); drawnow | |
for n1=1:3, subplot(2,2,n1);conn_vproject(a,b,c,d,'none',M{n1},threshold,res,box); end; | |
set(GCF,'pointer','arrow'); | |
else, | |
if ~nargout, set(GCF,'pointer','watch'); drawnow; end | |
% volume plot | |
[dataplot,idx,mask,B,b2,res,data1plot]=vproject_view(a,b,c,projection,threshold,res,select,data1plot); | |
%if size(dataplot,3)>1, dataplot=dataplot(:,:,1)+dataplot(:,:,2); end | |
infoplot=struct('boundingbox',b2,'res',res,'size',[size(dataplot,1),size(dataplot,2)],'projection',projection); | |
if ~nargout, | |
axes(DATA.axes); | |
%image(dataplot);axis equal;axis off; | |
pres=.25;conf=conn_hanning(2/pres+1);conf=conf/sum(conf); image(1:pres:size(dataplot,2),1:pres:size(dataplot,1),convn(convn(dataplot(round(1:pres:end),round(1:pres:end),:),conf,'same'),conf','same'));axis equal; axis off; | |
%pres=.5;image(1:pres:size(dataplot,2),1:pres:size(dataplot,1),round(max((ceil(dataplot(1:pres:end,1:pres:end)/64)-1)*64+1,convn(convn(dataplot(1:pres:end,1:pres:end),conn_hanning(5)/3,'same'),conn_hanning(5)'/3,'same'))));axis equal; axis off; | |
DATA.axes=gca; | |
DATA.infoplot{4}=infoplot;DATA.stdprojections{4}=data1plot; set(GCF,'userdata',DATA); | |
% bounding box | |
if box, | |
B3=B'*pinv(projection); | |
B3=[1+(B3(:,1)-b2(1,1))/res, 1+(B3(:,2)-b2(1,2))/res, 1+(B3(:,3)-b2(1,3))/res]; | |
border={[1,3,7,5,1],[2,6,4,8,2],[1,3,2,8,1],[7,5,4,6,7]}; | |
[minBt3]=max(B3(:,3)); | |
for n0=1:length(border), | |
for n1=1:length(border{n0})-1, | |
color=(B3(border{n0}(n1),3)==minBt3|B3(border{n0}(n1+1),3)==minBt3); | |
Bt1=linspace(B3(border{n0}(n1),1),B3(border{n0}(n1+1),1),100); | |
Bt2=linspace(B3(border{n0}(n1),2),B3(border{n0}(n1+1),2),100); | |
Bt3=linspace(B3(border{n0}(n1),3),B3(border{n0}(n1+1),3),100); | |
if color, | |
Bt1(Bt3>idx(max(1,min(prod(size(mask)), round(Bt2)+size(idx,1)*round(Bt1-1)))) & ... | |
mask(max(1,min(prod(size(mask)), round(Bt2)+size(idx,1)*round(Bt1-1)))) )=nan; | |
end | |
hold on; h=plot(Bt1,Bt2,'-'); set(h,'color',.25*[0,0,1],'linewidth',4-3*color);hold off; | |
end | |
end | |
end | |
set(GCF,'pointer','arrow'); | |
end | |
end | |
end | |
function [dataplot,idx,mask,B,b2,res,data1plot]=vproject_view(a,b,c,projection,threshold,res,select,data1plot); | |
%interpolate&project | |
if ~isempty(data1plot), | |
mask=data1plot.mask; | |
idx=data1plot.idx; | |
trans=data1plot.trans; | |
B=data1plot.B; | |
b2=data1plot.b2; | |
else, | |
if ~isempty(b), a=a+j*b(:,:,:,end); end | |
[x1,y1,z1]=meshgrid((1:size(a,2))-(size(a,2)+1)/2,(1:size(a,1))-(size(a,1)+1)/2,(1:size(a,3))-(size(a,3)+1)/2); | |
bb={[1,size(a,2)]-(size(a,2)+1)/2,[1,size(a,1)]-(size(a,2)+1)/2,[1,size(a,3)]-(size(a,3)+1)/2}; | |
B=[];for n1=1:8,B=[B,[bb{1}(1+rem(n1,2));bb{2}(1+rem(floor(n1/2),2));bb{3}(1+rem(floor(n1/4),2))]]; end | |
B2=B'*pinv(projection); | |
b2=[min(B2,[],1);max(B2,[],1)]; | |
%res=res*((prod(b2(2,:)-b2(1,:))./prod(size(a))).^(1/3)); | |
if 1,%faster&avoids memory problems | |
nz2=b2(1,3):res:b2(2,3); | |
[x2,y2]=meshgrid(b2(1,1):res:b2(2,1),b2(1,2):res:b2(2,2)); | |
N=numel(x2); | |
d2=[x2(:),y2(:)]*projection(1:2,:); | |
d2=d2-repmat([bb{2}(1),bb{1}(1),bb{3}(1)],[N,1]); | |
d2=reshape(d2,[size(x2),3]); | |
trans=zeros(size(x2)); | |
idx=zeros([size(x2),1+(length(threshold)>1)]); | |
idx1=1:N;idx2=[]; | |
for n1=1:length(nz2), | |
x3=round(d2(idx1)+nz2(n1)*projection(3,1)); | |
y3=round(d2(idx1+N)+nz2(n1)*projection(3,2)); | |
z3=round(d2(idx1+N*2)+nz2(n1)*projection(3,3)); | |
%a3=interp3(x1,y1,z1,a,x3,y3,z3,'nearest'); | |
%idxs=max(1,min(size(a,1), 1+round(y3-bb{2}(1)) )) + size(a,1)*max(0,min(size(a,2)-1, round(x3-bb{1}(1)) )) + size(a,1)*size(a,2)*max(0,min(size(a,3)-1, round(z3-bb{3}(1)) )); | |
idxs=max(1,min(size(a,1), 1+y3 )) + size(a,1)*max(0,min(size(a,2)-1, x3 )) + size(a,1)*size(a,2)*max(0,min(size(a,3)-1, z3 )); | |
a3=a(idxs); | |
idx0=real(a3)>threshold(1)|imag(a3)>threshold(end); | |
idx(idx1(idx0))=(length(nz2)+1-n1)/length(nz2); | |
idx2=[idx2,idx1(idx0)]; | |
idx1=idx1(~idx0); | |
if length(threshold)>1, | |
x3=d2(idx2)+nz2(n1)*projection(3,1); | |
y3=d2(idx2+N)+nz2(n1)*projection(3,2); | |
z3=d2(idx2+N*2)+nz2(n1)*projection(3,3); | |
%a3=interp3(x1,y1,z1,a,x3,y3,z3,'nearest'); | |
%idxt=max(1,min(size(a,1), 1+round(y3-bb{2}(1)) )) + size(a,1)*max(0,min(size(a,2)-1, round(x3-bb{1}(1)) )) + size(a,1)*size(a,2)*max(0,min(size(a,3)-1, round(z3-bb{3}(1)) )); | |
idxt=max(1,min(size(a,1), 1+round(y3) )) + size(a,1)*max(0,min(size(a,2)-1, round(x3) )) + size(a,1)*size(a,2)*max(0,min(size(a,3)-1, round(z3) )); | |
a3=a(idxt); | |
if 0, | |
idx00=find(imag(a3)>threshold(end)); | |
idx(N+idx2(idx00))=max(idx(N+idx2(idx00)),imag(a3(idx00))); %n1; | |
idxtrans=find(trans(idx2(idx00))==0); | |
trans(idx2(idx00(idxtrans)))=idxt(idx00(idxtrans)); | |
else, | |
idx00=find(imag(a3)>threshold(end)); | |
idxtrans=find(~idx(N+idx2(idx00)));%idxtrans=find(imag(a3(idx00))>=idx(N+idx2(idx00))); | |
idx(N+idx2(idx00(idxtrans)))=(length(nz2)+1-n1)/length(nz2);%imag(a3(idx00(idxtrans))); | |
trans(idx2(idx00(idxtrans)))=idxt(idx00(idxtrans)); | |
end | |
%idx2=idx2(~idx00); | |
end | |
end | |
mask=(idx>0); | |
%if any(any(mask(:,:,1)>0)), idx(~mask(:,:,1))=5*max(idx(mask(:,:,1)>0)); else, idx(~mask(:,:,1))=length(nz2); end | |
else, | |
[x2,y2,z2]=meshgrid(b2(1,1):res:b2(2,1),b2(1,2):res:b2(2,2),b2(1,3):res:b2(2,3)); | |
d=[x2(:),y2(:),z2(:)]*projection; | |
x2=reshape(d(:,1),size(x2)); | |
y2=reshape(d(:,2),size(y2)); | |
z2=reshape(d(:,3),size(z2)); | |
%a2=interp3(x1,y1,z1,a,x2,y2,z2,'nearest'); | |
a2=a(max(1,min(size(a,1), 1+round(y2-bb{2}(1)) )) + size(a,1)*max(0,min(size(a,2)-1, round(x2-bb{1}(1)) )) + size(a,1)*size(a,2)*max(0,min(size(a,3)-1, round(z2-bb{3}(1)) ))); | |
[mask,idx]=max(a2>threshold,[],3);idx(~mask)=max(idx(mask>0)); | |
end | |
data1plot.mask=mask; | |
data1plot.idx=idx; | |
data1plot.trans=trans; | |
data1plot.B=B; | |
data1plot.b2=b2; | |
end | |
conf1=conn_hanning(3)/2;conf1=conf1/sum(conf1); | |
conf2=conn_hanning(3)/2;conf2=conf2/sum(conf2); | |
if size(idx,3)==1, dataplot=-idx; dataplot=1+63*(dataplot-min(dataplot(:)))/(max(dataplot(:))-min(dataplot(:))); | |
else, | |
%dataplot1=-idx(:,:,1); dataplot1=1+63*(dataplot1-min(dataplot1(:)))/(max(dataplot1(:))-min(dataplot1(:))); | |
%conjmask=mask(:,:,1)&mask(:,:,2); | |
%dataplot2=-idx(:,:,2); dataplot2=1+63*(dataplot2-min(dataplot2(:)))/(max(dataplot2(:))-min(dataplot2(:))); | |
%dataplot=dataplot1; dataplot(conjmask)=64+dataplot2(conjmask); | |
if 1, | |
dataplot1=idx(:,:,1); | |
dataplot2=idx(:,:,2); | |
%dataplot1=convn(convn(dataplot1,conf1,'same'),conf1','same'); | |
%dataplot2=convn(convn(dataplot2,conf2,'same'),conf2','same'); | |
k=.75;%.2; | |
dataplotA=(dataplot2==0).*(k+(1-k)*dataplot1.^4) + (dataplot2>0).*(k+(1-k)*dataplot1.^4); | |
dataplotA(dataplot1==0)=1; | |
dataplotB=(dataplot2==0).*dataplotA + (dataplot2>0).*(dataplotA.*max(0,min(.75,tanh(1.5*(1*dataplot1-dataplot2))))); | |
%dataplotB=(dataplot2==0).*dataplotA + (dataplot2>0).*(.25*dataplotA.*(dataplot2<=.9*dataplot1)); | |
%dataplotB=(dataplot2==0).*dataplotA + (dataplot2>0).*(0*(dataplot2>.95*dataplot1) + .5*dataplotA.*(dataplot2<=.95*dataplot1)); | |
dataplot=cat(3,dataplotA,dataplotB,dataplotB); | |
else, | |
dataplot1=idx(:,:,1); | |
dataplot1=0+1*(dataplot1-min(dataplot1(~isinf(dataplot1))))/(max(dataplot1(~isinf(dataplot1)))-min(dataplot1(~isinf(dataplot1)))); | |
dataplot2=idx(:,:,2); if any(dataplot2(:)>0),mindataplot=.95*min(dataplot2(dataplot2>0));else,mindataplot=0;end; | |
%dataplot2=dataplot2>mindataplot; | |
dataplot2=max(0,dataplot2-mindataplot); | |
dataplot2=convn(convn(dataplot2,conf1,'same'),conf1','same'); | |
dataplot2=0+1*dataplot2/max(eps,max(dataplot2(:))); | |
%dataplot1=max(prctile(dataplot1(dataplot1<max(dataplot1(:))),5),dataplot1);dataplot2=max(0,dataplot1-dataplot2); | |
%dataplot1=.75+.25*(dataplot1).^2;dataplot2=max(0,dataplot1-dataplot2); | |
dataplot1=convn(convn(max(0,min(1,dataplot1)),conf2,'same'),conf2','same'); | |
dataplot1=0+1*(dataplot1).^4; | |
%dataplotA=max(0,min(1, dataplot1+.25*(dataplot2>0)));dataplotB=max(0,min(1, dataplot1-dataplot2+.0*(dataplot2>0))); | |
dataplotA=max(0,min(1, dataplot1.*(dataplot2==0)+(.25+dataplot1).*(dataplot2>0))); | |
dataplotB=max(0,min(1, dataplot1.*(dataplot2==0)+(.25+dataplot1).*(.5-.5*dataplot2).*(dataplot2>0))); | |
dataplot=cat(3,dataplotA,dataplotB,dataplotB); | |
%idxback=find(all(dataplot<.1,3)); dataplot(idxback)=1;dataplot(idxback+size(dataplot,1)*size(dataplot,2))=1;dataplot(idxback+2*size(dataplot,1)*size(dataplot,2))=1; | |
%dataplot=cat(3,dataplot1,dataplot2,dataplot2); | |
end | |
end | |
if ~isempty(select), | |
[transa,transb,transc]=unique(trans(:));%trans=a(c); | |
[nill,idxp]=intersect(transa(:),select(:)); | |
d=logical(zeros(size(transa)));d(idxp)=1; | |
e=find(d(transc)); | |
%%dataplot(e)=dataplot(e)+64; | |
dataplot3=zeros([size(dataplot,1),size(dataplot,2)]);dataplot3(e)=1;dataplot3=convn(convn(dataplot3,conf1,'same'),conf1,'same');e=find(dataplot3>0); | |
n=size(dataplot,1)*size(dataplot,2); | |
dataplot(e+1*n)=dataplot(e+1*n).*(1-dataplot3(e))+0*dataplot(e+0*n).*(dataplot3(e)); | |
dataplot(e+2*n)=dataplot(e+2*n).*(1-dataplot3(e))+0*dataplot(e+0*n).*(dataplot3(e)); | |
dataplot(e+0*n)=dataplot(e+0*n).*(1-dataplot3(e))+0*dataplot(e+0*n).*(dataplot3(e)); | |
end | |
if size(idx,3)~=1, | |
n=size(dataplot,1)*size(dataplot,2); | |
idxtemp1=find(dataplot2>0); | |
idxtemp2=find(c(trans(idxtemp1))>.5); | |
idxtemp=idxtemp1(idxtemp2); | |
temp3=dataplot(idxtemp+2*n); | |
dataplot(idxtemp+2*n)=dataplot(idxtemp+0*n); | |
dataplot(idxtemp+0*n)=temp3; | |
end | |
end | |
function [anew,txt,xyzpeak,clusters,clusternames,ithres]=vproject_display(a,threshold,thres,mat,side,Z,peakfdr) | |
global CONN_gui; | |
persistent refsrois; | |
if isempty(refsrois), | |
if isfield(CONN_gui,'refs')&&isfield(CONN_gui.refs,'rois')&&isfield(CONN_gui.refs.rois,'filename')&&~isempty(CONN_gui.refs.rois.filename), | |
refsrois=CONN_gui.refs.rois; | |
else | |
%filename=fullfile(fileparts(which('conn')),'utils','otherrois','Td.img'); | |
%filename=fullfile(fileparts(which('conn')),'rois','aal.nii'); | |
filename=fullfile(fileparts(which('conn')),'rois','BA.img'); | |
[filename_path,filename_name,filename_ext]=fileparts(filename); | |
V=spm_vol(filename); | |
refsrois=struct('filename',filename,'filenameshort',filename_name,'V',V,'data',spm_read_vols(V),'labels',{textread(fullfile(filename_path,[filename_name,'.txt']),'%s','delimiter','\n')}); | |
end | |
[x,y,z]=ndgrid(1:size(a,1),1:size(a,2),1:size(a,3));xyz=[x(:),y(:),z(:)]; | |
refsrois.data=spm_get_data(refsrois.V,pinv(refsrois.V.mat)*mat{1}*[xyz,ones(size(xyz,1),1)]'); | |
maxrefsrois=max(refsrois.data(:)); refsrois.count=hist(refsrois.data(:),0:maxrefsrois); | |
refsrois.labels={'not-labeled',refsrois.labels{:}}; | |
end | |
if nargin<5, side=1; end | |
if nargin<4, mat={eye(4),numel(a)}; end | |
idx0=find(~isnan(a)); | |
p=exp(-a(idx0)); | |
p0=a;p0(idx0)=p; | |
P=a;P(idx0)=conn_fdr(p(:)); | |
ithres=[nan,nan]; | |
switch(thres{2}), | |
case 1,%'vox-unc', | |
% voxels above height threshold | |
idxvoxels=find(a>-log(thres{1})); | |
anew=zeros(size(a));anew(idxvoxels)=a(idxvoxels)+log(thres{1});%1; | |
if ~isempty(idxvoxels), | |
[xt,yt,zt]=ind2sub(size(a),idxvoxels);C=spm_clusters([xt,yt,zt]');c=hist(C,1:max(C)); | |
end | |
if mat{6}=='T'&&side<3, %T stat | |
u=spm_invTcdf(1-thres{1},mat{3}(2)); | |
ithres(1)=u; | |
elseif mat{6}=='T'&&side==3, %two-sided T stat | |
u=spm_invFcdf(1-thres{1},mat{3}(1),mat{3}(2)); | |
ithres(1)=sqrt(u); | |
else %F stat | |
u=spm_invFcdf(1-thres{1},mat{3}(1),mat{3}(2)); | |
ithres(1)=u; | |
end | |
case 2,%'vox-FDR', | |
idxvoxels=find(P<thres{1}) ; | |
anew=zeros(size(a));anew(idxvoxels)=-log(P(idxvoxels))+log(thres{1});%1; | |
if ~isempty(idxvoxels), | |
[xt,yt,zt]=ind2sub(size(a),idxvoxels);C=spm_clusters([xt,yt,zt]');c=hist(C,1:max(C)); % C: cluster per voxel; c: #voxels per clusters | |
end | |
if isempty(idxvoxels), u=1; ithres(1)=inf;else, | |
if mat{6}=='T'&&side<3, %T stat | |
u=spm_invTcdf(1-exp(-min(a(idxvoxels))),mat{3}(2)); ithres(1)=u; | |
elseif mat{6}=='T'&&side==3, %two-sided T stat | |
u=spm_invFcdf(1-exp(-min(a(idxvoxels))),mat{3}(1),mat{3}(2)); ithres(1)=sqrt(u); | |
else %F stat | |
u=spm_invFcdf(1-exp(-min(a(idxvoxels))),mat{3}(1),mat{3}(2)); ithres(1)=u; | |
end | |
end | |
end | |
% if mat{6}=='T'&&side>2, %T stat two-sided | |
% ithres(1)=spm_invTcdf(1-(1-spm_Tcdf(ithres(1),mat{3}(2)))/2,mat{3}(2)); | |
% end | |
txt=[];xyzpeak={};clusters={};clusternames={}; | |
if ~isempty(idxvoxels), | |
xyz=[xt,yt,zt]; | |
idx1=find(c>0); | |
idxn=[];idx2={};for n1=1:length(idx1),idx2{n1}=find(C==(idx1(n1))); idxn(n1)=length(idx2{n1}); end | |
[nill,sidxn]=sort(idxn(:));sidxn=flipud(sidxn); | |
xyzpeak=cell(1,length(idx1)); | |
clusters=cell(1,length(idx1)); | |
k=zeros(1,length(idx1));cp=k;cP=k;Ez=k;cPFDR=k; minP=k;minp=k;maxZ=k;pPFWE=k; | |
for n1=1:length(idx1), | |
k(n1)=idxn(sidxn(n1)); | |
clusters{n1}=idxvoxels(idx2{sidxn(n1)}); | |
[minp(n1),idxminp]=min(p0(clusters{n1})); | |
minP(n1)=P(clusters{n1}(idxminp)); | |
maxZ(n1)=Z(clusters{n1}(idxminp)); | |
if side==2, maxZ(n1)=-maxZ(n1); end | |
%[minP(n1),idxminp]=min(P(clusters{n1})); | |
%minp(n1)=exp(-max(a(clusters{n1}))); | |
xyzpeak{n1}=xyz(idx2{sidxn(n1)}(idxminp),:); | |
if ~isempty(mat{2}), | |
if mat{6}=='T'&&side<3, %T stat | |
if isempty(mat{5}), [cP(n1),cp(n1)]=spm_P(1,k(n1)*mat{2}(end)/mat{4},u,mat{3},'T',mat{2},1,mat{4}); | |
else, [cP(n1),cp(n1)]=spm_P(1,k(n1)*mat{5},u,mat{3},'T',mat{2},1,mat{4}); | |
if isnan(cP(n1))&&~cp(n1),cP(n1)=0; end | |
end | |
pPFWE(n1)=spm_P(1,0,maxZ(n1),mat{3},'T',mat{2},1,mat{4}); | |
elseif mat{6}=='T'&&side==3, %two-sided T stat | |
if isempty(mat{5}), [nill,cP(n1),nill,cp(n1)] =stat_thres(mat{2},mat{4},mat{7},[mat{3};inf,inf], .05, u, k(n1)*mat{2}(end)/mat{4}); | |
else, [nill,cP(n1),nill,cp(n1)] =stat_thres(mat{2},mat{4},mat{7},[mat{3};inf,inf], .05, u, k(n1)*mat{5}); | |
if isnan(cP(n1))&&~cp(n1),cP(n1)=0; end | |
end | |
pPFWE(n1)=spm_P(1,0,maxZ(n1).^2,mat{3},'F',mat{2},1,mat{4}); | |
else %F stat | |
if 0,%enable Fcluster% %note:change this to 0 for NS toolbox implementation of cluster-level stats for F maps (assuming homogeneity) | |
cp(n1)=nan; cP(n1)=nan; | |
else | |
if isempty(mat{5}), [nill,cP(n1),nill,cp(n1)] =stat_thres(mat{2},mat{4},mat{7},[mat{3};inf,inf], .05, u, k(n1)*mat{2}(end)/mat{4}); | |
else, [nill,cP(n1),nill,cp(n1)] =stat_thres(mat{2},mat{4},mat{7},[mat{3};inf,inf], .05, u, k(n1)*mat{5}); | |
if isnan(cP(n1))&&~cp(n1),cP(n1)=0; end | |
end | |
end | |
pPFWE(n1)=spm_P(1,0,maxZ(n1),mat{3},'F',mat{2},1,mat{4}); | |
end | |
else, cP(n1)=nan;cp(n1)=nan; pPFWE(n1)=nan; end | |
end | |
if peakfdr>0, | |
try | |
if peakfdr==1, % consider all peak voxels for peak-FDR correction | |
if side==2, tZ=-Z(idxvoxels); else tZ=Z(idxvoxels); end | |
mtZ=min(tZ); | |
[maxN,maxZ,maxXYZ,maxA]=spm_max(1-mtZ+tZ,xyz'); | |
maxZ=maxZ+mtZ-1; | |
[maxOK,maxI]=min(sum(abs(conn_bsxfun(@minus,permute(maxXYZ',[1,3,2]),permute(cell2mat(xyzpeak'),[3,1,2]))).^2,3),[],1); | |
else % consider only onepeak voxel within each cluster for peak-FDR correction | |
maxI=1:numel(maxZ); | |
end | |
Ez=nan(size(maxZ)); | |
if mat{6}=='T'&&side<3, | |
[nill,nill,Eu] = spm_P_RF(1,0,u,mat{3},'T',mat{2},1); | |
for n1=1:numel(maxZ) | |
[nill,nill,Ez(n1)] = spm_P_RF(1,0,maxZ(n1),mat{3},'T',mat{2},1); | |
end | |
elseif mat{6}=='T'&&side==3, | |
[nill,nill,Eu] = spm_P_RF(1,0,u,mat{3},'F',mat{2},1); | |
for n1=1:numel(maxZ) | |
[nill,nill,Ez(n1)] = spm_P_RF(1,0,maxZ(n1).^2,mat{3},'F',mat{2},1); | |
end | |
else | |
[nill,nill,Eu] = spm_P_RF(1,0,u,mat{3},'F',mat{2},1); | |
for n1=1:numel(maxZ) | |
[nill,nill,Ez(n1)] = spm_P_RF(1,0,maxZ(n1),mat{3},'F',mat{2},1); | |
end | |
end | |
pPFDR=conn_fdr(Ez/Eu); | |
pPFDR=pPFDR(maxI); | |
maxZ=maxZ(maxI); | |
catch | |
pPFDR=nan(size(k)); | |
end | |
end | |
cPFDR=conn_fdr(cp); | |
for n1=1:length(idx1), | |
temp=['( ',sprintf('%+03.0f ',(mat{1}(1:3,:)*[xyzpeak{n1}';1])'),') ']; | |
temp=[temp,repmat(' ',[1,18-length(temp)])]; | |
if peakfdr>0, | |
txt=strvcat(txt,[... | |
temp,... | |
[sprintf('%15d',k(n1))],... | |
[sprintf('%15f',cP(n1))],... | |
[sprintf('%15f',cPFDR(n1))],... | |
[sprintf('%15f',cp(n1))],... | |
[sprintf('%15f',pPFWE(n1))],... | |
[sprintf('%15f',pPFDR(n1))],... | |
[sprintf('%15f',minp(n1))]]); | |
%[sprintf('%15f',minP(n1))]]); | |
else | |
txt=strvcat(txt,[... | |
temp,... | |
[sprintf('%15d',k(n1))],... | |
[sprintf('%15f',cP(n1))],... | |
[sprintf('%15f',cPFDR(n1))],... | |
[sprintf('%15f',cp(n1))],... | |
[sprintf('%15f',pPFWE(n1))],... | |
[sprintf('%15f',minp(n1))]]); | |
end | |
end | |
if ~peakfdr, thres4=thres{4}+(thres{4}>=6); | |
else thres4=thres{4}; | |
end | |
switch(thres4), | |
case 1,%'k-value', | |
idxclu=find(k>=thres{3}); | |
idxrem=find(~(k>=thres{3})); | |
case 2,%'clu-FWE', | |
idxclu=find(cP<thres{3}); | |
idxrem=find(~(cP<thres{3})); | |
case 3,%'clu-FDR', | |
idxclu=find(cPFDR<thres{3}); | |
idxrem=find(~(cPFDR<thres{3})); | |
case 4,%'clu-unc', | |
idxclu=find(cp<thres{3}); | |
idxrem=find(~(cp<thres{3})); | |
case 5,%'peak-FWE', | |
idxclu=find(pPFWE<thres{3}); | |
idxrem=find(~(pPFWE<thres{3})); | |
case 6,%'peak-FDR', | |
idxclu=find(pPFDR<thres{3}); | |
idxrem=find(~(pPFDR<thres{3})); | |
case 7,%'peak-unc', | |
idxclu=find(minp<thres{3}); | |
idxrem=find(~(minp<thres{3})); | |
end | |
if ~isempty(idxclu), ithres(2)=min(k(idxclu)); end | |
for n1=1:length(idxrem), anew(clusters{idxrem(n1)})=0; end | |
txt=txt(idxclu,:); | |
xyzpeak={xyzpeak{idxclu}}; | |
clusters={clusters{idxclu}}; | |
if ~isempty(idxclu), | |
for n1=1:length(idxclu)+1, | |
if n1<=length(idxclu),xyztemp=xyz(idx2{sidxn(idxclu(n1))},:); | |
else, xyztemp=xyz(cat(2,idx2{sidxn(idxclu)}),:); end; | |
v=spm_get_data(refsrois.V,pinv(refsrois.V.mat)*mat{1}*[xyztemp,ones(size(xyztemp,1),1)]'); | |
uv=unique(v); | |
clusternames{n1}.uvb=zeros(1,length(uv));for n2=1:length(uv),clusternames{n1}.uvb(n2)=sum(v==uv(n2));end | |
clusternames{n1}.uvc=refsrois.count(1+uv); | |
clusternames{n1}.uvd={refsrois.labels{1+uv}}; | |
[nill,uvidx]=sort(-clusternames{n1}.uvb+1e10*(uv==0)); | |
clusternames{n1}.uvb=clusternames{n1}.uvb(uvidx);clusternames{n1}.uvc=clusternames{n1}.uvc(uvidx);clusternames{n1}.uvd={clusternames{n1}.uvd{uvidx}}; | |
clusternames{n1}.txt=cell(1,length(uv)); for n2=1:length(uv),clusternames{n1}.txt{n2}=[num2str(clusternames{n1}.uvb(n2)),' voxels covering ',num2str(clusternames{n1}.uvb(n2)/clusternames{n1}.uvc(n2)*100,'%0.0f'),'% of ',refsrois.filenameshort,'.',clusternames{n1}.uvd{n2}]; end | |
clusternames{n1}.txt=strvcat(clusternames{n1}.txt{:}); | |
end | |
end | |
% clusternames={clusternames{idxclu,1},clusternames{idxclu(idxclulast),2}}; | |
%for n1=1:length(clusternames),disp(' ');disp(clusternames{n1}.txt);end | |
end | |
%if params.plotlist, figure('color','w'); end | |
%h=[];xlim=[];ylim=[]; | |
%disp(txt); | |
% if params.permutation && ~isempty(params.L), | |
% txt{end}=[txt{end},' p=',num2str(mean(params.L(:,1)>=k),'%0.4f'),' (',num2str(length(unique(params.L(params.L(:,1)>=k,2)))/params.Ln,'%0.4f'),')']; | |
% end | |
% if params.plotlist, | |
% %subplot(length(idx1),1,n1); | |
% h(n1)=axes('units','norm','position',... | |
% [.9,.5*(1-n1/max(length(idx1)+1,5)+.05/max(length(idx1)+1,5)),.09,.5*.9/max(length(idx1)+1,5)]); | |
% mx1=mean(X1(:,idx(idx2{sidxn(n1)})),2); | |
% mx2=mean(X2(:,idx(idx2{sidxn(n1)})),2); | |
% plot(mx1,mx2,'.'); h0=ylabel(txt{end});set(h0,'fontsize',8,'rotation',0,'horizontalalignment','right') | |
% params.output.clusters{n1}=[mx1,mx2]; | |
% xlim=cat(1,xlim,[min(mx1),max(mx1)]);ylim=cat(1,ylim,[min(mx2),max(mx2)]); | |
% end | |
% end | |
%if params.plotlist, | |
% for n1=1:length(idx1), | |
% set(h(n1),'xlim',[min(xlim(:,1))-.01,max(xlim(:,2))+.01],'ylim',[min(ylim(:,1))-.01,max(ylim(:,2))+.01]); | |
% if n1~=length(idx1), set(h(n1),'xticklabel',[],'yticklabel',[],'fontsize',6); end | |
% end | |
%end | |
end | |
function [peak_threshold, extent_threshold, peak_threshold_1, extent_threshold_1] = ... | |
stat_thres(search_volume, num_voxels, fwhm, df, p_val_peak, ... | |
cluster_threshold, p_val_extent, nconj, nvar, EC_file, expr) | |
% | |
% stat_thresh.m | |
% Modified version of STAT_THRESHOLD function by Keith Worsley. The original | |
% STAT_THRESHOLD function is part of the FMRISTAT packgage. The main use of the | |
% original version is to calculate peak and cluster thresholds, both corrected | |
% and uncorrected. Details on input and output arguments are found in the | |
% original STAT_THRESHOLD function available from Keith Worsley's web site | |
% at McGill University's Math & Stat department. | |
% | |
% This stat_thresh.m function is a customized version to be called by a function | |
% spm_list_nS for non-stationarity correction of RFT-based cluster size test. | |
% The input and output of this function is therefore modified for producing cluster | |
% p-values (corrected) under non-stationarity. The modification includes: | |
% -supressing the output from being displayed. | |
% -the number of cluster p-values it can calculate has been increased to 500 clusters | |
% (the default in the original version was 5). | |
% -the p_val_extent is treated as extent, no matter how small it is. | |
% | |
% stat_thresh is called by spm_list_nS in the following format: | |
% [PEAK_P CLUSTER_P PEAK_P_1 CLUSTER_P_1] = | |
% stat_thresh(V_RESEL,NUM_VOX,1,[DF_ER;DF_RPV],ALPHA,CL_DEF_TH,CL_RESEL); | |
% PARAMETERS: | |
% V_RESEL: The seach volume in terms of resels. It is a 1x4 vector | |
% describing the topological characteristic of the search | |
% volume. | |
% NUM_VOX: The number of voxels in the search volume. | |
% DF_ER: Degrees of freedom of error | |
% DF_RPV: Degrees of freedom of RPV image estimation. Usually the same | |
% as the error df. | |
% ALPHA: The significance level of the peak (arbitrarily set to 0.05) | |
% CL_DEF_TH: The cluster defining threshold. Can be entered in terms of | |
% a p-value (uncorrected) or a t-value. | |
% CL_RESEL: The cluster size in terms of resel | |
% | |
% PEAK_P: Peak p-value (FWE corrected). Not used for our purpose. | |
% PEAK_P_1: Peak p-value (uncorrected). Not used for our purpose. | |
% CLUSTER_P: Cluster p-value (FWE corrected) | |
% CLUSTER_P_1: Cluster p-value (uncorrected) | |
% | |
% ---------------- | |
% | |
% More etails on non-stationary cluster size test can be found in | |
% | |
% Worsley K J, Andermann M, Koulis T, MacDonald D and Evans A C | |
% Detecting Changes in Nonisotropic Images | |
% Human Brain Mapping 8: 98-101 (1999) | |
% | |
% Hayasaka S, Phan K L, Liberzon I, Worsley K J, and Nichols T E | |
% Nonstationary cluster size inference with random-field and permutation methods | |
% NeuroImage 22: 676-687 (2004) | |
% | |
% | |
%----------------------------------------------------------------------------------- | |
% Version 0.76b Feb 19, 2007 by Satoru Hayasaka | |
% | |
%############################################################################ | |
% COPYRIGHT: Copyright 2003 K.J. Worsley | |
% Department of Mathematics and Statistics, | |
% McConnell Brain Imaging Center, | |
% Montreal Neurological Institute, | |
% McGill University, Montreal, Quebec, Canada. | |
% keith.worsley@mcgill.ca , www.math.mcgill.ca/keith | |
% | |
% Permission to use, copy, modify, and distribute this | |
% software and its documentation for any purpose and without | |
% fee is hereby granted, provided that this copyright | |
% notice appears in all copies. The author and McGill University | |
% make no representations about the suitability of this | |
% software for any purpose. It is provided "as is" without | |
% express or implied warranty. | |
%############################################################################ | |
%############################################################################ | |
% UPDATES: | |
% | |
% Variable nvar is rounded so that it is recognized as an integer. | |
% Feb 19, 2007 by Satoru Hayasaka | |
%############################################################################ | |
% Defaults: | |
if nargin<1; search_volume=[]; end | |
if nargin<2; num_voxels=[]; end | |
if nargin<3; fwhm=[]; end | |
if nargin<4; df=[]; end | |
if nargin<5; p_val_peak=[]; end | |
if nargin<6; cluster_threshold=[]; end | |
if nargin<7; p_val_extent=[]; end | |
if nargin<8; nconj=[]; end | |
if nargin<9; nvar=[]; end | |
if nargin<10; EC_file=[]; end | |
if nargin<11; expr=[]; end | |
if isempty(search_volume); search_volume=1000000; end | |
if isempty(num_voxels); num_voxels=1000000; end | |
if isempty(fwhm); fwhm=0.0; end | |
if isempty(df); df=Inf; end | |
if isempty(p_val_peak); p_val_peak=0.05; end | |
if isempty(cluster_threshold); cluster_threshold=0.001; end | |
if isempty(p_val_extent); p_val_extent=0.05; end | |
if isempty(nconj); nconj=1; end | |
if isempty(nvar); nvar=1; end | |
if size(fwhm,1)==1; fwhm(2,:)=fwhm; end | |
if size(fwhm,2)==1; scale=1; else scale=fwhm(1,2)/fwhm(1,1); fwhm=fwhm(:,1); end; | |
isscale=(scale>1); | |
if length(num_voxels)==1; num_voxels(2,1)=1; end | |
if size(search_volume,2)==1 | |
radius=(search_volume/(4/3*pi)).^(1/3); | |
search_volume=[ones(length(radius),1) 4*radius 2*pi*radius.^2 search_volume]; | |
end | |
if size(search_volume,1)==1 | |
search_volume=[search_volume; [1 zeros(1,size(search_volume,2)-1)]]; | |
end | |
lsv=size(search_volume,2); | |
fwhm_inv=all(fwhm>0)./(fwhm+any(fwhm<=0)); | |
resels=search_volume.*repmat(fwhm_inv,1,lsv).^repmat(0:lsv-1,2,1); | |
invol=resels.*(4*log(2)).^(repmat(0:lsv-1,2,1)/2); | |
for k=1:2 | |
D(k,1)=max(find(invol(k,:)))-1; | |
end | |
% determines which method was used to estimate fwhm (see fmrilm or multistat): | |
df_limit=4; | |
% max number of pvalues or thresholds to print: | |
% it can print out a ton of stuff! (the original default was 5) | |
nprint=500; | |
if length(df)==1; df=[df 0]; end | |
if size(df,1)==1; df=[df; Inf Inf]; end | |
if size(df,2)==1; df=[df [0; df(2,1)]]; end | |
% is_tstat=1 if it is a t statistic | |
is_tstat=(df(1,2)==0); | |
if is_tstat | |
df1=1; | |
df2=df(1,1); | |
else | |
df1=df(1,1); | |
df2=df(1,2); | |
end | |
if df2 >= 1000; df2=Inf; end | |
df0=df1+df2; | |
dfw1=df(2,1); | |
dfw2=df(2,2); | |
if dfw1 >= 1000; dfw1=Inf; end | |
if dfw2 >= 1000; dfw2=Inf; end | |
if length(nvar)==1; nvar(2,1)=df1; end | |
nvar = round(nvar); %-to make sure that nvar is integer! | |
if isscale & (D(2)>1 | nvar(1,1)>1 | df2<Inf) | |
D | |
nvar | |
df2 | |
fprintf('Cannot do scale space.'); | |
return | |
end | |
Dlim=D+[scale>1; 0]; | |
DD=Dlim+nvar-1; | |
% Values of the F statistic: | |
t=((1000:-1:1)'/100).^4; | |
% Find the upper tail probs cumulating the F density using Simpson's rule: | |
if df2==Inf | |
u=df1*t; | |
b=exp(-u/2-log(2*pi)/2+log(u)/4)*df1^(1/4)*4/100; | |
else | |
u=df1*t/df2; | |
b=exp(-df0/2*log(1+u)+log(u)/4-betaln(1/2,(df0-1)/2))*(df1/df2)^(1/4)*4/100; | |
end | |
t=[t; 0]; | |
b=[b; 0]; | |
n=length(t); | |
sb=cumsum(b); | |
sb1=cumsum(b.*(-1).^(1:n)'); | |
pt1=sb+sb1/3-b/3; | |
pt2=sb-sb1/3-b/3; | |
tau=zeros(n,DD(1)+1,DD(2)+1); | |
tau(1:2:n,1,1)=pt1(1:2:n); | |
tau(2:2:n,1,1)=pt2(2:2:n); | |
tau(n,1,1)=1; | |
tau(:,1,1)=min(tau(:,1,1),1); | |
% Find the EC densities: | |
u=df1*t; | |
kk=(max(DD)-1+min(DD))/2; | |
uu=conn_bsxfun(@power,u,0:.5:kk); | |
[ii,jj]=ndgrid(0:kk,0:kk); | |
gammalnii=gammalni(0:max(DD)+kk); | |
for d=1:max(DD) | |
for e=0:min(min(DD),d) | |
s1=0; | |
cons=-((d+e)/2+1)*log(pi)+gammaln(d)+gammaln(e+1); | |
for k=0:(d-1+e)/2 | |
%[i,j]=ndgrid(0:k,0:k); | |
i=ii(1:k+1,1:k+1); j=jj(1:k+1,1:k+1); | |
if df2==Inf | |
q1=log(pi)/2-((d+e-1)/2+i+j)*log(2); | |
else | |
q1=(df0-1-d-e)*log(2)+gammaln((df0-d)/2+i)+gammaln((df0-e)/2+j) ... | |
-gammalni(df0-d-e+i+j+k)-((d+e-1)/2-k)*log(df2); | |
end | |
%q2=cons-gammalni(i+1)-gammalni(j+1)-gammalni(k-i-j+1) ... | |
% -gammalni(d-k-i+j)-gammalni(e-k-j+i+1); | |
q2=cons-gammalnii(1+max(0,i+1))-gammalnii(1+max(0,j+1))-gammalnii(1+max(0,k-i-j+1)) ... | |
-gammalnii(1+max(0,d-k-i+j))-gammalnii(1+max(0,e-k-j+i+1)); | |
s2=sum(sum(exp(q1+q2))); | |
if s2>0 | |
%s1=s1+(-1)^k*u.^((d+e-1)/2-k)*s2; | |
s1=s1+(-1)^k*uu(:,1+2*((d+e-1)/2-k))*s2; | |
end | |
end | |
if df2==Inf | |
s1=s1.*exp(-u/2); | |
else | |
s1=s1.*exp(-(df0-2)/2*log(1+u/df2)); | |
end | |
if DD(1)>=DD(2) | |
tau(:,d+1,e+1)=s1; | |
if d<=min(DD) | |
tau(:,e+1,d+1)=s1; | |
end | |
else | |
tau(:,e+1,d+1)=s1; | |
if d<=min(DD) | |
tau(:,d+1,e+1)=s1; | |
end | |
end | |
end | |
end | |
% For multivariate statistics, add a sphere to the search region: | |
a=zeros(2,max(nvar)); | |
for k=1:2 | |
j=(nvar(k)-1):-2:0; | |
a(k,j+1)=exp(j*log(2)+j/2*log(pi) ... | |
+gammaln((nvar(k)+1)/2)-gammaln((nvar(k)+1-j)/2)-gammaln(j+1)); | |
end | |
rho=zeros(n,Dlim(1)+1,Dlim(2)+1); | |
for k=1:nvar(1) | |
for l=1:nvar(2) | |
rho=rho+a(1,k)*a(2,l)*tau(:,(0:Dlim(1))+k,(0:Dlim(2))+l); | |
end | |
end | |
if is_tstat | |
t=[sqrt(t(1:(n-1))); -flipdim(sqrt(t),1)]; | |
rho=[rho(1:(n-1),:,:); flipdim(rho,1)]/2; | |
for i=0:D(1) | |
for j=0:D(2) | |
rho(n-1+(1:n),i+1,j+1)=-(-1)^(i+j)*rho(n-1+(1:n),i+1,j+1); | |
end | |
end | |
rho(n-1+(1:n),1,1)=rho(n-1+(1:n),1,1)+1; | |
n=2*n-1; | |
end | |
% For scale space: | |
if scale>1 | |
kappa=D(1)/2; | |
tau=zeros(n,D(1)+1); | |
for d=0:D(1) | |
s1=0; | |
for k=0:d/2 | |
s1=s1+(-1)^k/(1-2*k)*exp(gammaln(d+1)-gammaln(k+1)-gammaln(d-2*k+1) ... | |
+(1/2-k)*log(kappa)-k*log(4*pi))*rho(:,d+2-2*k,1); | |
end | |
if d==0 | |
cons=log(scale); | |
else | |
cons=(1-1/scale^d)/d; | |
end | |
tau(:,d+1)=rho(:,d+1,1)*(1+1/scale^d)/2+s1*cons; | |
end | |
rho(:,1:(D(1)+1),1)=tau; | |
end | |
if D(2)==0 | |
d=D(1); | |
if nconj>1 | |
% Conjunctions: | |
b=gamma(((0:d)+1)/2)/gamma(1/2); | |
for i=1:d+1 | |
rho(:,i,1)=rho(:,i,1)/b(i); | |
end | |
m1=zeros(n,d+1,d+1); | |
for i=1:d+1 | |
j=i:d+1; | |
m1(:,i,j)=rho(:,j-i+1,1); | |
end | |
for k=2:nconj | |
for i=1:d+1 | |
for j=1:d+1 | |
m2(:,i,j)=sum(rho(:,1:d+2-i,1).*m1(:,i:d+1,j),2); | |
end | |
end | |
m1=m2; | |
end | |
for i=1:d+1 | |
rho(:,i,1)=m1(:,1,i)*b(i); | |
end | |
end | |
if ~isempty(EC_file) | |
if d<3 | |
rho(:,(d+2):4,1)=zeros(n,4-d-2+1); | |
end | |
fid=fopen(EC_file,'w'); | |
% first 3 are dimension sizes as 4-byte integers: | |
fwrite(fid,[n max(d+2,5) 1],'int'); | |
% next 6 are bounding box as 4-byte floats: | |
fwrite(fid,[0 0 0; 1 1 1],'float'); | |
% rest are the data as 4-byte floats: | |
if ~isempty(expr) | |
eval(expr); | |
end | |
fwrite(fid,t,'float'); | |
fwrite(fid,rho,'float'); | |
fclose(fid); | |
end | |
end | |
if all(fwhm>0) | |
pval_rf=zeros(n,1); | |
for i=1:D(1)+1 | |
for j=1:D(2)+1 | |
pval_rf=pval_rf+invol(1,i)*invol(2,j)*rho(:,i,j); | |
end | |
end | |
else | |
pval_rf=Inf; | |
end | |
% Bonferroni | |
pt=rho(:,1,1); | |
pval_bon=abs(prod(num_voxels))*pt; | |
% Minimum of the two: | |
pval=min(pval_rf,pval_bon); | |
tlim=1; | |
if p_val_peak(1) <= tlim | |
peak_threshold=minterp1(pval,t,p_val_peak); | |
if length(p_val_peak)<=nprint | |
peak_threshold; | |
end | |
else | |
% p_val_peak is treated as a peak value: | |
P_val_peak=interp1(t,pval,p_val_peak); | |
peak_threshold=P_val_peak; | |
if length(p_val_peak)<=nprint | |
P_val_peak; | |
end | |
end | |
if fwhm<=0 | any(num_voxels<0) | |
peak_threshold_1=p_val_peak+NaN; | |
extent_threshold=p_val_extent+NaN; | |
extent_threshold_1=extent_threshold; | |
return | |
end | |
% Cluster_threshold: | |
%###-Changed so that cluster_threshold is considered as cluster extent no matter what. | |
if cluster_threshold > eps | |
tt=cluster_threshold; | |
else | |
% cluster_threshold is treated as a probability: | |
tt=minterp1(pt,t,cluster_threshold); | |
Cluster_threshold=tt; | |
end | |
d=D(1); | |
rhoD=interp1(t,rho(:,d+1,1),tt); | |
p=interp1(t,pt,tt); | |
% Pre-selected peak: | |
pval=rho(:,d+1,1)./rhoD; | |
if p_val_peak(1) <= tlim | |
peak_threshold_1=minterp1(pval,t, p_val_peak); | |
if length(p_val_peak)<=nprint | |
peak_threshold_1; | |
end | |
else | |
% p_val_peak is treated as a peak value: | |
P_val_peak_1=interp1(t,pval,p_val_peak); | |
peak_threshold_1=P_val_peak_1; | |
if length(p_val_peak)<=nprint | |
P_val_peak_1; | |
end | |
end | |
if D(1)==0 | nconj>1 | nvar(1)>1 | D(2)>0 | scale>1 | |
extent_threshold=p_val_extent+NaN; | |
extent_threshold_1=extent_threshold; | |
if length(p_val_extent)<=nprint | |
extent_threshold; | |
extent_threshold_1; | |
end | |
return | |
end | |
% Expected number of clusters: | |
%###-Change tlim to a small number so that p_val_extent is considered as cluster extent | |
tlim = eps; | |
EL=invol(1,d+1)*rhoD; | |
cons=gamma(d/2+1)*(4*log(2))^(d/2)/fwhm(1)^d*rhoD/p; | |
if df2==Inf & dfw1==Inf | |
if p_val_extent(1) <= tlim | |
pS=-log(1-p_val_extent)/EL; | |
extent_threshold=(-log(pS)).^(d/2)/cons; | |
pS=-log(1-p_val_extent); | |
extent_threshold_1=(-log(pS)).^(d/2)/cons; | |
if length(p_val_extent)<=nprint | |
extent_threshold; | |
extent_threshold_1; | |
end | |
else | |
% p_val_extent is now treated as a spatial extent: | |
pS=exp(-(p_val_extent*cons).^(2/d)); | |
P_val_extent=1-exp(-pS*EL); | |
extent_threshold=P_val_extent; | |
P_val_extent_1=1-exp(-pS); | |
extent_threshold_1=P_val_extent_1; | |
if length(p_val_extent)<=nprint | |
P_val_extent; | |
P_val_extent_1; | |
end | |
end | |
else | |
% Find dbn of S by taking logs then using fft for convolution: | |
ny=2^12; | |
a=d/2; | |
b2=a*10*max(sqrt(2/(min(df1+df2,dfw1))),1); | |
if df2<Inf | |
b1=a*log((1-(1-0.000001)^(2/(df2-d)))*df2/2); | |
else | |
b1=a*log(-log(1-0.000001)); | |
end | |
dy=(b2-b1)/ny; | |
b1=round(b1/dy)*dy; | |
y=((1:ny)'-1)*dy+b1; | |
numrv=1+(d+1)*(df2<Inf)+d*(dfw1<Inf)+(dfw2<Inf); | |
f=zeros(ny,numrv); | |
mu=zeros(1,numrv); | |
if df2<Inf | |
% Density of log(Beta(1,(df2-d)/2)^(d/2)): | |
yy=exp(y./a)/df2*2; | |
yy=yy.*(yy<1); | |
f(:,1)=(1-yy).^((df2-d)/2-1).*((df2-d)/2).*yy/a; | |
mu(1)=exp(gammaln(a+1)+gammaln((df2-d+2)/2)-gammaln((df2+2)/2)+a*log(df2/2)); | |
else | |
% Density of log(exp(1)^(d/2)): | |
yy=exp(y./a); | |
f(:,1)=exp(-yy).*yy/a; | |
mu(1)=exp(gammaln(a+1)); | |
end | |
nuv=[]; | |
aav=[]; | |
if df2<Inf | |
nuv=[df1+df2-d df2+2-(1:d)]; | |
aav=[a repmat(-1/2,1,d)]; | |
end | |
if dfw1<Inf | |
if dfw1>df_limit | |
nuv=[nuv dfw1-dfw1/dfw2-(0:(d-1))]; | |
else | |
nuv=[nuv repmat(dfw1-dfw1/dfw2,1,d)]; | |
end | |
aav=[aav repmat(1/2,1,d)]; | |
end | |
if dfw2<Inf | |
nuv=[nuv dfw2]; | |
aav=[aav -a]; | |
end | |
for i=1:(numrv-1) | |
nu=nuv(i); | |
aa=aav(i); | |
yy=y/aa+log(nu); | |
% Density of log((chi^2_nu/nu)^aa): | |
f(:,i+1)=exp(nu/2*yy-exp(yy)/2-(nu/2)*log(2)-gammaln(nu/2))/abs(aa); | |
mu(i+1)=exp(gammaln(nu/2+aa)-gammaln(nu/2)-aa*log(nu/2)); | |
end | |
% Check: plot(y,f); sum(f*dy,1) should be 1 | |
omega=2*pi*((1:ny)'-1)/ny/dy; | |
shift=complex(cos(-b1*omega),sin(-b1*omega))*dy; | |
prodfft=prod(fft(f),2).*shift.^(numrv-1); | |
% Density of Y=log(B^(d/2)*U^(d/2)/sqrt(det(Q))): | |
ff=real(ifft(prodfft)); | |
% Check: plot(y,ff); sum(ff*dy) should be 1 | |
mu0=prod(mu); | |
% Check: plot(y,ff.*exp(y)); sum(ff.*exp(y)*dy.*(y<10)) should equal mu0 | |
alpha=p/rhoD/mu0*fwhm(1)^d/(4*log(2))^(d/2); | |
% Integrate the density to get the p-value for one cluster: | |
pS=cumsum(ff(ny:-1:1))*dy; | |
pS=pS(ny:-1:1); | |
% The number of clusters is Poisson with mean EL: | |
pSmax=1-exp(-pS*EL); | |
if p_val_extent(1) <= tlim | |
yval=minterp1(-pSmax,y,-p_val_extent); | |
% Spatial extent is alpha*exp(Y) -dy/2 correction for mid-point rule: | |
extent_threshold=alpha*exp(yval-dy/2); | |
% For a single cluster: | |
yval=minterp1(-pS,y,-p_val_extent); | |
extent_threshold_1=alpha*exp(yval-dy/2); | |
if length(p_val_extent)<=nprint | |
extent_threshold; | |
extent_threshold_1; | |
end | |
else | |
% p_val_extent is now treated as a spatial extent: | |
P_val_extent=interp1(y,pSmax,log(p_val_extent/alpha)+dy/2); | |
extent_threshold=P_val_extent; | |
% For a single cluster: | |
P_val_extent_1=interp1(y,pS,log(p_val_extent/alpha)+dy/2); | |
extent_threshold_1=P_val_extent_1; | |
if length(p_val_extent)<=nprint | |
P_val_extent; | |
P_val_extent_1; | |
end | |
end | |
end | |
return | |
end | |
function x=gammalni(n); | |
i=find(n>=0); | |
x=Inf+n; | |
if ~isempty(i) | |
x(i)=gammaln(n(i)); | |
end | |
return | |
end | |
function iy=minterp1(x,y,ix); | |
% interpolates only the monotonically increasing values of x at ix | |
n=length(x); | |
mx=x(1); | |
my=y(1); | |
xx=x(1); | |
for i=2:n | |
if x(i)>xx | |
xx=x(i); | |
mx=[mx xx]; | |
my=[my y(i)]; | |
end | |
end | |
iy=interp1(mx,my,ix); | |
return | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment