diff --git a/CodeBook.mat b/CodeBook.mat index 7852c55..98b51d8 100644 Binary files a/CodeBook.mat and b/CodeBook.mat differ diff --git a/JOVE_GUI4.m b/JOVE_GUI4.m index 31b2102..e0885d9 100644 --- a/JOVE_GUI4.m +++ b/JOVE_GUI4.m @@ -1,509 +1,509 @@ function varargout = JOVE_GUI4(varargin) gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @JOVE_GUI4_OpeningFcn, ... 'gui_OutputFcn', @JOVE_GUI4_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end function JOVE_GUI4_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; addpath(genpath(fullfile(pwd,'Utilities'))); handles.NullType = 'Normal'; handles.IsISFCDataLoaded = 0; handles.IsNullLoaded = 0; handles.IsCodeBookLoaded = 0; handles.W = realmax; handles.TR = 1; handles.IsTREntered = 0; handles.IsWEntered = 0; handles.ISFC_Data = {}; handles.Null_Data = {}; handles.Alpha = 0.01; handles.NullThresh = {}; handles.SignMat = []; handles.IDX= []; handles.t_start = 0; handles.t_end = realmax; handles.range = [-1,1]; handles.SaveName = 'DefaultName'; guidata(hObject, handles); function varargout = JOVE_GUI4_OutputFcn(hObject, eventdata, handles) varargout{1} = handles.output; %% Loading the ISFC data to threshold function DataButton_Callback(hObject, eventdata, handles) % Selection of all the fMRI files [filename1,pathname1]=uigetfile({'*.*','All Files'},... 'Select ISFC files...','MultiSelect','on'); % If the user has indeed entered files if ~isequal(filename1,0) || ~isequal(pathname1,0) if ~ischar(filename1) % The files are loaded sequentially: File{t} contains the path % towards the t-th frame for f = 1:length(filename1) load((fullfile(pathname1, filename1{f}))); assignin('base','ISFC_Final', ISFC_Final); handles.ISFC_Data = [handles.ISFC_Data,ISFC_Final]; end else load((fullfile(pathname1, filename1))); assignin('base','ISFC_Final', ISFC_Final); handles.ISFC_Data = ISFC_Final; end handles.IsISFCDataLoaded = 1; % If we have entered all required fields, we prepare the slider to % lie within the t_start/t_end interval if handles.IsTREntered && handles.IsWEntered && handles.IsISFCDataLoaded handles.t_start = (handles.TR*handles.W)-1; handles.t_end = (size(handles.ISFC_Data{1},2)-1)*handles.TR + handles.t_start; set(handles.Slider,'Value',handles.t_start); set(handles.Slider,'Min',handles.t_start); set(handles.Slider,'Max',handles.t_end); end end guidata(hObject,handles); %% Loading of the null data function NullButton_Callback(hObject, eventdata, handles) % Selection of all the fMRI files [filename2,pathname2]=uigetfile({'*.*','All Files'},... 'Select null ISFC files...','MultiSelect','on'); % If the user has indeed entered files if ~isequal(filename2,0) || ~isequal(pathname2,0) if ~ischar(filename2) % The files are loaded sequentially: File{t} contains the path % towards the t-th frame for f = 1:length(filename2) load((fullfile(pathname2, filename2{f}))); assignin('base','ISFC_Final', ISFC_Final); handles.Null_Data = [handles.Null_Data,ISFC_Final]; end else load((fullfile(pathname2, filename2))); assignin('base','ISFC_Final', ISFC_Final); handles.Null_Data = ISFC_Final; end handles.IsNullLoaded = 1; end guidata(hObject,handles); %% Entry of the percentile value at which to threshold function PercentileText_Callback(hObject, eventdata, handles) if (~isempty(str2double(get(hObject,'String')))) && ... (str2double(get(hObject,'String')) > 0) && ... (str2double(get(hObject,'String')) < 100) handles.Alpha = str2double(get(hObject,'String')); set(hObject,'BackgroundColor', [0.4 0.6 0.4]); else set(hObject,'BackgroundColor', [0.93 0.84 0.84]); end guidata(hObject,handles); function PercentileText_CreateFcn(hObject, eventdata, handles) set(hObject,'String','Enter alpha value...'); set(hObject,'FontAngle','italic'); guidata(hObject,handles); function PercentileText_ButtonDownFcn(hObject, eventdata, handles) set(hObject,'Enable','on'); set(hObject,'String',''); set(hObject,'FontAngle','normal'); uicontrol(hObject); guidata(hObject,handles); %% Plotting button function PlotButton_Callback(hObject, eventdata, handles) if handles.IsISFCDataLoaded && handles.IsNullLoaded % Computes excursions (size conn x n_swtp x subj) [SignMat,NullThresh] = JOVE_FindExcursions(handles.ISFC_Data,handles.Null_Data,handles.Alpha,handles.NullType); handles.SignMat = SignMat; handles.NullThresh = NullThresh; % Sorts the time courses, so that we display first the ones with the % largest excursion values (absolute) [tmp,IDX] = sort(squeeze(sum(abs(mean(handles.SignMat,3)),2)),'descend'); handles.IDX = IDX(~isnan(tmp)); tmp = handles.ISFC_Data{1}(handles.IDX,:); tmp = tmp(:); handles.range = [-max(abs(tmp)),max(abs(tmp))]; % Plots the ISFC data as well as the associated thresholds - [handles.ISFCPlot] = JOVE_PlotAtlasTC(handles.ISFCPlot,handles.ISFC_Data{1},handles.IDX(1:4),'ISFC',handles.W,handles.Step,handles.TR); + [handles.ISFCPlot] = JOVE_PlotAtlasTC(handles.ISFCPlot,handles.ISFC_Data{1},handles.IDX(1:3),'ISFC',handles.W,handles.Step,handles.TR); tmp_CM = cbrewer('qual','Set1',3); for i = 1:3 plot([handles.t_start,handles.t_end],[handles.NullThresh{1}(handles.IDX(i),1),handles.NullThresh{1}(handles.IDX(i),1)],'Parent',handles.ISFCPlot,'Color',tmp_CM(i,:)); plot([handles.t_start,handles.t_end],[handles.NullThresh{1}(handles.IDX(i),2),handles.NullThresh{1}(handles.IDX(i),2)],'Parent',handles.ISFCPlot,'Color',tmp_CM(i,:)); end handles.Line1 = plot([handles.t_start handles.t_start],[-1 1],'color',[0 0 0],'Parent',handles.ISFCPlot); % Plots the excursion time courses for i = 1:3 tmp_vec = zeros(size(handles.ISFC_Data{1},1),1); tmp_vec(handles.IDX(i)) = 1; tmp_mat = jVecToUpperTriMat(tmp_vec,(1+sqrt(1+4*2*size(handles.SignMat,1)))/2); JOVE_Plot_Conn_TimeCourse(handles.ExcPlot,handles.SignMat,find(sum(tmp_mat,2)==1),find(sum(tmp_mat,1)==1),handles.W,handles.TR,tmp_CM(i,:),tmp_CM(i,:)); end handles.Line2 = plot([handles.t_start handles.t_start],[-1 1],'color',[0 0 0],'Parent',handles.ExcPlot); if handles.IsCodeBookLoaded == 1 curtime = floor((get(handles.Slider,'Value')-handles.t_start)/(handles.Step*handles.TR)) + 1; Spatial_OI = mean(squeeze(handles.SignMat(:,curtime,:)),2); tmp_MAT = jVecToUpperTriMat(Spatial_OI,(1+sqrt(1+4*2*size(handles.SignMat,1)))/2)+jVecToUpperTriMat(Spatial_OI,(1+sqrt(1+4*2*size(handles.SignMat,1)))/2)'; tmp_DEG = sum(abs(tmp_MAT),1)/2; Factor_plots = 2*max(tmp_DEG); PlotBrainGraph_Kmeans_withtitle(handles.BrainPlot,tmp_MAT,tmp_DEG,handles.CodeBook,0.2,... Factor_plots,Factor_plots,2,1,'hot','spring',1,0.5,[-1 1],... 'W10_Alpha001','W10_Alpha001'); end end guidata(hObject,handles); %% Slider controls function Slider_Callback(hObject, eventdata, handles) handles.Line1.XData = [get(hObject,'Value'), get(hObject,'Value')]; handles.Line2.XData = [get(hObject,'Value'), get(hObject,'Value')]; if handles.IsCodeBookLoaded == 1 curtime = floor((get(hObject,'Value')-handles.t_start)/(handles.Step*handles.TR)) + 1; Spatial_OI = mean(squeeze(handles.SignMat(:,curtime,:)),2); tmp_MAT = jVecToUpperTriMat(Spatial_OI,(1+sqrt(1+4*2*size(handles.SignMat,1)))/2)+jVecToUpperTriMat(Spatial_OI,(1+sqrt(1+4*2*size(handles.SignMat,1)))/2)'; tmp_DEG = sum(abs(tmp_MAT),1)/2; Factor_plots = 2*max(tmp_DEG); cla(handles.BrainPlot); PlotBrainGraph_Kmeans_withtitle(handles.BrainPlot,tmp_MAT,tmp_DEG,handles.CodeBook,0.2,... Factor_plots,Factor_plots,2,1,'hot','spring',1,0.5,[-1 1],... 'W10_Alpha001','W10_Alpha001'); end guidata(hObject, handles); function Slider_CreateFcn(hObject, eventdata, handles) if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor',[.9 .9 .9]); end guidata(hObject, handles); %% Save button function SaveButton_Callback(hObject, eventdata, handles) SM = handles.SignMat; save(handles.SaveName,'SM'); guidata(hObject,handles); %% Clear button function ClearButton_Callback(hObject, eventdata, handles) handles.NullType = 'Normal'; handles.IsISFCDataLoaded = 0; handles.IsNullLoaded = 0; handles.IsMovieLoaded = 0; handles.W = realmax; handles.TR = 1; handles.IsTREntered = 0; handles.IsWEntered = 0; handles.ISFC_Data = {}; handles.Null_Data = {}; handles.Alpha = 0.05; handles.NullThresh = {}; handles.SignMat = []; handles.IDX= []; handles.t_start = 0; handles.t_end = realmax; handles.range = [-1,1]; handles.SaveName = 'DefaultName'; cla(handles.ISFCPlot); cla(handles.ExcPlot); cla(handles.BrainPlot); set(handles.Slider,'Value',0); set(handles.Slider,'Min',0); set(handles.Slider,'Max',1); set(handles.WindowText,'Enable','off'); set(handles.WindowText,'BackgroundColor',240/255*[1 1 1]); WindowText_CreateFcn(handles.WindowText, eventdata, handles); set(handles.TRText,'Enable','off'); set(handles.TRText,'BackgroundColor',240/255*[1 1 1]); TRText_CreateFcn(handles.TRText, eventdata, handles); set(handles.StepText,'Enable','off'); set(handles.StepText,'BackgroundColor',240/255*[1 1 1]); StepText_CreateFcn(handles.StepText, eventdata, handles); set(handles.SaveText,'Enable','off'); set(handles.SaveText,'BackgroundColor',240/255*[1 1 1]); SaveText_CreateFcn(handles.SaveText, eventdata, handles); set(handles.PercentileText,'Enable','off'); set(handles.PercentileText,'BackgroundColor',240/255*[1 1 1]); PercentileText_CreateFcn(handles.PercentileText, eventdata, handles); guidata(hObject,handles); %% Window text entry function WindowText_Callback(hObject, eventdata, handles) % If the high-pass takes a reasonable value, then we validate it if (~isempty(str2double(get(hObject,'String')))) && ... (str2double(get(hObject,'String')) > 1) && ... (str2double(get(hObject,'String')) < size(handles.ISFC_Data{1},2)) handles.W = str2double(get(hObject,'String')); set(hObject,'BackgroundColor', [0.4 0.6 0.4]); handles.IsWEntered = 1; if handles.IsTREntered && handles.IsWEntered && handles.IsISFCDataLoaded handles.t_start = (handles.TR*handles.W)-1; handles.t_end = (size(handles.ISFC_Data{1},2)-1)*handles.TR + handles.t_start; set(handles.Slider,'Value',handles.t_start); set(handles.Slider,'Min',handles.t_start); set(handles.Slider,'Max',handles.t_end); end else set(hObject,'BackgroundColor', [0.93 0.84 0.84]); end guidata(hObject,handles); function WindowText_CreateFcn(hObject, eventdata, handles) set(hObject,'String','Enter window size...'); set(hObject,'FontAngle','italic'); guidata(hObject,handles); function WindowText_ButtonDownFcn(hObject, eventdata, handles) set(hObject,'Enable','on'); set(hObject,'String',''); set(hObject,'FontAngle','normal'); uicontrol(hObject); guidata(hObject,handles); %% Loading of codebook function MovieButton_Callback(hObject, eventdata, handles) % Selection of all the fMRI files [filename3,pathname3]=uigetfile({'*.*','All Files'},... 'Select null ISFC files...','MultiSelect','off'); % If the user has indeed entered files if ~isequal(filename3,0) || ~isequal(pathname3,0) load((fullfile(pathname3, filename3))); assignin('base','CodeBook', CodeBook); handles.CodeBook = CodeBook; handles.IsCodeBookLoaded = 1; end guidata(hObject,handles); %% TR text entry function TRText_Callback(hObject, eventdata, handles) % If the high-pass takes a reasonable value, then we validate it if (~isempty(str2double(get(hObject,'String')))) && ... (str2double(get(hObject,'String')) > 0) handles.TR = str2double(get(hObject,'String')); set(hObject,'BackgroundColor', [0.4 0.6 0.4]); handles.IsTREntered = 1; if handles.IsTREntered && handles.IsWEntered && handles.IsISFCDataLoaded handles.t_start = (handles.TR*handles.W)-1; handles.t_end = (size(handles.ISFC_Data{1},2)-1)*handles.TR + handles.t_start; set(handles.Slider,'Value',handles.t_start); set(handles.Slider,'Min',handles.t_start); set(handles.Slider,'Max',handles.t_end); end else set(hObject,'BackgroundColor', [0.93 0.84 0.84]); end guidata(hObject,handles); function TRText_CreateFcn(hObject, eventdata, handles) set(hObject,'String','Enter TR...'); set(hObject,'FontAngle','italic'); guidata(hObject,handles); function TRText_ButtonDownFcn(hObject, eventdata, handles) set(hObject,'Enable','on'); set(hObject,'String',''); set(hObject,'FontAngle','normal'); uicontrol(hObject); guidata(hObject,handles); %% Step text entry function StepText_Callback(hObject, eventdata, handles) % If the high-pass takes a reasonable value, then we validate it if (~isempty(str2double(get(hObject,'String')))) && ... (str2double(get(hObject,'String')) >= 1) handles.Step = str2double(get(hObject,'String')); set(hObject,'BackgroundColor', [0.4 0.6 0.4]); else set(hObject,'BackgroundColor', [0.93 0.84 0.84]); end guidata(hObject,handles); function StepText_CreateFcn(hObject, eventdata, handles) set(hObject,'String','Enter step size...'); set(hObject,'FontAngle','italic'); guidata(hObject,handles); function StepText_ButtonDownFcn(hObject,eventdata,handles) set(hObject,'Enable','on'); set(hObject,'String',''); set(hObject,'FontAngle','normal'); uicontrol(hObject); guidata(hObject,handles); %% Save text entry function SaveText_Callback(hObject, eventdata, handles) % If the high-pass takes a reasonable value, then we validate it if (~isempty(get(hObject,'String'))) handles.SaveName = get(hObject,'String'); set(hObject,'BackgroundColor', [0.4 0.6 0.4]); else set(hObject,'BackgroundColor', [0.93 0.84 0.84]); end guidata(hObject,handles); function SaveText_CreateFcn(hObject, eventdata, handles) set(hObject,'String','Enter save name...'); set(hObject,'FontAngle','italic'); guidata(hObject,handles); function SaveText_ButtonDownFcn(hObject, eventdata, handles) set(hObject,'Enable','on'); set(hObject,'String',''); set(hObject,'FontAngle','normal'); uicontrol(hObject); guidata(hObject,handles); diff --git a/Readme.rtf b/Readme.rtf new file mode 100644 index 0000000..1aaf93c --- /dev/null +++ b/Readme.rtf @@ -0,0 +1,18 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 + +\f0\fs24 \cf0 In this repository, you will find all the scripts necessary to leverage the inter-subject functional correlation approach described in Bolton et al. 2019 (JoVE). All graphical user interfaces were last tested on January 21st 2021, and were fully functional on the provided example data.\ +\ +JOVE_GUI1 enables to perform initial preprocessing steps on the functional data at hand (detrending, regression of nuisance variables), and to display the time courses following these steps.\ +\ +JOVE_GUI2 enables to perform atlasing into regional time courses, scrubbing and filtering at an appropriate cutoff for the analysis (as a function of the desired window length).\ +\ +JOVE_GUI3 enables to computes, in sliding window fashion, inter-subject functional correlation (ISFC) estimates. A bootstrapping process is conducted to improve robustness of the outcomes.\ +\ +JOVE_GUI4 thresholds the ISFC time courses from a naturalistic paradigm of interest, using either resting-state or phase-randomised time courses as null data.\ +\ +If there is anything unclear left, do not hesitate to contact us at thomas.bolton@epfl.ch for assistance.} \ No newline at end of file diff --git a/Utilities/Plotting/PlotBrainGraph_Kmeans_withtitle.m b/Utilities/Plotting/PlotBrainGraph_Kmeans_withtitle.m index 80b2fa4..5812c44 100755 --- a/Utilities/Plotting/PlotBrainGraph_Kmeans_withtitle.m +++ b/Utilities/Plotting/PlotBrainGraph_Kmeans_withtitle.m @@ -1,88 +1,88 @@ function [] = PlotBrainGraph_Kmeans_withtitle(h,CM,CC,CodeBook,T_conn,... Factor_SphereSize,Factor_Col,Exp_Sphere,View,Colormap_nodes,... Colormap_edges,Gamma,LinearWeight,CA,PT,title) % edges pp.doPlotConnections=1; pp.pruneTinyConnections=1; pp.pruningWeight=T_conn; pp.linearWeight=LinearWeight; pp.gamma=Gamma; pp.doColourCode=true; pp.cmapchoiceE=Colormap_edges; % nodes pp.doPlotDegreeSpheres=true;%** pp.myDSplotT=0; % this * 1/N is the threshold pp.showLabels=0; pp.cmapchoiceV=Colormap_nodes; % gray % Controls the exponent for the display of the spheres pp.e_matD_to_sphS=Exp_Sphere; pp.f_matD_to_sphS=1; % brain outline pp.bmesh_faceAlpha=0.2; % transparency % node size and color pp.FctForColSph=CC/Factor_Col; pp.FctForSizSph=CC/Factor_SphereSize; % Edge transparency pp.doAlpha = true; pp.alphagamma = 0.05; axes(h); hold(h,'on'); if ~isempty(CA) show_cm(CM,CodeBook.full,3,'gamma',pp.gamma,'FctForColSph',pp.FctForColSph,... 'linearWeight',pp.linearWeight,'showLabels',pp.showLabels,... 'createFigure',false,'doColourCode',pp.doColourCode,'doAlpha',pp.doAlpha,'alphagamma',pp.alphagamma,... 'cmapchoiceV',pp.cmapchoiceV,'cmapchoiceE',pp.cmapchoiceE,... 'doPlotConnections',pp.doPlotConnections,'doPlotDegreeSpheres',pp.doPlotDegreeSpheres,... 'bmesh_show',1,'bmesh_hemi','lr','bmesh_useConvexHull',false,... 'bmesh_convexHullOutlinePlanes','','FctForSizSph',pp.FctForSizSph,... 'bmesh_faceAlpha',pp.bmesh_faceAlpha,'pruneTinyConnections',pp.pruneTinyConnections,... 'pruningWeight',pp.pruningWeight,'e_matD_to_sphS',pp.e_matD_to_sphS,'f_matD_to_sphS', pp.f_matD_to_sphS,... 'plotDegreeSpheresOnlyAboveThreshold',pp.myDSplotT,... 'showTopNlabels',0,'txtPosOffset',5*[1 1 1],'ColAxis',CA,... 'showTopNlabelsBy','vertexW','useShortNames',0); else show_cm(CM,CodeBook.full,3,'gamma',pp.gamma,'FctForColSph',pp.FctForColSph,... 'linearWeight',pp.linearWeight,'showLabels',pp.showLabels,... 'createFigure',false,'doColourCode',pp.doColourCode,'doAlpha',pp.doAlpha,'alphagamma',pp.alphagamma,... 'cmapchoiceV',pp.cmapchoiceV,'cmapchoiceE',pp.cmapchoiceE,... 'doPlotConnections',pp.doPlotConnections,'doPlotDegreeSpheres',pp.doPlotDegreeSpheres,... 'bmesh_show',1,'bmesh_hemi','lr','bmesh_useConvexHull',false,... 'bmesh_convexHullOutlinePlanes','','FctForSizSph',pp.FctForSizSph,... 'bmesh_faceAlpha',pp.bmesh_faceAlpha,'pruneTinyConnections',pp.pruneTinyConnections,... 'pruningWeight',pp.pruningWeight,'e_matD_to_sphS',pp.e_matD_to_sphS,'f_matD_to_sphS', pp.f_matD_to_sphS,... 'plotDegreeSpheresOnlyAboveThreshold',pp.myDSplotT,... 'showTopNlabels',0,'txtPosOffset',5*[1 1 1],... 'showTopNlabelsBy','vertexW','useShortNames',0); end hold(h,'off'); %colorbar; axis off axis tight; if View==1, az=0; el=90; cam='right'; vview='ax'; elseif View==2, az=90; el=0; cam='right'; vview='sag'; else az=0; el=0; cam='left'; vview='cor'; end view(az,el); camlight(cam); %disp('done'); - print('-depsc',[PT,'_',title]); - savefig([PT,'_',title]); + %print('-depsc',[PT,'_',title]); + %savefig([PT,'_',title]); end \ No newline at end of file diff --git a/Utilities/Plotting/show_FSmesh.m b/Utilities/Plotting/show_FSmesh.m index 74ce7f4..01b2b0a 100755 --- a/Utilities/Plotting/show_FSmesh.m +++ b/Utilities/Plotting/show_FSmesh.m @@ -1,143 +1,144 @@ function myH=show_FSmesh(hemi,meshType,varargin) % SHOW_FSMESH show a freesurfer 3-dimensional hemisphere mesh % % IN: % hemi - a char array containing 'l','r', or 'lr', indicating which hemi- % sphere to display % meshtype - a char array containing mesh type ('white') % 'faceColor': ColorSpec - colour for the faces of the brain mesh % triangles % 'faceAlpha': scalar between 0 and 1 - alpha transparency value to % use for brain mesh triangles (0: fully transparent, 1: fully % opaque) % 'edgeColor': ColorSpec - colour for the edges of the brain mesh % triangles % 'edgeAlpha': scalar between 0 and 1 - alpha transparency value to % use for brain mesh triangle edges (0: fully transparent, 1: fully % opaque) % 'reducePatchVal': scalar, fraction of patches to keep - increasing % from the default value may crash Matlab due to a bug in Matlab. % OUT: % myH: a vector of handles to patch objects % % v1.0 Nov 2009 Jonas Richiardi % - inital release based on read_surf/trisurf snippet by Markus Gschwind % v1.1 2009 Dec 10 Jonas Richiardi % - code clean up % - fix for alpha values crashing in 2-hemispheres display (known bug % 484445): use subdivision algorithm to "downsample" Delaunay triangulation % This is a better solution in this case than those suggested in % http://www.mathworks.com/support/bugreports/484445 % v1.2 2010 Jul Jonas Richiardi % - fix a bug due to reducepatch does not setting CData and FaceVertexCData % after reducing the vertex and face count (despite the doc saying it does % not set the Faces and Vertices properties). Now CData and FaceVertexCData % are in sync. [createFigure,FaceColor,EdgeColor,FaceAlpha,EdgeAlpha,useConvexHull,... reducePatchVal]=process_options(varargin,... 'createFigure',true,'FaceColor',[0.8 0.8 0.8],'EdgeColor',[0.5 0.5 0.5],... 'FaceAlpha',0.2,'EdgeAlpha',0.05,'useConvexHull',false,'reducePatchVal',... 0.015); %% sanity check hemiSupported={'l','r','lr'}; meshTypeSupported={'white'}; if all(cellfun('isempty',strfind(hemiSupported,hemi))) error(['Unsupported hemi type: ' hemi]); end if all(cellfun('isempty',strfind(meshTypeSupported,meshType))) error(['Unsupported mesh type: ' meshType]); end %% setup host-specific options and paths -location=whereAmIRunning; -if strcmp(location,'jmac') - % set root path to FreeSurfer application - FSROOTPATH='/Applications/freesurfer/'; -else - error('Please modify whereAmIRunning.m for your own settings'); -end -% generate path where to find the surface mesh files -FSSURFPATH=fullfile(FSROOTPATH,'subjects','fsaverage','surf'); - -if exist('read_surf')~=2 - addpath(fullfile(FSROOTPATH,'matlab')); -end +% location=whereAmIRunning; +% if strcmp(location,'jmac') +% % set root path to FreeSurfer application +% FSROOTPATH='/Users/TiBiUan/Desktop/freesurfer/'; +% %FSROOTPATH='/Applications/freesurfer/'; +% else +% error('Please modify whereAmIRunning.m for your own settings'); +% end +% % generate path where to find the surface mesh files +% FSSURFPATH=fullfile(FSROOTPATH,'subjects','fsaverage','surf'); +% +% if exist('read_surf')~=2 +% addpath(fullfile(FSROOTPATH,'matlab')); +% end if (createFigure==true) figure; end hold on; %% load surfaces % surfaces are encoded by Delaunay triangulation (region-adjacency graph % of Voronoi tesselation - Delaunay graph is the dual of the Voronoi % diagram (Okabe et al 200)) % faces is the m x 3 triangulation matrix - the set of simplices (triangle) % that make the triangulation. Each row (in simplex-vertex format) encodes % the three vertices a triangular face via indexing into a matrix containing % the 3D space location of vertices % e.g. 1 4 2 says that this triangles is made up of vertices 1, 4, and 2, % whose 3D spatial locations are found in the vertices matrix. myH=zeros(numel(hemi),1); for h=1:numel(hemi) if strcmp(hemi(h),'r') f_surf=['rh.' meshType]; elseif strcmp(hemi(h),'l') f_surf=['lh.' meshType]; else error('Wrong hemi specification. How on earth did you trigger this code path?'); end % read surface using freesurfer function % note we could access matlab functionality for the TriRep class via % trirep(faces+,vertices(:,1)... etc) - [vertices,faces]=read_surf(fullfile(FSSURFPATH,f_surf)); + [vertices,faces]=read_surf(fullfile(pwd,f_surf)); vertices=single(vertices); % save memory nVertices = size(vertices,1); if (useConvexHull==true) disp('Computing convex hull...'); myConvHull = convhulln(double(vertices)); myH(h)=trisurf(myConvHull+1,vertices(:,1),vertices(:,2),vertices(:,3),... 'FaceColor',FaceColor,'EdgeColor',EdgeColor); %disp('Doing mesh subdivision...'); %reducepatch(myH(h),0.05); else % plot Delaunay triangulated mesh myH(h)=trisurf(faces+1,vertices(:,1),vertices(:,2),vertices(:,3),... ones(nVertices,1),'FaceColor',FaceColor,'EdgeColor',EdgeColor); % do subdivision to reduce number of faces % another solution would be to set(gca,'DrawMode','Fast'); as per % 484445 bug report %disp('Doing mesh subdivision...'); reducepatch(myH(h),reducePatchVal); % higher may cause crash, still too many faces % CData and FaceVertexCData are now desynchronised, so fix them % manually nf=get(myH(h),'Faces'); nv=get(myH(h),'Vertices'); % 1) fix CData to be 3xsize(Faces,1), all ones or actually FaceColor set(myH(h),'CData',repmat(FaceColor,3,size(nf,1))); % 2) fix FaceVertexCData to be nVertices x 1 set(myH(h),'FaceVertexCData',repmat(FaceColor,size(nv,1),1)); end xlabel('left-right'); ylabel('posterior-anterior'); zlabel('ventral-dorsal'); clear vertices faces; if (h==1) axis equal; view(0,90); end end %set(gca,'DrawMode','Fast'); % set transparency now, with reduced number of faces (does not crash) for h=1:numel(hemi) set(myH(h),'EdgeAlpha',EdgeAlpha,'FaceAlpha',FaceAlpha,... 'DiffuseStrength',1,'SpecularStrength',0); end diff --git a/Utilities/Preprocessing/RemoveNaNRegions.m b/Utilities/Preprocessing/RemoveNaNRegions.m new file mode 100644 index 0000000..469095a --- /dev/null +++ b/Utilities/Preprocessing/RemoveNaNRegions.m @@ -0,0 +1,43 @@ +%% This function verifies whether a given atlas time course is acceptable +% or not +% +% Inputs: +% +% - TCin is the input cell array containing the data of each subject in a +% cell (of size n_ROI x n_timepoints) +% +% Outputs: +% +% - TCout is the same array, having removed the bad regional time courses +% - idx_toremove summarizes which regional indices have been removed +% +% Written by Thomas Bolton, last checked on July 24th +function [TCout,idx_toremove] = RemoveNaNRegions(TCin) + + % Indices of the ROIs where in at least one subject, there are NaN + % values + idx_toremove = []; + + n_ROI = size(TCin,1); + + % If there is at least a NaN value in a given time course, we include + % it in the ones to remove + if ~isempty(TCin) + for j = 1:n_ROI + if(sum(isnan(TCin(j,:))) > 0) + idx_toremove = [idx_toremove,j]; + end + end + end + + % Makes each ROI appear only once in the vector + idx_toremove = unique(idx_toremove); + + % Only keeps the time courses that were deemed OK by the check + if ~isempty(TCin) + TCout = TCin(~ismember(1:n_ROI,idx_toremove),:); + else + TCout = NaN; + end + +end \ No newline at end of file diff --git a/lh.white b/lh.white new file mode 100755 index 0000000..966f93b Binary files /dev/null and b/lh.white differ diff --git a/rh.white b/rh.white new file mode 100755 index 0000000..11f8fca Binary files /dev/null and b/rh.white differ