diff --git a/Analysis/Build_Connectivity_Matrix.m b/Analysis/Build_Connectivity_Matrix.m deleted file mode 100755 index 50f03c3..0000000 --- a/Analysis/Build_Connectivity_Matrix.m +++ /dev/null @@ -1,23 +0,0 @@ -%% This function constructs a connectivity matrix from the indices of -% cluster assignment -function [M] = Build_Connectivity_Matrix(IDX,tmp_ss,type,n_items) - - IDX_full = zeros(n_items,1); - - switch type - case 'items' - IDX_full(tmp_ss) = IDX; - case 'dims' - IDX_full = IDX; - end - - M = zeros(n_items,n_items); - - for i = 1:length(IDX_full) - for j = 1:length(IDX_full) - if (IDX_full(i) == IDX_full(j)) && (IDX_full(i) > 0) - M(i,j) = 1; - end - end - end -end \ No newline at end of file diff --git a/Analysis/CAPToNIFTI.m b/Analysis/CAPToNIFTI.m deleted file mode 100755 index 51622ba..0000000 --- a/Analysis/CAPToNIFTI.m +++ /dev/null @@ -1,29 +0,0 @@ -%% Converts CAPs (matlab matrix) into NIFTI files -% CAP must have size n_CAPs x n_voxels -function [] = CAPToNIFTI(CAP,mask,brain_info,savedir,savename) - - % Number of CAPs - n_CAPs = size(CAP,1); - - % Voxel size - voxel_size = diag(brain_info.mat); - voxel_size = voxel_size(1:end-1)'; - - voxel_shift = brain_info.mat(:,4); - voxel_shift = voxel_shift(1:end-1)'; - - % Converts each CAP into a 3D volume - for i = 1:n_CAPs - - tmp = CAP(i,:); - V = zeros(brain_info.dim); - V(mask) = tmp; - - tmp_NIFTI = make_nii(V,voxel_size,-voxel_shift./voxel_size); - - tmp_NIFTI.hdr.dime.datatype=64; - tmp_NIFTI.hdr.dime.bitpix=64; - - save_nii(tmp_NIFTI,fullfile(savedir,[savename,'_CAP',num2str(i),'.nii'])); - end -end \ No newline at end of file diff --git a/Analysis/CAP_AddToLog.m b/Analysis/CAP_AddToLog.m deleted file mode 100755 index c2e3e2f..0000000 --- a/Analysis/CAP_AddToLog.m +++ /dev/null @@ -1,19 +0,0 @@ -% Displays a message specifying what command is currently being run, and -% saves the same command and relevant information into a text file -function [Log] = CAP_AddToLog(Log,new_s,Params,Params_name) - - n = length(Log); - Log{n+1}{1} = [' ']; - %Log{n+1}{1} = [date,'/',num2str(round(hour(now))),'/',num2str(round(minute(now))),'/',num2str(round(second(now)))]; - Log{n+1}{2} = new_s; - - disp(new_s); - - % If we also want to save parameters, we do so - if nargin > 2 - for n2 = 1:length(Params) - Log{n+1}{n2+2} = [Params_name{n2},': ',num2str(Params{n2})]; - disp(Log{n+1}{n2+2}); - end - end -end \ No newline at end of file diff --git a/Analysis/CAP_AssignFrames.m b/Analysis/CAP_AssignFrames.m deleted file mode 100755 index 812f777..0000000 --- a/Analysis/CAP_AssignFrames.m +++ /dev/null @@ -1,14 +0,0 @@ -function [i] = CAP_AssignFrames(Cp,XON,d,T) - - % Value of correlation below which 5% of all values lie (so gives an - % estimate of a 'bad correlation for a trace belonging to a cluster' - CT = prctile(d,T); - - % cluster assignment in young - r = corr(Cp',XON); - [c,i] = max(r); - - % If the correlation value is too low (below threshold), the index is set - % to a new non-existing group - i(c... - 3 && sum(cell2mat(cellfun(@(x) size(x,1) == size(TC{1},1) && ... - size(x,2) == size(TC{1},2),TC,'un',0))) == size(TC,2) - - % If the dimensions of FD fit the dimensions of TC... - if size(FD,1) == size(TC{1},1) && size(FD,2) == size(TC,2) - - % If the dimensions of the mask fit the rest... - if size(mask,2) == 1 && sum(mask,1) == size(TC{1},2) - - % If the dimensions of the brain info are consistant... - if isfield(BI,'dim') && isfield(BI,'mat') && size(BI.mat,1) == 4 && size(BI.mat,2) == 4 && size(BI.dim,1) == 1 && size(BI.dim,2) == 3 - - % Then, everything is OK ! - IsOK = 1; - Problems = 'No problem !!'; - else - Problems = 'Inconsistant brain information dimensions'; - end - else - Problems = 'Inconsistant mask dimensions compared to time courses'; - end - else - Problems = 'Inconsistant dimensions between time courses and motion file'; - end - - else - Problems = 'Inconsistant time courses dimensions'; - end - - -end \ No newline at end of file diff --git a/Analysis/CAP_V2V.m b/Analysis/CAP_V2V.m deleted file mode 100755 index 5cabfac..0000000 --- a/Analysis/CAP_V2V.m +++ /dev/null @@ -1,41 +0,0 @@ -function Out=CAP_V2V(In,In_dim,In_mat,Out_dim,Out_mat) -% map voxels in the space of input volume to voxels in the space -% of output volumes -% Out_fn: uses only header info -% -% v1.0 Jonas Richiardi -% - initial release, based on code by Dimitri Van De Ville and Jonas -% Richiardi - -% Out is filled with zeros and has the size of the output file -Out=zeros(Out_dim); - -% generate all coordinates in output space -[x1,x2,x3]=ndgrid(1:Out_dim(1),1:Out_dim(2),1:Out_dim(3)); -idx=1:numel(Out); % map all voxels - -% take every voxel in the volume spanned by the output images, -% compute its real-world position in mm, then map input image - -oobList=zeros(0,4); % list of out-of-bound input voxels - -for iter=1:length(idx), - oob=false; - % recover world-space position of this voxel in mm from affine - % transform matrix - mm=Out_mat*[x1(idx(iter)) x2(idx(iter)) x3(idx(iter)) 1]'; - % convert this position into index of the closest structural voxel - vx=round(In_mat\[mm(1) mm(2) mm(3) 1]'); - vx(vx<=0)=1; - vxOri=vx; - % remap out-of-bounds voxels to last - if vx(1)>In_dim(1), vx(1)=In_dim(1); oob=true; end - if vx(2)>In_dim(2), vx(2)=In_dim(2); oob=true; end - if vx(3)>In_dim(3), vx(3)=In_dim(3); oob=true; end - if (oob==true), oobList(end+1,:)=vxOri; end - % idx(iter): current voxel - Out(idx(iter))=In(vx(1),vx(2),vx(3)); - if any(Out(idx(iter))<0) %Out - warning('mapV2V:negativeVal',['Negative voxel values at ' num2str(iter)]); - end -end; \ No newline at end of file diff --git a/Analysis/CAP_find_activity.m b/Analysis/CAP_find_activity.m deleted file mode 100755 index 744299d..0000000 --- a/Analysis/CAP_find_activity.m +++ /dev/null @@ -1,156 +0,0 @@ -%% Finds the moments of (de)activation in a group of fMRI subjects -% Inputs -% tcvox: cell aray with a seed signal in each cell (time points x masked voxels) -% seed: masks for the seeds used (masked voxels x n_seed) -% T: threshold for the retention of active or inactive frames -% FDall: framewise displacement traces for all subjects (time points x n_subjects) -% Mot_thresh: threshold (in mm) to use for scrubbing -% -% Outputs -% Xonp: cell array (each cell dimension masked voxels x n_retained_frames) -% for active frames brain patterns -% p: 5xn_subject matrix with percentages of scrubbed frames, scrubbed and -% active frames, scrubbed and inactive frames, retained frames for active -% analysis and retained frames for inactive analysis -function [Xonp,p,Indices,idx_sep_seeds] = CAP_find_activity(tcvox,seed,T,FDall,Mot_thresh,SelMode,SeedType,SignMat,is_SS) - - % Contains the indices (logical) of the selected frames for each seed - % subcase - idx_sep_seeds = nan(size(FDall,1),size(FDall,2),size(seed,2)); - - % Computes the indices of the peak values that must be excluded. If we - % go above threshold for motion, we censor the current frame, but also - % the one just before and the one just after - flag = FDall>Mot_thresh; - flag2 = circshift(flag,[1 0]); - flag3 = circshift(flag,[-1 0]); - flag = flag+flag2+flag3; - flag(flag>1)=1; - - % We want to store the indices of scrubbed frames and return it later - Indices.scrubbed = logical(flag); - - % Same for the retained frames - switch SeedType - case 'Intersection' - Indices.kept.active = logical(zeros(size(FDall,1),size(FDall,2))); - otherwise - Indices.kept.active = logical(ones(size(FDall,1),size(FDall,2))); - end - - - % Each cell of flag will contain a time x 1 vector of logicals (1 if - % the frame is to be censored, 0 otherwise) - flag = num2cell(flag,1); - clear flag2 - clear flag3 - - % 1 x n_subject vector containing the percentage of scrubbed frames (throughout the whole scan) - p_scrubbed = cell2mat(cellfun(@(x) sum(x)/length(x)*100, flag,'un',0)); - - % If we wanted an average seed, we can either be in the - % subject-specific seed case (we know there is only one seed type), or - % in the case with several different seeds (up to three) to average - % together - if strcmp(SeedType,'Average') - - % According to the two options, we compute the seed time courses - % for each subject. - if ~is_SS - S = CAP_get_seed_traces(tcvox,logical(sum(seed,2)),SignMat(1,:),is_SS); - else - S = CAP_get_seed_traces(tcvox,seed,SignMat(1,:),is_SS); - end - - % Selects the indices appropriately (threshold or percentage - % selection cases) - if strcmp(SelMode,'Threshold') - - xindp = cellfun(@(x) x>T, S, 'un', 0); - - elseif strcmp(SelMode,'Percentage') - - T_per_act = cellfun(@(x) prctile(x,100-T), S, 'un', 0); - xindp = cellfun(@(x,y) x>y, S,T_per_act, 'un', 0); - - else - errordlg('Should never happen...'); - end - - % flag now contains the traces with high activity AND high motion - flag_active = cellfun(@(x,y) x & y,xindp, flag,'un',0); - - % Vector (1xn_subj) with the percentage of traces removed because of too high - % motion and being selected as active - p_scrubactive = cell2mat(cellfun(@(x) sum(x)/length(x)*100, flag_active,'un',0)); - - % My indices of active/inactive frames now contain only the non - % corrupted frames - xindp = cellfun(@(x,y) x & ~y, xindp,flag_active,'un',0); - - Indices.kept.active = cell2mat(xindp); - idx_sep_seeds(:,:,1) = cell2mat(xindp); - - % If Union or Intersection was wanted instead, then computations for - % different seeds need to be carried independently - else - for idx = 1:size(seed,2) - - S = CAP_get_seed_traces(tcvox,logical(seed(:,idx)),SignMat(idx,:),is_SS); - - if strcmp(SelMode,'Threshold') - - % Computes the indexes at which we have a seed activity of interest - xindp = cellfun(@(x) x>T, S, 'un', 0); - - elseif strcmp(SelMode,'Percentage') - - % Computes the threshold that corresponds to P percent frames for - % each subject - T_per_act = cellfun(@(x) prctile(x,100-T), S, 'un', 0); - - % And then uses this to select frames - xindp = cellfun(@(x,y) x>y, S,T_per_act, 'un', 0); - - else - errordlg('Should never happen...'); - end - - % flag now contains the traces with high activity AND high motion - flag_active = cellfun(@(x,y) x & y,xindp, flag,'un',0); - - % Vector (1xn_subj) with the percentage of traces removed because of too high - % motion and being selected as active - p_scrubactive = cell2mat(cellfun(@(x) sum(x)/length(x)*100, flag_active,'un',0)); - - % My indices of active/inactive frames now contain only the non - % corrupted frames - xindp = cellfun(@(x,y) x & ~y, xindp,flag_active,'un',0); - - % Updates the indices of the frames to keep - switch SeedType - case 'Union' - - Indices.kept.active = (Indices.kept.active) & cell2mat(xindp); - - case 'Intersection' - - Indices.kept.active = (Indices.kept.active) | cell2mat(xindp); - end - - idx_sep_seeds(:,:,idx) = cell2mat(xindp); - - end - end - - % Each cell contains the frames selected as active or as inactive (if - % inactive, the sign is reversed, i.e. inactivation is a positive - % signal). Size: masked voxels x n_retained_frames - Xonp = cellfun(@(x,y) x(y,:)',tcvox,num2cell(Indices.kept.active,1),'un',0); - - % Percentage of active and inactive frames retained per subject - p_active = cell2mat(cellfun(@(x) size(x,2)/size(FDall,1)*100, Xonp,'un',0)); - - % Matrix containing all the interesting probabilities - p = [p_scrubbed; p_scrubactive; p_active]; -end \ No newline at end of file diff --git a/Analysis/CAP_get_seed_traces.m b/Analysis/CAP_get_seed_traces.m deleted file mode 100755 index 62ddd93..0000000 --- a/Analysis/CAP_get_seed_traces.m +++ /dev/null @@ -1,40 +0,0 @@ -%% From the raw voxelwise data, computes a spatially averaged seed signal -% tcvox is a cell array (each cell has time x masked voxels dimension) -% seed is the seed mask (masked voxel x 1) -% S is a cell array (each cell is a time x 1 vector) -function [S] = CAP_get_seed_traces(tcvox,seed,SignMat,is_SS) - - % In the case when we have the same seed across subjects, we use it - % throughout for the computations - if ~is_SS - if SignMat(1) - % Computation of the spatially averaged seed signal - S = cellfun(@(x) mean(x(:,seed),2), tcvox, 'un', 0); - elseif SignMat(2) - % Computation of the spatially averaged seed signal - S = cellfun(@(x) (-1)*mean(x(:,seed),2), tcvox, 'un', 0); - else - errordlg('PROBLEM WITH SIGN MAT !!!'); - end - - % In the case when we have subject-specific seeds, we will compute the - % seed signal separately for each subject - else - - seed_cell = {}; - - for s = 1:size(seed,2) - seed_cell{s} = seed(:,s); - end - - if SignMat(1) - % Computation of the spatially averaged seed signal - S = cellfun(@(x,y) mean(x(:,y),2), tcvox, seed_cell, 'un', 0); - elseif SignMat(2) - % Computation of the spatially averaged seed signal - S = cellfun(@(x,y) (-1)*mean(x(:,y),2), tcvox, seed_cell, 'un', 0); - else - errordlg('PROBLEM WITH SIGN MAT !!!'); - end - end -end \ No newline at end of file diff --git a/Analysis/CAP_mask4kmeans.m b/Analysis/CAP_mask4kmeans.m deleted file mode 100755 index 5e9b035..0000000 --- a/Analysis/CAP_mask4kmeans.m +++ /dev/null @@ -1,53 +0,0 @@ -%% This function sets to zero the value of the voxels that are judged noise -% X is the data to mask (n_vox x n_frames) -% topP and bottomP are the percentages of data retained (top and lowest -% activity ones respectively) by the masking procedure -% n_cv is the number of voxels in a group that must be reached for that -% group not to be masked -function [Y] = CAP_mask4kmeans(X,topP,bottomP,n_cv,mask,ai) - - % We want to exit with a matrix of the same size as X, for which each - % frame has had its noise-related elements set to zero - Y = zeros(size(X)); - - % For all frames... - for i = 1:size(X,2) - % We sort in descending and ascending order to get the indexes of - % the considered frame matching the top percentage of high or low - % activity - [~,Isorted] = sort(X(:,i),'descend'); - [~,Isortedrev] = sort(X(:,i),'ascend'); - - % Contains the indexes of all the points with activity of interest, - % both high and low - I = [Isorted(1:round(topP/100*length(Isorted)))',Isortedrev(1:round(bottomP/100*length(Isortedrev)))']; - - % If the elements of the frame belong to the indexes, X_binary has - % the corresponding entry set to 1. Else, it is set to 0 - X_binary = ismember(1:length(X(:,i)),I); - - % To perform the opening operation, we must convert X_binary to a - % 3D volume - temp = nan(size(mask)); - temp(mask) = X_binary; - temp(isnan(temp)) = 0; - temp = reshape(temp,ai.dim); - - % At this state, temp is a binary image on which the small clusters - % of neigboring voxels retained (less than n_cv neighbours) have - % been removed - temp = bwareaopen(temp,n_cv); - - % We convert temp back to a 1D vector, and conserve only the - % elements of interest (70700 voxels) with 0 and 1 respectively - % denoting 'not to consider for k-means' and 'to consider for - % k-means' - temp = temp(:); - Y(:,i) = temp(mask); - end - - % Y is a binary matrix of same size as X; multiplying element by - % element, we set to zero the elements of X that we want to neglect for - % clustering - Y = Y.*X; -end \ No newline at end of file diff --git a/Analysis/Compute_Metrics.m b/Analysis/Compute_Metrics.m deleted file mode 100755 index fe93dc0..0000000 --- a/Analysis/Compute_Metrics.m +++ /dev/null @@ -1,120 +0,0 @@ -%% This function computes all the metrics of the CAP analysis framework -% Inputs: -% -% - idx depicts the indices of the frames that have been clustered (the -% cluster to which they belong) -% - xindp1 depicts the indices of the frames that have been selected as -% activation moments -% - xindn1 is the same for deactivation time points -% - sind depicts scrubbed frames -% - n_clusters is the number of clusters used for state disentanglement -% - TR is the TR of the experiment -% - CAPType denotes the type of clustering that has been chosen (only -% activation, only deactivation, or both) -% -% Outputs: -% -% - TPM (n_subjects x n_frames) is the state sequence matrix -% - Counts (-> raw/frac -> scrubbed/baseline/state: n_subj x n_states) -% contains the counts (raw and normalized) -% - Number (n_subj x n_seqtype) with sequence type: scrub, act/deact/-, -% baseline, then states -% - Avg_Duration (n_subj x n_seqtype) contains the average duration of a -% state for a subject -% - Duration (n_subj array of size 1 x n_sequences) contains the duration -% of the state sequences for each subject -% - TM (n_seqtype x n_seqtype) encompasses the transitions that exist -function [TPM,Counts,Number,Avg_Duration,Duration,TM] = Compute_Metrics(idx,xindp1,sind,n_clusters,TR) - - % Number of subjects - n = size(xindp1,2); - - % Number of frames - n_frames = size(xindp1,1); - - % This will contain our transitions - TM = zeros(n_clusters+2,n_clusters+2,n); - - % Cumulative frame counts across subjects (1xn_subjects) for frames - dd2p = cumsum([1,sum(xindp1,1)]); - - % TPM will contain the sequence of states for all subjects - TPM = zeros(n,n_frames); - - % Computation of the state matrix - - % Filling of TP for each subject - for i = 1:n - % We set scrubbed time points at -1 - TPM(i,xindp1(:,i)) = idx(dd2p(i):dd2p(i+1)-1)'; - TPM(i,sind(:,i)) = -1; - end - - % Computation of the counts - - % We first compute the amount and percentage of scrubbed frames - % Raw counts - Counts.raw.scrubbed = sum(TPM == -1,2); - Counts.raw.notpicked = sum(TPM == 0,2); - - % Normalized counts - Counts.frac.scrubbed = 100*sum(TPM == -1,2)./sum(TPM,2); - Counts.frac.notpicked = 100*sum(TPM == 0,2)./sum(TPM,2); - - for idx_state = 1:n_clusters - Counts.raw.state(:,idx_state) = sum(TPM == idx_state,2); - Counts.frac.state(:,idx_state) = 100*sum(TPM == idx_state,2)./sum(TPM > 0,2); - end - - % Computation of state number and duration - - % We now want to compute dynamical metrics for each subject - for j = 1:n - - % Marks the indices when we switch state (last element is idx_max+1) - TS = find(diff([-1337 TPM(j,:) -1337])~=0); - - % Length of each period (in s.) - Length = diff(TS)*TR; - - % Starting index of each period (in s., first element at 0 s.) - StartTime = (TS(1:end-1)-1)*TR; - - % Type of each period - SeqType = TPM(j,TS(1:end-1)); - - % Number of different states that have been entered - n_Periods = length(Length); - - % We now want to actually count how many times we enter each state, - % and how long we stay in each state - n_Sequences = zeros(1,n_clusters+2); - length_Sequences = cell(1,n_clusters+2); - - % We go through all sequences - for i = 1:n_Periods - - % We increase the appropriate counter - n_Sequences(SeqType(i)+2) = n_Sequences(SeqType(i)+2)+1; - length_Sequences{SeqType(i)+2} = [length_Sequences{SeqType(i)+2},Length(i)]; - end - - for ns = 1:n_clusters+2 - % Average duration of states - avg_length_Sequences(ns) = mean(length_Sequences{ns}); - end - - Duration{j} = length_Sequences; - Number(j,:) = n_Sequences; - Avg_Duration(j,:) = avg_length_Sequences; - - % For each state transition, we increment properly the matrix of - % transitions - for k = 1:n_frames-1 - TM(TPM(j,k)+2,TPM(j,k+1)+2,j) = TM(TPM(j,k)+2,TPM(j,k+1)+2,j) + 1; - end - end - - % We normalize the matrix by all the transitions - TM = TM/(n_frames-1); -end \ No newline at end of file diff --git a/Analysis/ConsensusClustering.m b/Analysis/ConsensusClustering.m deleted file mode 100755 index 67195f7..0000000 --- a/Analysis/ConsensusClustering.m +++ /dev/null @@ -1,106 +0,0 @@ -%% This function performs consensus clustering over a range of K values -% The goal is to provide a measure of how good each value of K is -% -% Inputs: -% - X is the data matrix (n_DP x n_DIM) -% - K_range is the range of K values to examine -% - Subsample_type defines how subsampling is done: across items (data -% points) if 'items', and across dimensions if 'dimensions' -% - Subsample_fraction is the fraction of the original data points, or -% dimensions, to keep for a given fold -% - n_folds is the number of folds over which to run -function [Consensus_ordered] = ConsensusClustering(X,K_range,Subsample_type,Subsample_fraction,n_folds,DistType) - - % Number of data points - n_items = size(X,1); - - % Number of dimensions - n_dims = size(X,2); - - Consensus = zeros(n_items,n_items,length(K_range)); - Consensus_ordered = zeros(n_items,n_items,length(K_range)); - - % Loop over all K values to assess - for k = 1:length(K_range) - - disp(['Running consensus clustering for K = ',num2str(K_range(k)),'...']); - - % Connectivity matrix that will contain 0s or 1s depending on whether - % elements are clustered together or not - M = zeros(n_items,n_items,n_folds); - I = zeros(n_items,n_items,n_folds); - - disp('before h loop'); - - % Loops over all the folds to perform clustering for - for h = 1:n_folds - - switch Subsample_type - case 'items' - - % Number of items to subsample - n_items_ss = floor(Subsample_fraction*n_items); - - % Does the subsampling - [X_ss,tmp_ss] = datasample(X,n_items_ss,1,'Replace',false); - - % Vector - I_vec = zeros(n_items,1); - I_vec(tmp_ss) = 1; - - % Constructs the indicator matrix - for i = 1:length(I_vec) - for j = 1:length(I_vec) - if (I_vec(i) == I_vec(j)) && (I_vec(i) > 0) - I(i,j,h) = 1; - end - end - end - - case 'dims' - - % Number of dimensions to subsample - n_dims_ss = floor(Subsample_fraction*n_dims); - - % Does the subsampling - [X_ss,tmp_ss] = datasample(X,n_dims_ss,2,'Replace',false); - - % Constructs the indicator matrix - I(:,:,h) = ones(n_items,n_items); - - otherwise - errordlg('PROBLEM IN TYPE OF SUBSAMPLING'); - end - - % Does the clustering (for now, only with k-means), so that IDX - % contains the indices for each datapoint - IDX = kmeans(X_ss,K_range(k),'Distance',DistType,'Replicates',1,'Start','uniform'); - - % Builds the connectivity matrix - M(:,:,h) = Build_Connectivity_Matrix(IDX,tmp_ss,Subsample_type,n_items); - - clear I_vec - clear X_ss - clear tmp_ss - clear IDX - end - - % Constructs the consensus matrix for the considered K - Consensus(:,:,k) = sum(M,3)./sum(I,3); - - tree = linkage(squeeze(1-Consensus(:,:,k)),'average'); - - % Leaf ordering to create a nicely looking matrix - leafOrder = optimalleaforder(tree,squeeze(1-Consensus(:,:,k))); - - % Ordered consensus matrix - Consensus_ordered(:,:,k) = Consensus(leafOrder,leafOrder,k); - - clear leafOrder - clear Dist_vec - clear test - clear IDX - clear M - clear I - end -end \ No newline at end of file diff --git a/Analysis/Run_Clustering.m b/Analysis/Run_Clustering.m deleted file mode 100755 index e812dff..0000000 --- a/Analysis/Run_Clustering.m +++ /dev/null @@ -1,121 +0,0 @@ -function [CP2,Disp,Std_Clusters,idx,d,sfrac] = Run_Clustering(XONn,n_clusters,mask,brain_info,maskP,maskN,n_rep,idx_sep_seeds,SeedType) - - % Number of seeds - n_seeds = size(idx_sep_seeds,3); - - % Number of subjects - n_subjects = size(idx_sep_seeds,2); - - % Number of possible seed combinations - switch n_seeds - case 1 - n_combos = 1; - combvec = [1]; - case 2 - n_combos = 3; - combvec = [1 0; 0 1; 1 1]; - case 3 - n_combos = 7; - combvec = [1 0 0; 0 1 0; 0 0 1; 1 1 0; 0 1 1; 1 0 1; 1 1 1]; - otherwise - errordlg('PROBLEM AT SEED FRACTIONS'); - end - - % Will contain the fraction of frames linked to a given seed (if using - % the 'Intersection' method) - sfrac = zeros(n_subjects,n_clusters,n_combos); - - % 'Filtering so that we only use the largest activation and deactivation - % spots for clustering - XONn_filtered = CAP_mask4kmeans(XONn,maskP,maskN,6,mask,brain_info); - - % Rows datapoints, columns variable (so here every 70700 activation is - % a datapoint) - % idx will contain 1462 elements (the index of the cluster to which the - % considered datapoint belongs - [idx,CP] = kmeans(XONn_filtered',n_clusters,'distance','correlation','replicates',n_rep,'empty','drop','maxiter',100,'Display','iter'); - - % idx2counts is of size K (number of clusters) and has the number of - % datapoints classified within a given cluster) - - % disp('idx2counts:'); - idx2counts = histc(idx, 1:max(idx)); - - % Output = Input(IX) - [~,IX] = sort(idx2counts,'descend'); - - % Size Kx70700 (location of each cluster); clusters are put with 'the - % most prominent one first' - CP = CP(IX,:); idx2 = idx; % order by occurrence - - % Changes the datapoint indexes so that they fit the new clusters order - for l=1:max(idx), idx2(idx==IX(l))=l; end - idx=idx2; - - CP2 = zeros(n_clusters,size(CP,2)); - Disp = zeros(1,n_clusters); - Std_Clusters = zeros(size(CP,2),n_clusters); - - % For each cluster index - for l=1:max(idx) - % Averages all data points belonging to one specific cluster, and - % stores the obtained pattern as a cell in CP2 - CP2(l,:) = mean(XONn(:,idx==l),2); %./ ( std(XON(:,idx==l),[],2) ) * sqrt(length(idx==l)); % Liu&Duyn - - % Measure of dispersion within the cluster considered - Disp(l) = mean(corr(CP2(l,:)',XONn(:,idx==l))); - - Std_Clusters(:,l) = std(XONn(:,idx==l),[],2); - end - - % d contains the correlation values of all frames to the CAPs - r = corr(CP2',XONn); - - d = zeros(1,length(idx)); - for k=1:max(idx) - d(idx==k) = r(k,idx==k); - end - - % Added part to compute the fraction of frames assigned to a given seed - % if using the intersection option (in which a data point is retained - % as long as at least one seed region becomes significantly (de)active) - if strcmp(SeedType,'Intersection') - - % idx_all will contain the clustering indices as put on a whole - % temporal scale (time x subjects) - idx_all = zeros(size(idx_sep_seeds,1),n_subjects); - - % Index to properly fill in the matrix by adding up the number of - % frames per subject every time - tmp_loc = 1; - - - for s = 1:n_subjects - tmp = sum(squeeze(idx_sep_seeds(:,s,:)),2); - tmp(tmp >= 1) = 1; - tmp = logical(tmp); - idx_all(tmp,s) = idx(tmp_loc:(tmp_loc+sum(tmp)-1)); - tmp_loc = tmp_loc + sum(tmp); - end - - - - % I will compute my fractions for each seed combination of - % interest; for example, 3 seeds would yield 7 possible - % combinations - for s = 1:n_subjects - for t = 1:size(idx_sep_seeds,1) - - tmp = squeeze(idx_sep_seeds(t,s,:)); - - % If there is at least one seed active or deactive at - % the point of interest, we update the sfrac count at the - % appropriate CAP - if sum(tmp) > 0 - sfrac(s,idx_all(t,s),find(ismember(combvec,tmp','rows'))) = ... - sfrac(s,idx_all(t,s),find(ismember(combvec,tmp','rows'))) + 1; - end - end - end - end -end \ No newline at end of file diff --git a/Analysis/circular_arrow.m b/Analysis/circular_arrow.m deleted file mode 100644 index ae40811..0000000 --- a/Analysis/circular_arrow.m +++ /dev/null @@ -1,137 +0,0 @@ -function circular_arrow(figHandle, radius, centre, arrow_angle, angle, direction, colour, head_size, head_style) -% This is a function designed to draw a circular arrow onto the current -% figure. It is required that "hold on" must be called before calling this -% function. -% -% The correct calling syntax is: -% circular_arrow(height, centre, angle, direction, colour, head_size) -% where: -% figHandle - the handle of the figure to be drawn on. -% radius - the radius of the arrow. -% centre - a vector containing the desired centre of the circular -% arrow. -% arrow_angle - the desired orientation angle of the circular arrow. -% This is measured in degrees counter-clockwise -% angle - the angle between starting and end point of the arrow in -% degrees. -% direction - variable set to determine format of arrow head. Use 1 -% to get a clockwise arrow, -1 to get a counter clockwise -% arrow, 2 to get a double headed arrow and 0 to get just -% an arc. -% colour (optional) - the desired colour of the arrow, using Matlab's -% Color Specification. -% head_size (optional) - the size of the arrow head. -% head_style (optional) - the style of the arrow head. -% For more information, see Annotation Arrow Properties. - -%Ensure proper number of arguments -if (nargin < 6)||(nargin > 9) - error(['Wrong number of parameters '... - 'Enter "help circular_arrow" for more information']); -end - -% arguments 7, 8 and 9 are optional, -if nargin < 9 - head_style = 'vback2'; -end -if nargin < 8 - head_size = 10; -end -if nargin < 7 - colour = 'k'; -end - -% display a warning if the headstyle has been specified, but direction has -% been set to no heads -if nargin == 9 && direction == 0 - warning(['Head style specified, but direction set to 0! '... - 'This will result in no arrow head being displayed.']); -end - - -% Check centre is vector with two points -[m,n] = size(centre); -if m*n ~= 2 - error('Centre must be a two element vector'); -end - -arrow_angle = deg2rad(arrow_angle); % Convert angle to rad -angle = deg2rad(angle); % Convert angle to rad -xc = centre(1); -yc = centre(2); - -% Creating (x, y) values that are in the positive direction along the x -% axis and the same height as the centre -x_temp = centre(1) + radius; -y_temp = centre(2); - -% Creating x & y values for the start and end points of arc -x1 = (x_temp-xc)*cos(arrow_angle+angle/2) - ... - (y_temp-yc)*sin(arrow_angle+angle/2) + xc; -x2 = (x_temp-xc)*cos(arrow_angle-angle/2) - ... - (y_temp-yc)*sin(arrow_angle-angle/2) + xc; -x0 = (x_temp-xc)*cos(arrow_angle) - ... - (y_temp-yc)*sin(arrow_angle) + xc; -y1 = (x_temp-xc)*sin(arrow_angle+angle/2) + ... - (y_temp-yc)*cos(arrow_angle+angle/2) + yc; -y2 = (x_temp-xc)*sin(arrow_angle-angle/2) + ... - (y_temp-yc)*cos(arrow_angle-angle/2) + yc; -y0 = (x_temp-xc)*sin(arrow_angle) + ... - (y_temp-yc)*cos(arrow_angle) + yc; - -% Plotting twice to get angles greater than 180 -i = 1; - -% Creating points -P1 = struct([]); -P2 = struct([]); -P1{1} = [x1;y1]; % Point 1 - 1 -P1{2} = [x2;y2]; % Point 1 - 2 -P2{1} = [x0;y0]; % Point 2 - 1 -P2{2} = [x0;y0]; % Point 2 - 1 -centre = [xc;yc]; % guarenteeing centre is the right dimension -n = 1000; % The number of points in the arc -v = struct([]); - -while i < 3 - - v1 = P1{i}-centre; - v2 = P2{i}-centre; - c = det([v1,v2]); % "cross product" of v1 and v2 - a = linspace(0,atan2(abs(c),dot(v1,v2)),n); % Angle range - v3 = [0,-c;c,0]*v1; % v3 lies in plane of v1 and v2 and is orthog. to v1 - v{i} = v1*cos(a)+((norm(v1)/norm(v3))*v3)*sin(a); % Arc, center at (0,0) - plot(v{i}(1,:)+xc,v{i}(2,:)+yc,'Color', colour) % Plot arc, centered at P0 - - i = i + 1; - -end - -position = struct([]); - -% Setting x and y for CW and CCW arrows -if direction == 1 - position{1} = [x2 y2 x2-(v{2}(1,2)+xc) y2-(v{2}(2,2)+yc)]; -elseif direction == -1 - position{1} = [x1 y1 x1-(v{1}(1,2)+xc) y1-(v{1}(2,2)+yc)]; -elseif direction == 2 - position{1} = [x2 y2 x2-(v{2}(1,2)+xc) y2-(v{2}(2,2)+yc)]; - position{2} = [x1 y1 x1-(v{1}(1,2)+xc) y1-(v{1}(2,2)+yc)]; -elseif direction == 0 - % Do nothing -else - error('direction flag not 1, -1, 2 or 0.'); -end - -% Loop for each arrow head -i = 1; -while i < abs(direction) + 1 - h=annotation('arrow'); % arrow head - set(h,'parent', gca, 'position', position{i}, ... - 'HeadLength', head_size, 'HeadWidth', head_size,... - 'HeadStyle', head_style, 'linestyle','none','Color', colour); - - i = i + 1; -end \ No newline at end of file diff --git a/Analysis/jUpperTriMatToVec.m b/Analysis/jUpperTriMatToVec.m deleted file mode 100755 index 693b942..0000000 --- a/Analysis/jUpperTriMatToVec.m +++ /dev/null @@ -1,32 +0,0 @@ -function v=jUpperTriMatToVec(m,varargin) -% converts the upper-triangular part of a matrix to a vector -% -% IN: -% m: matrix -% offset: offset above leading diagonal, fed to triu function -% OUT: -% v: vector of upper-triangular values -% -% v1.0 Oct 2009 Jonas Richiardi -% - initial release -% v1.1 Feb 2015 Dimitri Van De Ville -% - faster version by single index - -switch nargin - case 1 - offset=1; - case 2 - offset=varargin{1}; -end - -% get indices of upper triangular part (Peter Acklam's trick) -%[m_i m_j] = find(triu(ones(size(m)), offset)); -idx = find(triu(ones(size(m)), offset)); - -v=m(idx); - -% copy to vector -%v=zeros(numel(m_i),1); -%for v_idx=1:numel(m_i) -% v(v_idx)=m(m_i(v_idx),m_j(v_idx)); -%end \ No newline at end of file diff --git a/ArtificialExampleData/FD.mat b/ArtificialExampleData/FD.mat deleted file mode 100644 index 9c9b8e7..0000000 Binary files a/ArtificialExampleData/FD.mat and /dev/null differ diff --git a/ArtificialExampleData/TC.mat b/ArtificialExampleData/TC.mat deleted file mode 100644 index 3f4a136..0000000 Binary files a/ArtificialExampleData/TC.mat and /dev/null differ diff --git a/ArtificialExampleData/brain_info.mat b/ArtificialExampleData/brain_info.mat deleted file mode 100644 index 0500ea0..0000000 Binary files a/ArtificialExampleData/brain_info.mat and /dev/null differ diff --git a/ArtificialExampleData/mask.mat b/ArtificialExampleData/mask.mat deleted file mode 100644 index 6078006..0000000 Binary files a/ArtificialExampleData/mask.mat and /dev/null differ diff --git a/ArtificialExampleData/seed1.mat b/ArtificialExampleData/seed1.mat deleted file mode 100644 index fa06e6e..0000000 Binary files a/ArtificialExampleData/seed1.mat and /dev/null differ diff --git a/Build_Connectivity_Matrix.m b/Build_Connectivity_Matrix.m deleted file mode 100755 index 4befae4..0000000 --- a/Build_Connectivity_Matrix.m +++ /dev/null @@ -1,25 +0,0 @@ -%% This function constructs a connectivity matrix from the indices of -% cluster assignment -function [M] = Build_Connectivity_Matrix(IDX,tmp_ss,type,n_items) - - IDX_full = zeros(n_items,1); - - switch type - case 'items' - IDX_full(tmp_ss) = IDX; - case 'dims' - IDX_full = IDX; - case 'subjects' - IDX_full(tmp_ss) = IDX; - end - - M = zeros(n_items,n_items); - - for i = 1:length(IDX_full) - for j = 1:length(IDX_full) - if (IDX_full(i) == IDX_full(j)) && (IDX_full(i) > 0) - M(i,j) = 1; - end - end - end -end \ No newline at end of file diff --git a/CAP_ConsensusClustering.m b/CAP_ConsensusClustering.m deleted file mode 100755 index e017aa2..0000000 --- a/CAP_ConsensusClustering.m +++ /dev/null @@ -1,137 +0,0 @@ -%% This function performs consensus clustering over a range of K values -% The goal is to provide a measure of how good each value of K is -% -% Inputs: -% - X is the data matrix (cell array with each cell n_DP x n_DIM) -% - K_range is the range of K values to examine -% - Subsample_type defines how subsampling is done: across items (data -% points) if 'items', and across dimensions if 'dimensions' -% - Subsample_fraction is the fraction of the original data points, or -% dimensions, to keep for a given fold -% - n_folds is the number of folds over which to run -function [Consensus_ordered] = CAP_ConsensusClustering(X,K_range,Subsample_type,Subsample_fraction,n_folds,DistType) - - % Number of subjects - n_subjects = length(X); - - n_items = 0; - - frames_index = cell(1,n_subjects); - - for s = 1:n_subjects - frames_index{s} = n_items + (1:size(X{s},2)); - n_items = n_items + size(X{s},2); - end - - % Number of dimensions - n_dims = size(X{1},1); - - Consensus = zeros(n_items,n_items,length(K_range)); - Consensus_ordered = zeros(n_items,n_items,length(K_range)); - - % Loop over all K values to assess - for k = 1:length(K_range) - - disp(['Running consensus clustering for K = ',num2str(K_range(k)),'...']); - - % Connectivity matrix that will contain 0s or 1s depending on whether - % elements are clustered together or not - M = zeros(n_items,n_items,n_folds); - I = zeros(n_items,n_items,n_folds); - - % Loops over all the folds to perform clustering for - for h = 1:n_folds - - switch Subsample_type - case 'items' - - % Number of items to subsample - n_items_ss = floor(Subsample_fraction*n_items); - - % Does the subsampling - [X_ss,tmp_ss] = datasample((cell2mat(X))',n_items_ss,1,'Replace',false); - - % Vector - I_vec = zeros(n_items,1); - I_vec(tmp_ss) = 1; - - % Constructs the indicator matrix - for i = 1:length(I_vec) - for j = 1:length(I_vec) - if (I_vec(i) == I_vec(j)) && (I_vec(i) > 0) - I(i,j,h) = 1; - end - end - end - - case 'dims' - - % Number of dimensions to subsample - n_dims_ss = floor(Subsample_fraction*n_dims); - - % Does the subsampling - [X_ss,tmp_ss] = datasample((cell2mat(X))',n_dims_ss,2,'Replace',false); - - % Constructs the indicator matrix - I(:,:,h) = ones(n_items,n_items); - - case 'subjects' - - % Number of subjects to use in the subsampling - n_subjects_ss = floor(Subsample_fraction*n_subjects); - - tmp = datasample(1:n_subjects,n_subjects_ss,'Replace',false); - - % n_frames x n_voxels - X_ss = (cell2mat(X(tmp)))'; - tmp_ss = cell2mat(frames_index(tmp)); - - % Vector - I_vec = zeros(n_items,1); - I_vec(tmp_ss) = 1; - - % Constructs the indicator matrix - for i = 1:length(I_vec) - for j = 1:length(I_vec) - if (I_vec(i) == I_vec(j)) && (I_vec(i) > 0) - I(i,j,h) = 1; - end - end - end - - otherwise - errordlg('PROBLEM IN TYPE OF SUBSAMPLING'); - end - - % Does the clustering (for now, only with k-means), so that IDX - % contains the indices for each datapoint - IDX = kmeans(X_ss,K_range(k),'Distance',DistType,'Replicates',1,'Start','uniform'); - - % Builds the connectivity matrix - M(:,:,h) = Build_Connectivity_Matrix(IDX,tmp_ss,Subsample_type,n_items); - - clear I_vec - clear X_ss - clear tmp_ss - clear IDX - end - - % Constructs the consensus matrix for the considered K - Consensus(:,:,k) = sum(M,3)./sum(I,3); - - tree = linkage(squeeze(1-Consensus(:,:,k)),'average'); - - % Leaf ordering to create a nicely looking matrix - leafOrder = optimalleaforder(tree,squeeze(1-Consensus(:,:,k))); - - % Ordered consensus matrix - Consensus_ordered(:,:,k) = Consensus(leafOrder,leafOrder,k); - - clear leafOrder - clear Dist_vec - clear test - clear IDX - clear M - clear I - end -end \ No newline at end of file diff --git a/CAP_TB.fig b/CAP_TB.fig deleted file mode 100755 index e172d2c..0000000 Binary files a/CAP_TB.fig and /dev/null differ diff --git a/CAP_TB.m b/CAP_TB.m deleted file mode 100755 index d608cf0..0000000 --- a/CAP_TB.m +++ /dev/null @@ -1,3413 +0,0 @@ -%% This is the main script containing the routines necessary for the use -% of the co-activation pattern analysis (CAP) toolbox -% -% Implemented and written by Thomas Bolton, Medical Image Processing -% Laboratory (MIP:Lab) -% -% Version 1.0: November 9th 2018: fixing the last remaining issues -% -function varargout = CAP_TB(varargin) - -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @CAP_TB_OpeningFcn, ... - 'gui_OutputFcn', @CAP_TB_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 - - - - - -%% Executes when the window opens -function CAP_TB_OpeningFcn(hObject, eventdata, handles, varargin) - -%%%%%%%%%%%%%%%%%%%% -% Path and other miscellaneous settings - -% Adds the paths to the subfolders of the toolbox that will be important -% for the plotting and the analysis -addpath(genpath('./Plotting')); -addpath(genpath('./Analysis')); -addpath(genpath('./DefaultData')); - -% Sets warnings off -warning('off'); - -% Choose default command line output for CAP_TB -handles.output = hObject; - - -%%%%%%%%%%%%%%%%%%%% -% Data loading - -% TC will contain the time courses of the subjects from the different -% populations (cell array, each cell with size n_TP x n_masked_voxels) -handles.TC = {}; - -% FD contains the traces of framewise displacement for the subjects (n_TP x -% n_subj per cell of the array, one cell per dataset) -handles.FD = {}; - -% Information on the NIFTI files from which the data originate -handles.brain_info = {}; - -% Mask used prior to CAP analysis -handles.mask = {}; - -% Number of datasets added to the interface. A dataset is defined as a -% population of subjects from the same experimental group (e.g., an -% ensemble of subjects suffering from the same disorder) -handles.n_datasets = 0; - -% Stores the number of subjects that have been loaded -handles.n_subjects = {}; - -% SubjNames contains the names of the files from which subject data have -% been sampled (full paths) -handles.SubjNames = {}; - -% MotName contains the name(s) of the file(s) loaded as motion ones -handles.MotName = {}; - -% TP and VOX contain the number of time points (of frames) and of brain -% voxels that are present in the loaded datasets. Those values are -% initialized at -inf, and then take the values of the first file that is -% being loaded if that file looks reasonable dimensionally speaking. In the -% scripts below, it is assumed that all subject populations loaded have a -% similar number of time points and of voxels -handles.SubjSize.TP = -inf; -handles.SubjSize.VOX = -inf; - -% By default, the reference population from which CAPs will be extracted -% will be the first uploaded one -% Note: for the moment, this parameter is fixed to 1 (no functionality for -% modifying it yet) -handles.ReferencePopulation = 1; - -% Loads and sets the brain underlay used for plotting purposes -Underlay = load_nii('Underlay.nii'); -Underlay_mat = [Underlay.hdr.hist.srow_x; Underlay.hdr.hist.srow_y; Underlay.hdr.hist.srow_z; 0 0 0 1]; -Underlay_dim = Underlay.hdr.dime.dim; -Underlay_dim = Underlay_dim(2:4); -handles.Underlay_info.dim = Underlay_dim; -handles.Underlay_info.mat = Underlay_mat; -clear Underlay -clear Underlay_dim -clear Underlay_mat -load('brain.mat'); -assignin('base','brain', brain); -handles.brain = brain; -clear brain - -% Handles for the TR and whether it is a reasonable value -handles.TR = -inf; -handles.isTROK = false; - - -%%%%%%%%%%%%%%%%%%%% -% Seed selection and seed maps - -% Seed used for the analysis -handles.seed = []; - -% Because there can be more than one seed, we create a vector that will -% encompass the multiple information in several colors -handles.seed_display = []; - -% Handle to verify whether the amount of seeds has been entered well, how -% many seeds there are, and the type -handles.isSeedOK = false; - -% Option to have a subject-specific seed -handles.isSeedSubjectSpecific = 0; - -% Number of different seeds -handles.n_seed = 1; - -handles.SeedType = 'Average'; - -% One average map throughout subjects -handles.AvgSeedMap = []; - -%%%%%%%%%%%%%%%%%%%% -% Time points selection - -% Motion threshold for scrubbing -handles.Tmot = 0.5; - -% Threshold for frame selection in the analysis -handles.T = 0.5; - -% Sets the right text header in front of the frame selection threshold box -% (threshold or retention percentage) -if get(handles.TRadio,'Value') - set(handles.TText,'String','T [-]'); - handles.SelMode = 'Threshold'; -else - set(handles.TText,'String','P [%]'); - handles.SelMode = 'Percentage'; -end - -% Denotes the type of frames (activation, deactivation or both) to use for -% selecting time points -handles.SignMatrix = [1 0; 1 0]; - -% Activation and deactivation frames kept for all datasets -handles.Xonp = {}; -handles.Xonn = {}; - -% Percentage of frames retained for CAP analysis (discarding both the -% baseline time points and the scrubbed time points) -handles.RetainedPercentage = {}; - -% Indices of the frames that have been retained (i.e. when do they occur in -% the full time course), of baseline frames, and of scrubbed frames -handles.FrameIndices = {}; - -handles.idx_sep_seeds = {}; - -%%%%%%%%%%%%%%%%%%%% -% CAP analysis - -% Max number of clusters to verify with consensus clustering -handles.Kmax = 12; - -% Percentage of items to use for the consensus clustering folds -handles.PCC = 80; - -% Number of times that clustering is run -handles.n_rep = 20; - -% Percentage voxels to keep for clustering (positive - Pp - and negative - -% Pn - ones) -handles.Pp = 100; -handles.Pn = 100; - -% Number of clusters to use in the analysis -handles.K = 5; - -% Indices of the CAP to which frames from the reference population and from -% the other populations are assigned -handles.idx = {}; - -% Value of correlation of the control group frame that is the Tper-th least -% close to its CAP -handles.CorrDist = []; - -% Contains the CAPs -handles.CAP = []; - -% Contains the standard deviation for the CAPs -handles.STDCAP = []; - -% Percentile threshold used in frame assignment -handles.percentile = 5; - -%%%%%%%%%%%%%%%%%%%% -% Metrics - -% Will contain the metrics -% State matrix (n_subjects x n_time points) -handles.TPM = {}; - -% State counts (raw and frac) -handles.Counts = {}; - -% Number of times entering a state -handles.Number = {}; - -% Average duration within a state -handles.Avg_Duration = {}; - -% Duration of all the excursions within a state -handles.Duration = {}; - -% Transition probabilities -handles.TM = {}; - -% Cumulative sum of states -handles.TPMCum = {}; - -% Seed fractions -handles.sfrac = []; - -%%%%%%%%%%%%%%%%%%%% -% General utilities - -% Log containing the different events summoned from the toolbox -handles.Log = {}; - -% Colors used in plotting of all populations -handles.PopColor{1} = [255,255,180; 219,224,252; 188,252,188; 230,230,230]/255; -handles.PopColor{2} = [130,48,48; 51,75,163; 59,113,86; 0, 0, 0]/255; - -% Project title, by default 'Untitled' -handles.project_title = 'Untitled'; - -% Directory to which data is to be saved (initially loaded as ./SavedData) -handles.savedir = fullfile(pwd,'SavedData'); -set(handles.SaveFolderText,'String',handles.savedir); - -% Update handles structure -guidata(hObject, handles); - -% --- Outputs from this function are returned to the command line. -function varargout = CAP_TB_OutputFcn(hObject, eventdata, handles) - -% Get default command line output from handles structure -varargout{1} = handles.output; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%% SECTION 1: LOADING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Data Button Click - -% Executes when adding a subject population (clicking on 'A. Load data') -function DataButton_Callback(hObject, eventdata, handles) - % Opens up a menu to choose the required files for the analysis; the user - % must select four files: - % 1. Data file - % 2. Mask file - % 3. Info file (header of NIFTI) - % 4. Motion file - - % He can select them in the order he likes - [filename1,pathname1]=uigetfile({'*.*','All Files'},... - 'Select data, motion, mask and brain info files...','MultiSelect','on'); - - % If the user has indeed entered files - if ~isequal(filename1,0) || ~isequal(pathname1,0) - % There should be four selected files. In this switch, we test - % for the amount of entered files - if length(filename1) == 4 - - % The files are loaded sequentially - for i = 1:length(filename1) - File{i} = fullfile(pathname1, filename1{i}); - tmp = load(File{i}); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - - % Finds what type of file DataType is between the four - % possibilities - DataType = CAP_FindDataType(tmp); - - % Accordingly, fill the right handle with the information - switch DataType - case 'Data' - % We store the data into handles.TC and the file name that goes - % with it - handles.TC{handles.n_datasets+1} = tmp; - - % Takes only the last two parts of the file name and - % puts them in tmp_file - [tmp_file,n_delim] = strsplit(File{i},'/'); - - if isempty(n_delim) - tmp_file = strsplit(File{i},'\'); - end - - tmp_file = tmp_file(end-1:end); - - % This is what is saved and displayed in the main - % window then - handles.SubjNames{handles.n_datasets+1} = fullfile(tmp_file{1},tmp_file{2}); - handles.n_subjects{handles.n_datasets+1} = size(handles.TC{handles.n_datasets+1},2); - - % Some commands are run only for the first dataset that we add - if handles.n_datasets == 0 - % We compute and store the number of voxels and the number of time - % points, as well as the number of subjects - handles.SubjSize.VOX = size(handles.TC{1}{1},2); - handles.SubjSize.TP = size(handles.TC{1}{1},1); - end - - % Sets the text label about data dimensions - set(handles.Dimensionality_Text, 'String', [num2str(handles.SubjSize.TP),... - ' frames x ',num2str(handles.SubjSize.VOX),' voxels (',... - strjoin(arrayfun(@(x) num2str(x),cell2mat(handles.n_subjects),... - 'UniformOutput',false),'+'),')']); - - case 'Motion' - % We store the path of the motion file added - handles.MotName{handles.n_datasets+1} = File{i}; - % If the dimensions hold, we store the file into the FD variable - % and then plot the FD ribbon graph - handles.FD{handles.n_datasets+1} = tmp; - - case 'Mask' - handles.mask{handles.n_datasets+1} = tmp; - case 'Info' - % If so, we store the value and we validate the choice - handles.brain_info{handles.n_datasets+1} = tmp; - - % If the data file is unknown, then we return an error and - % the user must enter files again - case 'Unknown' - errordlg('At least one of the selected files is not recognized; please try again !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - end - - % Check if the dimensionality of the entered data holds between - % the file types. It may be that the user entered four files of - % the same type (e.g. four data files), rather than one of each - % type as required - [is_DataOK,Data_problems] = CAP_IsDataOK(handles.TC{handles.n_datasets+1},handles.FD{handles.n_datasets+1},... - handles.mask{handles.n_datasets+1},handles.brain_info{handles.n_datasets+1}); - if is_DataOK - - % We increment handles.n_datasets - handles.n_datasets = handles.n_datasets + 1; - - % We can now enable the seed selection - set(handles.SeedButton,'Enable','on'); - - % Also, we can now color the button in green - set(hObject,'BackgroundColor', [101,140,196]/255); - - % If we are loading the first dataset, we convert the underlay - % to the resolution of the functional data for plotting - if handles.n_datasets == 1 - - % If we are loading the first dataset, we can get rid - % of anything else that we have so far - handles = ClearSection3(eventdata,handles); - handles = ClearSection4(eventdata,handles); - - % The brain variable now contains a good resolution - % underlay that can directly be overlapped with the - % functional data - handles.brain = CAP_V2V(handles.brain,handles.Underlay_info.dim,... - handles.Underlay_info.mat,handles.brain_info{1}.dim,handles.brain_info{1}.mat); - - elseif handles.n_datasets > 1 && handles.n_datasets < 5 && ~isempty(handles.CAP) - - % If we are loading one more dataset on top of the - % first one, then we rather want to solely clear the - % Metrics content; but we may want to keep the rest - handles = ClearSection4(eventdata,handles); - - set(handles.AssignButton,'Enable','on'); - - set(handles.CAP_TP,'Visible','on'); - set(handles.Percentile_Edit,'Visible','on'); - - elseif handles.n_datasets > 4 - errordlg('Please enter at most four different populations in the interface !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - handles.Log = CAP_AddToLog(handles.Log,'Data correctly loaded'); - - % If it doesn't hold, then we return an error - else - errordlg(['There is a dimensionality problem in your data: ',Data_problems]); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - % If a different number of files is entered, then there is a problem, - % and everything is reset - else - errordlg('You did not enter the correct number of files !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - % Else, an error is displayed and the user is prompted to enter files - else - errordlg('Cancelling data entry will not solve your problems !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - -% Update handles structure -guidata(hObject, handles); - - - - - -%% TR Textbox Interaction - -% Executes when we go to the TR field to add the TR of the experiment -function TR_Entry_Callback(hObject, eventdata, handles) - - % If the TR takes a reasonable value, then we validate it; we enable values - % between 0.5 and 5s - if (~isempty(str2double(get(hObject,'String')))) && ... - (str2double(get(hObject,'String')) > 0.5) && ... - (str2double(get(hObject,'String')) <= 5) - - handles.TR = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - handles.isTROK = true; - - handles.Log = CAP_AddToLog(handles.Log,'Correct value of TR entered',{handles.TR},{'TR'}); - - % Else, the TR value is not accepted - else - set(hObject,'BackgroundColor', [204,146,146]/255); - handles.isTROK = false; - end - -guidata(hObject, handles); - - - -% Executes during creation of the TR textbox -function handles = TR_Entry_CreateFcn(hObject, eventdata, handles) - - set(hObject,'Enable','off'); - set(hObject,'String','Click to enter...'); - set(hObject,'FontAngle','italic'); - - if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','r'); - end - -guidata(hObject, handles); - - - -% Executes when clicking on the TR text space -function TR_Entry_ButtonDownFcn(hObject, eventdata, handles) - - set(hObject,'Enable','on'); - set(hObject,'String',''); - set(hObject,'FontAngle','normal'); - uicontrol(hObject); - -guidata(hObject, handles); - - - - - -%% Seed Button Controls -% We want to define what happens when loading data (SeedButton) or when -% attempting to plot them (PlotSeedButton) - -% --- Executes on button press in CheckS1POS. -function CheckS1POS_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - set(handles.CheckS1NEG,'Value',0); -else - set(handles.CheckS1POS,'Value',1); -end - -handles.SignMatrix(2,:) = [1 0]; - -rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - - - -% --- Executes on button press in CheckS1NEG. -function CheckS1NEG_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - handles.SignMatrix(1,:) = [0 1]; - set(handles.CheckS1POS,'Value',0); - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); -else - handles.SignMatrix(1,:) = [1 0]; - set(handles.CheckS1POS,'Value',1); - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); -end - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - - -% --- Executes on button press in CheckS2POS. -function CheckS2POS_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - set(handles.CheckS2NEG,'Value',0); -else - set(handles.CheckS2POS,'Value',1); -end - -handles.SignMatrix(2,:) = [1 0]; -rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - - -% --- Executes on button press in CheckS2NEG. -function CheckS2NEG_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - handles.SignMatrix(2,:) = [0 1]; - set(handles.CheckS2POS,'Value',0); - rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); -else - handles.SignMatrix(2,:) = [1 0]; - set(handles.CheckS2POS,'Value',1); - rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); -end - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - - - -% --- Executes on button press in CheckS3POS. -function CheckS3POS_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - set(handles.CheckS3NEG,'Value',0); -else - set(handles.CheckS3POS,'Value',1); -end - -handles.SignMatrix(3,:) = [1 0]; - -rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - -% --- Executes on button press in CheckS3NEG. -function CheckS3NEG_Callback(hObject, eventdata, handles) - -if get(hObject,'Value') - handles.SignMatrix(3,:) = [0 1]; - set(handles.CheckS3POS,'Value',0); - rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); -else - handles.SignMatrix(3,:) = [1 0]; - set(handles.CheckS3POS,'Value',1); - rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); -end - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -guidata(hObject,handles); - - - -% Executes when the user changes the type of seed relationship desired -% (Average, Intersection, Union of seed signals) -function SeedPopup_Callback(hObject, eventdata, handles) - -% Clears and makes the circles display reflecting seed types unvisible -handles = ResetGraphDisplay(handles.FancyCircles,handles); - -% We consider the value selected by the user for the first seed between -% '+' or '-', and update the FancyCircles plot accordingly -if get(handles.CheckS1POS,'Value') - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); -elseif get(handles.CheckS1NEG,'Value') - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); -end - -% The same is done for the other seeds, if more than one has been loaded -% (or if more than two have been loaded) -if handles.n_seed > 1 - - if get(handles.CheckS2POS,'Value') - rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - elseif get(handles.CheckS2NEG,'Value') - rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); - end - - if handles.n_seed > 2 - - if get(handles.CheckS3POS,'Value') - rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - elseif get(handles.CheckS3NEG,'Value') - rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[51,75,163]/255,'EdgeColor','none','Parent',handles.FancyCircles); - end - end -end - -% The second step in the plotting is to add the "arrows" that link circles -% differently depending on whether we consider a Union or an Intersection -switch get(hObject,'Value') - - % If we have the "average" pick - case 1 - % If the user selects "average" but the number of seeds entered - % exceeds 1, then by default we revert back to the "union" case, - % since the user should enter one averaged seed file to have an - % averaged seed output - if handles.n_seed > 1 - set(hObject,'Value',2); - handles.SeedType = 'Union'; - rectangle('Position',[12 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[11 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - if handles.n_seed > 2 - rectangle('Position',[32 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[31 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - end - else - handles.SeedType = 'Average'; - end - - % If we have the union pick - case 2 - handles.SeedType = 'Union'; - rectangle('Position',[12 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[11 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - if handles.n_seed > 2 - rectangle('Position',[32 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[31 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - end - - % If we have the intersection pick - case 3 - handles.SeedType = 'Intersection'; - rectangle('Position',[12 10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[11 9 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - if handles.n_seed > 2 - rectangle('Position',[32 10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[31 9 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - end -end - -% Modifies the axis parameters to have a big enough seed display -axis(handles.FancyCircles,'square'); - -switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); -end - -handles.Log = CAP_AddToLog(handles.Log,'Seed union status changed',{handles.SeedType},{'Status'}); - -guidata(hObject, handles); - - - -% Executes during object creation, after setting all properties. -function SeedPopup_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -guidata(hObject, handles); - - - -% Executes when clicking on 'B. Select a seed' -function SeedButton_Callback(hObject, eventdata, handles) - -% We want to clear everything from and after this stage, since we will -% compute results with a new seed -handles = ClearSection3(eventdata,handles); -handles = ClearSection4(eventdata,handles); - -% Multiselection is on, so that as many as three files can be picked -[filename_seed,pathname_seed]=uigetfile({'*.*','All Files'},... - 'Select Seed File...','MultiSelect','on'); - -% Stores the type of frames to retain for each seed -handles.SignMatrix = [1 0; 1 0; 1 0]; - -% Resets the graph displays as well as the seed-related parameters -handles = ResetGraphDisplay(handles.FancyCircles,handles); - -set(handles.Seed1Text,'Visible','off'); -set(handles.Seed2Text,'Visible','off'); -set(handles.Seed3Text,'Visible','off'); - -set(handles.SeedPlusText,'Visible','off'); -set(handles.SeedMinusText,'Visible','off'); - -set(handles.CheckS1POS,'Visible','off'); -set(handles.CheckS1NEG,'Visible','off'); - -set(handles.CheckS1POS,'Value',1); -set(handles.CheckS1NEG,'Value',0); - -set(handles.CheckS2POS,'Visible','off'); -set(handles.CheckS2NEG,'Visible','off'); - -set(handles.CheckS2POS,'Value',1); -set(handles.CheckS2NEG,'Value',0); - -set(handles.CheckS3POS,'Visible','off'); -set(handles.CheckS3NEG,'Visible','off'); - -set(handles.CheckS3POS,'Value',1); -set(handles.CheckS3NEG,'Value',0); - -handles = ResetGraphDisplay(handles.SeedGraphX,handles); -handles = ResetGraphDisplay(handles.SeedGraphZ,handles); -handles = ResetGraphDisplay(handles.SeedMapX,handles); -handles = ResetGraphDisplay(handles.SeedMapZ,handles); - -% If the user has indeed entered files -if ~isequal(filename_seed,0) || ~isequal(pathname_seed,0) - % There should be three or less selected files. In this switch, we test - % for the amount of entered files - - % In the case in which only one seed file is entered ('char' type), - % we convert into an array - if strcmp(class(filename_seed),'char') - filename_seed = {filename_seed}; - end - - % If we enter that statement, it means that we have only one seed type - % across subjects (that is, no subject-specific data) - if length(filename_seed) <= 3 - - % Number of entered seeds - handles.n_seed = length(filename_seed); - - for myindex = 1:length(filename_seed) - File_seed = fullfile(pathname_seed, filename_seed{myindex}); - tmp = load(File_seed); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - - % If the file is of suitable dimensions - if islogical(tmp) && size(tmp,2) == 1 && size(tmp,1) == sum(handles.mask{1}) - - % Then we put it in the handles, enable the plotting button, and - % make the seed selection button green - handles.seed(:,myindex) = tmp; - - handles.Log = CAP_AddToLog(handles.Log,'Seed chosen',{File_seed},{'Seed file'}); - else - errordlg('The file you entered appears to be of wrong dimensions...'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - end - - % If we survive all the above, we can see that the seed files are - % good - handles.isSeedOK = true; - - % We also enable to plot the seed results - set(handles.PlotSeedButton,'Enable','on'); - set(handles.PlotSeedButton,'Visible','on'); - - % We make the text legends visible - set(handles.S_SEED1,'Visible','on'); - - set(handles.SeedButton,'BackgroundColor', [101,140,196]/255); - - % We can now go through the next parts of the analysis, so we - % enable the related buttons - set(handles.TPSelectionButton,'Enable','on'); - set(handles.SeedMapPushButton,'Enable','on'); - - set(handles.TPSelectionButton,'Visible','on'); - set(handles.SeedMapPushButton,'Visible','on'); - - % Makes other TP selection utilities visible - set(handles.PRadio,'Visible','on'); - set(handles.TRadio,'Visible','on'); - set(handles.uibuttongroup7,'Visible','on'); - set(handles.TText,'Visible','on'); - set(handles.TMotText,'Visible','on'); - set(handles.TEdit,'Visible','on'); - set(handles.TMotEdit,'Visible','on'); - - % We also see the displays for entering seed specifications - set(handles.SeedPopup,'Visible','on'); - - handles.Log = CAP_AddToLog(handles.Log,'Correct amount of seeds entered',{handles.n_seed},{'Seed amount'}); - - handles.seed_display = zeros(length(handles.seed(:,1)),1); - - set(handles.CheckS1POS,'Visible','on'); - set(handles.CheckS1NEG,'Visible','on'); - CheckS1POS_Callback(handles.CheckS1POS,eventdata,handles); - - set(handles.Seed1Text,'Visible','on'); - - set(handles.SeedPlusText,'Visible','on'); - set(handles.SeedMinusText,'Visible','on'); - - % If there are more than one seed, then we allow the popup button to be - % changed for a more complex seed use choice - if handles.n_seed > 1 - set(handles.SeedPopup,'Enable','on'); - set(handles.SeedPopup,'Value',2); - handles.SeedType = 'Union'; - - % We also update the circles in the seed illustration - rectangle('Position',[12 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[11 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - - % We fill seed_display with one scalar value across seed voxels - % per seed (to have different colors plotted in the seed choice - % graph - useless_vector = [0.25,0.75,1]; - - for se = 1:handles.n_seed - handles.seed_display = handles.seed_display + useless_vector(se)*handles.seed(:,se); - end - - set(handles.S_SEED2,'Visible','on'); - - set(handles.CheckS2POS,'Visible','on'); - set(handles.CheckS2NEG,'Visible','on'); - CheckS2POS_Callback(handles.CheckS2POS,eventdata,handles); - - set(handles.Seed2Text,'Visible','on'); - - % Same for 3 seeds - if handles.n_seed > 2 - set(handles.CheckS3POS,'Visible','on'); - set(handles.CheckS3NEG,'Visible','on'); - CheckS3POS_Callback(handles.CheckS3POS,eventdata,handles); - - set(handles.Seed3Text,'Visible','on'); - - rectangle('Position',[32 -10 6 8],'Curvature',[0.8 0.8],'Parent',handles.FancyCircles); - rectangle('Position',[31 -5 8 4],'Curvature',[0.8 0.8],'EdgeColor','none','FaceColor','w','Parent',handles.FancyCircles); - - set(handles.S_SEED3,'Visible','on'); - end - - % Entered if we have just one seed - else - set(handles.SeedPopup,'Enable','off'); - set(handles.SeedPopup,'Value',1); - handles.SeedType = 'Average'; - - handles.seed_display = handles.seed; - - set(handles.CheckS1POS,'Visible','on'); - set(handles.CheckS1NEG,'Visible','on'); - end - - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - - if handles.n_seed > 1 - rectangle('Position',[20 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - - if handles.n_seed > 2 - rectangle('Position',[40 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - end - end - - % If the seed file is of length n_subjects, then we want a - % subject-specific seed scheme to run - elseif length(filename_seed) == handles.n_subjects{1} - - handles.isSeedSubjectSpecific = 1; - - % Then, we only allow one seed to be considered - handles.n_seed = 1; - - % For each entry (i.e., each subject data), we load the seed - for myindex = 1:length(filename_seed) - File_seed = fullfile(pathname_seed, filename_seed{myindex}); - tmp = load(File_seed); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - - % If the file is of suitable dimensions - if islogical(tmp) && size(tmp,2) == 1 && size(tmp,1) == sum(handles.mask{1}) - - % Then we put it in the handles, enable the plotting button, and - % make the seed selection button green - handles.seed(:,myindex) = tmp; - - handles.Log = CAP_AddToLog(handles.Log,'Seed chosen',{File_seed},{'Seed file'}); - else - errordlg('The file you entered appears to be of wrong dimensions...'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - end - - handles.seed_display = zeros(length(handles.seed(:,1)),1); - - % If we survive all the above, we can see that the seed files are - % good - handles.isSeedOK = true; - - % We also enable to plot the seed results - set(handles.PlotSeedButton,'Enable','on'); - set(handles.PlotSeedButton,'Visible','on'); - - set(handles.S_SEED1,'Visible','on'); - - set(handles.SeedButton,'BackgroundColor', [101,140,196]/255); - - set(handles.SeedPopup,'Enable','off'); - set(handles.SeedPopup,'Value',1); - handles.SeedType = 'Average'; - set(handles.CheckS1POS,'Visible','on'); - set(handles.CheckS1NEG,'Visible','on'); - - % Creates the seed information to plot in the subject-specific case - for idx_seed = 1:size(handles.seed,2) - - handles.seed_display = handles.seed_display + handles.seed(:,idx_seed); - end - - handles.seed_display = handles.seed_display/handles.n_subjects{1}; - - % We can now go through the next parts of the analysis, so we - % enable the related buttons - set(handles.TPSelectionButton,'Enable','on'); - set(handles.SeedMapPushButton,'Enable','on'); - - set(handles.TPSelectionButton,'Visible','on'); - set(handles.SeedMapPushButton,'Visible','on'); - - set(handles.PRadio,'Visible','on'); - set(handles.TRadio,'Visible','on'); - set(handles.uibuttongroup7,'Visible','on'); - set(handles.TText,'Visible','on'); - set(handles.TMotText,'Visible','on'); - set(handles.TEdit,'Visible','on'); - set(handles.TMotEdit,'Visible','on'); - - % We also see the displays for entering seed specifications - set(handles.SeedPopup,'Visible','on'); - - handles.Log = CAP_AddToLog(handles.Log,'Correct subject-specific seed data entered',{handles.n_seed},{'Seed amount'}); - - handles.seed_display = zeros(length(handles.seed(:,1)),1); - - set(handles.CheckS1POS,'Visible','on'); - set(handles.CheckS1NEG,'Visible','on'); - CheckS1POS_Callback(handles.CheckS1POS,eventdata,handles); - - set(handles.Seed1Text,'Visible','on'); - - set(handles.SeedPlusText,'Visible','on'); - set(handles.SeedMinusText,'Visible','on'); - - rectangle('Position',[0 0 10 10],'Curvature',[1 1],'FaceColor',[150,48,48]/255,'EdgeColor','none','Parent',handles.FancyCircles); - - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - - else - errordlg('Problem with the amount of seed files entered !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - % Updates the limits of the plot - switch handles.n_seed - case 1 - set(handles.FancyCircles,'xlim',[-10 10]); - set(handles.FancyCircles,'ylim',[-10 10]); - case 2 - set(handles.FancyCircles,'xlim',[-10 30]); - set(handles.FancyCircles,'ylim',[-10 30]); - case 3 - set(handles.FancyCircles,'xlim',[-10 50]); - set(handles.FancyCircles,'ylim',[-10 50]); - end - -else - errordlg('You did not enter a seed file !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); -end - -guidata(hObject, handles); - - - -% Executes when clicking on 'Plot Seed' -function PlotSeedButton_Callback(hObject, eventdata, handles) - -% Clears the present graph content -cla(handles.SeedGraphX); -cla(handles.SeedGraphZ); - -% Plots the slices within the graph windows -handles.SeedGraphX = plot_slice(handles.seed_display,get(handles.TVIS_Slider,... - 'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(handles.SliderX,... - 'Value'),handles.SeedGraphX); - -handles.SeedGraphZ = plot_slice(handles.seed_display,get(handles.TVIS_Slider,... - 'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SliderZ,... - 'Value'),handles.SeedGraphZ); - -% Sets the sliders to visible -set(handles.SliderX,'Visible','on'); -set(handles.SliderZ,'Visible','on'); - -% Sets the text values at the ones of the sliders -set(handles.XCoordText,'String',['X: ',sprintf('%.2f',get(handles.SliderX,'Value'))]); -set(handles.ZCoordText,'String',['Z: ',sprintf('%.2f',get(handles.SliderZ,'Value'))]); - -% Sets the visibility of the slider texts to on -set(handles.XCoordText,'Visible','on'); -set(handles.ZCoordText,'Visible','on'); - -handles.Log = CAP_AddToLog(handles.Log,'Seed plots activated'); - -guidata(hObject, handles); - - - - - -%% Seed sliders interactions -% For the below functions, the goal is to change the value of the slider -% textboxes when the sliders are moved, and to update the graph display -% accordingly. For this purpose, cla is used to clear graph content prior -% to a new display - -% Executes on slider movement. -function SliderX_Callback(hObject, eventdata, handles) - -% Clears the content of the graph -cla(handles.SeedGraphX); - -% Gets the MNI slice coordinate value associated to the new display -set(handles.XCoordText,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Slice plotting itself; 1.5 is the color past which the display saturates -handles.SeedGraphX = plot_slice(handles.seed_display,get(handles.TVIS_Slider,... - 'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),... - handles.SeedGraphX); - -guidata(hObject, handles); - - - -% Executes during object creation, after setting all properties. -function SliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -guidata(hObject, handles); - - - -% Executes on slider movement. -function SliderZ_Callback(hObject, eventdata, handles) - -cla(handles.SeedGraphZ); -set(handles.ZCoordText,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); -handles.SeedGraphZ = plot_slice(handles.seed_display,get(handles.TVIS_Slider,... - 'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),... - handles.SeedGraphZ); - -guidata(hObject, handles); - - - -% Executes during object creation, after setting all properties. -function SliderZ_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -guidata(hObject, handles); - - - - - -%% Seed Map Computation Button -% When pressing on this button, classical seed maps are computed for the -% population of subjects chosen as the reference one in the loading part. -% The last entered seed is used - -function SeedMapPushButton_Callback(hObject, eventdata, handles) - -% Computes seed maps for each subject and for the population, using the -% data from the chosen reference population -[~,handles.AvgSeedMap] = CAP_Compute_SeedMap(handles.TC{handles.ReferencePopulation},handles.seed,handles.isSeedSubjectSpecific); - -% Graphical displays - -% Making the plots, texts and sliders visible -set(handles.SeedMapX,'Visible','on'); -set(handles.SeedMapZ,'Visible','on'); - -set(handles.SeedMap_SliderX,'Visible','on'); -set(handles.SeedMap_SliderZ,'Visible','on'); -set(handles.SeedMapSliderX,'Visible','on'); -set(handles.SeedMapSliderZ,'Visible','on'); - -set(handles.TSeed_Slider,'Visible','on'); -set(handles.TSeed,'Visible','on'); -set(handles.ColorbarSeed,'Visible','on'); - -% Writing down the text with current MNI coordinates -set(handles.SeedMap_SliderX,'String',['X: ',sprintf('%.2f',get(handles.SeedMapSliderX,'Value'))]); -set(handles.SeedMap_SliderZ,'String',['Z: ',sprintf('%.2f',get(handles.SeedMapSliderZ,'Value'))]); - -% Clears previous plot contents (in case we want to re-plot after changing -% the seed) -cla(handles.SeedMapX); -cla(handles.SeedMapZ); - -% Plots new slices -handles.SeedMapX = plot_slice(handles.AvgSeedMap,0.25,1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(handles.SeedMapSliderX,'Value'),handles.SeedMapX); -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,0.25,1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SeedMapSliderZ,'Value'),handles.SeedMapZ); - -% Adds the colorbar for the seed maps (between -1 and 1) -handles.ColorbarSeed = Create_CAP_colorbar(-1,1,0.5,get(handles.TSeed_Slider,'Value'),'',handles.ColorbarSeed,'Horizontal','div','RdBu',1000); - -handles.Log = CAP_AddToLog(handles.Log,'Seed maps displayed'); - -guidata(hObject,handles); - - - - - -%% Slider Controls (MNI coordinates) -% We want to reload the seed images with the new parameters when changing a -% slider, so we clear the previous display, change the text summarizing the -% MNI coordinate where we stand, and plot the new image - -function SeedMapSliderX_Callback(hObject, eventdata, handles) - -% Clears graphs -cla(handles.SeedMapX); - -% Changes slider texts -set(handles.SeedMap_SliderX,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Plots new slices -handles.SeedMapX = plot_slice(handles.AvgSeedMap,get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),handles.SeedMapX); - -guidata(hObject, handles); - - - -function SeedMapSliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - - -function SeedMapSliderZ_Callback(hObject, eventdata, handles) - -cla(handles.SeedMapZ); - -% Changes slider texts -set(handles.SeedMap_SliderZ,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Plots new slices -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),handles.SeedMapZ); - -guidata(hObject, handles); - - - -% --- Executes during object creation, after setting all properties. -function SeedMapSliderZ_CreateFcn(hObject, eventdata, handles) -% hObject handle to SeedMapSliderZ (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - - - - -%% Slider controls (visualization threshold) -% We want to replot and modify the colorbar according to the visualization -% threshold that we select (and also change the text) - -function TSeed_Slider_Callback(hObject, eventdata, handles) - -% Clears previous plot contents -cla(handles.SeedMapX); -cla(handles.SeedMapZ); - -% Plots new slices (average seed maps) -handles.SeedMapX = plot_slice(handles.AvgSeedMap,get(hObject,'Value'),1,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',... - get(handles.SeedMapSliderX,'Value'),handles.SeedMapX); - -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,get(hObject,'Value'),1,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',... - get(handles.SeedMapSliderZ,'Value'),handles.SeedMapZ); - -% Modifies the text -set(handles.TSeed,'String',['Tv: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Clears and replots the colorbar -cla(handles.ColorbarSeed); -handles.ColorbarSeed = Create_CAP_colorbar(-1,1,0.5,get(hObject,'Value'),'',handles.ColorbarSeed,'Horizontal','div','RdBu',1000); - -guidata(hObject,handles); - - - -function TSeed_Slider_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - - - - -%% Motion parameter entry -% In the following, we have the functions controling the motion threshold -% (Power's FD) value - -function TMotEdit_Callback(hObject, eventdata, handles) - -% If we enter a reasonable value, it is taken as a new threshold -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 0.5) - handles.Tmot = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid motion threshold value entered',{handles.Tmot},{'Motion threshold value'}); - -% If we set something wrong again, we set the threshold value back to the -% default of 0.5 -else - set(hObject,'BackgroundColor', [203,146,146]/255); - handles.Tmot = 0.5; -end - -guidata(hObject, handles); - - - -% When clicking on the motion button -function handles = TMotEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject, handles); - - - -% When the object is created -function handles = TMotEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','r'); -end - -guidata(hObject, handles); - - - - - -%% Frame selection parameter entry -% What comes below describes the control of the frame selection threshold -% value entered by the user - -% Threshold for selection of the frames to keep -function TEdit_Callback(hObject, eventdata, handles) - -% If we enter a reasonable value, it is taken as the new threshold -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.T = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid (de)activation threshold entered',{handles.T},{'Threshold value'}); - -% If we set something wrong again, we set the threshold value back to the -% default of 0.5 -else - set(hObject,'BackgroundColor',[203,146,146]/255); - handles.T = 0.5; -end - -guidata(hObject, handles); - - - -% When the object is created -function handles = TEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end -guidata(hObject, handles); - - - -% When clicking on it -function TEdit_ButtonDownFcn(hObject,eventdata,handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - - - -%% Frame selection mode control buttons -% The below code is run when the user wishes to change between frame -% selection modes - -% If we select threshold, we update the Selmode accordingly -function TRadio_Callback(hObject, eventdata, handles) - -set(handles.TText,'String','T [-]'); -handles.SelMode = 'Threshold'; - -handles.Log = CAP_AddToLog(handles.Log,'Changed time points selection scheme',{handles.SelMode},{'Selected mode'}); - -guidata(hObject,handles); - - - -% Same for percentage -function PRadio_Callback(hObject, eventdata, handles) - -set(handles.TText,'String','P [%]'); -handles.SelMode = 'Percentage'; - -handles.Log = CAP_AddToLog(handles.Log,'Changed time points selection scheme',{handles.SelMode},{'Selected mode'}); - -guidata(hObject,handles); - - - - - -%% Time points selection control -% When clicking on the select time points button, the frames matching the -% provided thresholds for scrubbing and for frame retention are selected. -% Both activation and deactivation frames are selected. This is performed -% on all the loaded populations of subjects - -% Upon clicking on the 'Select time points' button -function TPSelectionButton_Callback(hObject, eventdata, handles) - -% Clears the current plot display (for the case of having already computed -% something before with other parameters) -cla(handles.TPViolin); - -% Performs the analysis to extract frames of activity for all loaded -% populations (done for each dataset) -for n_ds = 1:handles.n_datasets - % Xonp and Xonn contain the frames (deactivation frames have been - % switched in sign, so that deactivation is positive) - [handles.Xonp{n_ds},p,Indices,... - handles.idx_sep_seeds{n_ds}] = CAP_find_activity(handles.TC{n_ds},... - handles.seed,handles.T,handles.FD{n_ds},handles.Tmot,... - handles.SelMode,handles.SeedType,handles.SignMatrix,handles.isSeedSubjectSpecific); - - % Percentage of retained frames across subjects - handles.RetainedPercentage{n_ds} = p(3,:); - - % Indices of the frames that have been retained (used later for metrics - % computations) - handles.FrameIndices{n_ds} = Indices; -end - -% Enables to go to the next step of the analysis and cluster the extracted -% frames -set(handles.ClusterButton,'Enable','on'); -set(handles.CCButton,'Enable','on'); - -set(handles.ClusterButton,'Visible','on'); -set(handles.CCButton,'Visible','on'); - -% Sets related displays to visible -set(handles.CAP_Kmax,'Visible','on'); -set(handles.CAP_PPC,'Visible','on'); -set(handles.CAP_N,'Visible','on'); -set(handles.CAP_K,'Visible','on'); -set(handles.CAP_PP,'Visible','on'); -set(handles.CAP_PN,'Visible','on'); - -set(handles.KRange_Edit,'Visible','on'); -set(handles.PCC_Edit,'Visible','on'); -set(handles.ClusterEdit,'Visible','on'); -set(handles.ClusterRepEdit,'Visible','on'); -set(handles.ClusterPpEdit,'Visible','on'); -set(handles.ClusterPnEdit,'Visible','on'); - -tmp_toplot = ConcatMat(handles.RetainedPercentage,handles.n_datasets,1,handles.n_subjects,'FD'); - -% Displays the violin plot of subject scrubbing percentage for the -% reference population -[~,~,handles.TPViolin] = MakeViolin(tmp_toplot,handles.TPViolin,{' '},'Frames ret. [%]',handles.PopColor,handles.n_datasets,1); -set(handles.TPViolin,'Visible','on'); - -clear tmp_toplot - -handles.Log = CAP_AddToLog(handles.Log,'Time points selected',{['1 to ',num2str(handles.n_datasets)],handles.SelMode,handles.T,handles.Tmot},{'Datasets indices','Selection mode','Activation threshold','Motion threshold'}); - -guidata(hObject, handles); - - - - - -%% Data saving and loading -% The functions below are summoned when the user wishes to save his/her -% data into a MATLAB structure, or to load previously processed data (until -% the end of spatio-temporal selection) and attempt clustering computations -% and CAP generation - -% Save folder change function -function SaveFolderButton_Callback(hObject, eventdata, handles) - -% Selection of a directory -[dirname]=uigetdir('*.*','Please select a save directory'); -handles.savedir = dirname; - -% If the user has indeed chosen a directory, we set it as the new save -% folder -if ~isequal(dirname,0) - set(handles.SaveFolderText,'String',handles.savedir); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Save folder changed',... - {handles.savedir},... - {'Save folder'}); -else - errordlg('Please select a directory !'); -end - -guidata(hObject,handles); - -% Upon clicking on the 'SAVE' button, the data will be saved entirely under -% a file name partly chosen by the user and partly depending on the present -% date and time -function SaveButton_Callback(hObject, eventdata, handles) - -% Upon pressing the save button, we want to save all the important -% information into a big matlab structure -SAVED = []; - -% General information on the project -SAVED.ProjectInfo.title = handles.project_title; -SAVED.ProjectInfo.date = date; - -% Name of the files that were loaded -SAVED.SubjData.SubjFileNames = handles.SubjNames; -SAVED.SubjData.MotFileNames = handles.MotName; - -% Dimension over time and voxels of the files analyzed -SAVED.SubjData.Dimensions.TP = handles.SubjSize.TP; -SAVED.SubjData.Dimensions.VOX = handles.SubjSize.VOX; - -% Number of subjects considered -SAVED.SubjData.n_subjects = handles.n_subjects; - -% TR of the experiment -SAVED.SubjData.TR = handles.TR; - -% Information about the NIFTI files used (dimensions, mapping between real -% world and index) -SAVED.BrainData.brain_info = handles.brain_info; - -% Mask that was used on the considered data -SAVED.BrainData.mask = handles.mask; - -% Seed used for the analysis -SAVED.BrainData.seed = handles.seed; - -% Motion threshold and activation threshold used in time points selection -SAVED.TPSelData.Tmot = handles.Tmot; -SAVED.TPSelData.T = handles.T; - -% Type of frame selection used -SAVED.TPSelData.SelMode = handles.SelMode; - -% Frames that were considered in the clustering process -% SAVED.TPSelData.Act = handles.Xonp; - -% Type of seed computation chosen ('Avg','Union','Intersection') -SAVED.TPSelData.SeedType = handles.SeedType; - -% Indices, for each seed used, of the retained frames across subjects -SAVED.TPSelData.idx_sep_seeds = handles.idx_sep_seeds; - -% Percentage frames retained for the clustering -SAVED.TPSelData.PercRetained = handles.RetainedPercentage; - -% Computed seed maps (average and subject-wise) -SAVED.SeedMap.AvgMap = handles.AvgSeedMap; - -% Parameters used for clustering -SAVED.ClusterData.N = handles.n_rep; -SAVED.ClusterData.K = handles.K; -SAVED.ClusterData.Pp = handles.Pp; -SAVED.ClusterData.Pn = handles.Pn; - -% CAP data -SAVED.ClusterData.CAPs = handles.CAP; -SAVED.ClusterData.StdCAPs = handles.STDCAP; -SAVED.ClusterData.idx = handles.idx; - -% Computed metrics -SAVED.Metrics.TPM = handles.TPM; -SAVED.Metrics.Counts = handles.Counts; -SAVED.Metrics.Number = handles.Number; -SAVED.Metrics.Avg_Duration = handles.Avg_Duration; -SAVED.Metrics.Duration = handles.Duration; -SAVED.Metrics.TM = handles.TM; -SAVED.Metrics.SeedFrac = handles.sfrac; - -%[tmp_date,tmp_date2] = strtok(date,'-'); -%[tmp_date2,tmp_date3] = strtok(tmp_date2,'-'); -%tmp_date3 = strtok(tmp_date3,'-'); - -% Name that will be given to the saved files -% fancy_name = [handles.project_title,'_',tmp_date,'_',tmp_date2,'_',tmp_date3,'_',... -% num2str(hour(now)),'_',num2str(minute(now)),'_',... -% num2str(round(second(now)))]; - -fancy_name = [handles.project_title]; - -% Saves NIFTI files storing the CAPs (already 'normalized'), in MNI space -CAPToNIFTI(handles.CAP./handles.STDCAP',... - handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.savedir,['CAP_NIFTI_',fancy_name]); - -% Saves the different variables from the program -save(fullfile(handles.savedir,fancy_name),'SAVED','-v7.3'); - -% Adds the save process to the log -handles.Log = CAP_AddToLog(handles.Log,'Data saved'); - -% Writes a log .txt file with what has been done so far -file_ID = fopen(fullfile(handles.savedir,[fancy_name,'.txt']),'wt'); - -for i = 1:length(handles.Log) - for j = 1:length(handles.Log{i}) - fprintf(file_ID,[handles.Log{i}{j},'\n']); - end - fprintf(file_ID,'\n'); -end - -fclose(file_ID); - -% Clears the structure now that it has been saved -clear SAVED - -guidata(hObject,handles); - - - -% This function is summoned when the user wishes to load previously -% computed data and pursue an analysis -function LoadButton_Callback(hObject, eventdata, handles) - -% We want to verify -[filename1,pathname1]=uigetfile({'*.*','All Files'},... - 'Select struct file to load...','MultiSelect','on'); - - % If the user has indeed entered a file - if ~isequal(filename1,0) || ~isequal(pathname1,0) - - Loaded_File = fullfile(pathname1, filename1); - tmp = load(Loaded_File); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - end - - % Checks that the right fields do exist - try - if tmp.SubjData.n_subjects{1} > 3 &&... - ~isempty(tmp.BrainData.brain_info) &&... - sum(tmp.BrainData.mask{1}) == size(tmp.BrainData.seed,1) && ... - length(tmp.TPSelData.Act{1}) == tmp.SubjData.n_subjects{1} &&... - size(tmp.TPSelData.Act{1}{1},1) == sum(tmp.BrainData.mask{1}) - - handles.brain_info = tmp.BrainData.brain_info; - handles.Xonp = tmp.TPSelData.Act{1}; - handles.mask = tmp.BrainData.mask; - handles.SeedType = tmp.TPSelData.SeedType; - handles.idx_sep_seeds = tmp.TPSelData.idx_sep_seeds; - - % Makes the LOAD button green to indicate that loading worked - set(handles.LoadButton,'BackgroundColor',[59 113 86]/255); - - % Enables to go to the next step of the analysis and cluster the extracted - % frames - set(handles.ClusterButton,'Enable','on'); - set(handles.CCButton,'Enable','on'); - - set(handles.ClusterButton,'Visible','on'); - set(handles.CCButton,'Visible','on'); - - % Sets related displays to visible - set(handles.CAP_Kmax,'Visible','on'); - set(handles.CAP_PPC,'Visible','on'); - set(handles.CAP_N,'Visible','on'); - set(handles.CAP_K,'Visible','on'); - set(handles.CAP_PP,'Visible','on'); - set(handles.CAP_PN,'Visible','on'); - - set(handles.KRange_Edit,'Visible','on'); - set(handles.PCC_Edit,'Visible','on'); - set(handles.ClusterEdit,'Visible','on'); - set(handles.ClusterRepEdit,'Visible','on'); - set(handles.ClusterPpEdit,'Visible','on'); - set(handles.ClusterPnEdit,'Visible','on'); - end - catch - errordlg('Problem in loading the data...'); - end - -guidata(hObject,handles); - - - -% Executes when pressing on the 'CLEAR' button for data loading; supposed -% to set everything back to normal (when the window opened) -function handles = ClearDataButton_Callback(hObject, eventdata, handles) - - handles = ClearSection1(eventdata,handles); - handles = ClearSection2(eventdata,handles); - handles = ClearSection3(eventdata,handles); - handles = ClearSection4(eventdata,handles); - - % Loads and sets the brain underlay used for plotting purposes - Underlay = load_nii('Underlay.nii'); - Underlay_mat = [Underlay.hdr.hist.srow_x; Underlay.hdr.hist.srow_y; Underlay.hdr.hist.srow_z; 0 0 0 1]; - Underlay_dim = Underlay.hdr.dime.dim; - Underlay_dim = Underlay_dim(2:4); - handles.Underlay_info.dim = Underlay_dim; - handles.Underlay_info.mat = Underlay_mat; - clear Underlay - clear Underlay_dim - clear Underlay_mat - load('brain.mat'); - assignin('base','brain', brain); - handles.brain = brain; - clear brain - - handles.Log = CAP_AddToLog(handles.Log,'Data cleared'); - -guidata(hObject, handles); - - - -% Clears the content of section 1 only -function handles = ClearSection1(eventdata, handles) - -% Makes 'A. Load data' red again -set(handles.DataButton,'BackgroundColor',[204,146,146]/255); - -% Same for Save folder button -set(handles.SaveFolderButton,'BackgroundColor',[204,146,146]/255); - -% Resets the time point and voxel parameters -handles.SubjSize.TP = -inf; -handles.SubjSize.VOX = -inf; - -% Resets the TR -handles.TR = -inf; -handles.isTROK = false; - -% Resets the reference population -handles.ReferencePopulation = 1; - -handles = ProjectTitleText_CreateFcn(handles.ProjectTitleText,eventdata,handles); - -% Also resets the number of subjects variable and associated text -set(handles.Dimensionality_Text, 'String','_ frames x _ voxels (_)'); -handles.n_subjects = {}; - -% Resets the number of datasets entered to 0 -handles.n_datasets = 0; - -% Empties the data, motion, brain information and mask variables -handles.TC = {}; -handles.FD = {}; -handles.mask = {}; -handles.brain_info = {}; - -% Resets the text related to motion and data files -handles.SubjNames = {}; -handles.MotName = {}; - -% Resets the title and save folder information -handles.Log = {}; - -% Project title, by default 'Untitled' -handles.project_title = 'Untitled'; - -set(handles.LoadButton,'BackgroundColor',[51 75 163]/255); - -% Directory to which data is to be saved (initially loaded as ./SavedData) -handles.savedir = fullfile(pwd,'SavedData'); -set(handles.SaveFolderText,'String',handles.savedir); - -%%%%%%%%%% Putting the loading part (bottom) back to normal %%%%%%%%%%% - -% We also want to set the TR textbox back to its initial state -handles = TR_Entry_CreateFcn(handles.TR_Entry, eventdata, handles); - - - -% Clears the content of section 1 only -function handles = ClearSection2(eventdata, handles) - -% Puts back the seed buttons information to original state -handles.seed = []; -set(handles.SeedButton,'BackgroundColor',[204,146,146]/255); -set(handles.SeedButton,'Enable','off'); -set(handles.PlotSeedButton,'Enable','off'); -set(handles.PlotSeedButton,'Visible','off'); - -% Seed label entries set invisible -set(handles.S_SEED1,'Visible','off'); -set(handles.S_SEED2,'Visible','off'); -set(handles.S_SEED3,'Visible','off'); - -% Puts back the logical defining the type of seed information entered -handles.isSeedSubjectSpecific = 0; - -% Removes graph display for the seed -cla(handles.SeedGraphX); -cla(handles.SeedGraphZ); -set(handles.SeedGraphX,'Visible','off'); -set(handles.SeedGraphZ,'Visible','off'); -set(handles.SliderX,'Visible','off'); -set(handles.SliderZ,'Visible','off'); -set(handles.XCoordText,'Visible','off'); -set(handles.ZCoordText,'Visible','off'); - -%%%%%%%%%%%% Putting the seed map part back to normal %%%%%%%%%%%%%%%%%%% - -% Resets the variable containing the seed maps of the subjects -handles.AvgSeedMap = []; - -% Not clickable anymore -set(handles.SeedMapPushButton,'Enable','off'); -set(handles.SeedMapPushButton,'Visible','off'); - -% Resets colorbar display -handles = ResetGraphDisplay(handles.ColorbarSeed,handles); - -% Makes the slider and the text linked to slider of the seed map threshold -% back to invisible -set(handles.TSeed_Slider,'Visible','off'); -set(handles.TSeed,'Visible','off'); - -% Resets graphs with seed map plots -handles = ResetGraphDisplay(handles.SeedMapX,handles); -handles = ResetGraphDisplay(handles.SeedMapZ,handles); - -% Resets associated sliders -set(handles.SeedMapSliderX,'Visible','off'); -set(handles.SeedMapSliderZ,'Visible','off'); - -% Resets associated slider texts -set(handles.SeedMap_SliderX,'Visible','off'); -set(handles.SeedMap_SliderZ,'Visible','off'); - -% Resets the circles plot -handles = ResetGraphDisplay(handles.FancyCircles,handles); - -% Sets the associated text back to invisible -set(handles.SeedPlusText,'Visible','off'); -set(handles.SeedMinusText,'Visible','off'); -set(handles.Seed1Text,'Visible','off'); -set(handles.Seed2Text,'Visible','off'); -set(handles.Seed3Text,'Visible','off'); - -% Puts the seed boxes back to not visible -set(handles.CheckS1POS,'Visible','off'); -set(handles.CheckS2POS,'Visible','off'); -set(handles.CheckS3POS,'Visible','off'); -set(handles.CheckS1NEG,'Visible','off'); -set(handles.CheckS2NEG,'Visible','off'); -set(handles.CheckS3NEG,'Visible','off'); - -set(handles.TPSelectionButton,'Enable','off'); -set(handles.TPSelectionButton,'Visible','off'); - -set(handles.PRadio,'Visible','off'); -set(handles.TRadio,'Visible','off'); -set(handles.uibuttongroup7,'Visible','off'); -set(handles.TText,'Visible','off'); -set(handles.TMotText,'Visible','off'); -set(handles.TEdit,'Visible','off'); -set(handles.TMotEdit,'Visible','off'); - -% Resets the frame selection mode -handles.SelMode = 'Threshold'; - -% Invisible Seed type list -set(handles.SeedPopup,'Visible','off'); - -% Reinitializes motion and the motion box -handles.Tmot = 0.5; -handles = TMotEdit_CreateFcn(handles.TMotEdit,eventdata,handles); - -% Reinitializes frame selection threshold and the linked box -handles.T = 0.5; -handles = TEdit_CreateFcn(handles.TEdit,eventdata,handles); - -% Resets the frame and percentage retention variables -handles.Xonp = {}; -handles.Xonn = {}; -handles.RetainedPercentage = {}; -handles.FrameIndices = {}; - -% Resets the variables indexing seed selection time points retained -handles.idx_sep_seeds = {}; -handles.sfrac = []; - -% Resets the violin plot with percentage retained frames -handles = ResetGraphDisplay(handles.TPViolin,handles); - - - -% Clears the content of section 3 only -function handles = ClearSection3(eventdata, handles) - -set(handles.ClusterButton,'Enable','off'); -set(handles.CCButton,'Enable','off'); -set(handles.AssignButton,'Enable','off'); -set(handles.AssignButton,'Visible','off'); - -set(handles.CCPlot,'Visible','off'); -cla(handles.CCPlot); - -set(handles.CAP_TP,'Visible','off'); -set(handles.Percentile_Edit,'Visible','off'); - -set(handles.CAP_Kmax,'Visible','off'); -set(handles.CAP_PPC,'Visible','off'); -set(handles.CAP_N,'Visible','off'); -set(handles.CAP_K,'Visible','off'); -set(handles.CAP_PP,'Visible','off'); -set(handles.CAP_PN,'Visible','off'); - -set(handles.KRange_Edit,'Visible','off'); -set(handles.PCC_Edit,'Visible','off'); -set(handles.ClusterEdit,'Visible','off'); -set(handles.ClusterRepEdit,'Visible','off'); -set(handles.ClusterPpEdit,'Visible','off'); -set(handles.ClusterPnEdit,'Visible','off'); - -% Resets the consensus clustering parameter input boxes -handles = KRange_Edit_CreateFcn(handles.KRange_Edit,eventdata,handles); -handles = PCC_Edit_CreateFcn(handles.PCC_Edit,eventdata,handles); - -% Resets the parameter input boxes -handles = ClusterEdit_CreateFcn(handles.ClusterEdit,eventdata,handles); -handles = ClusterRepEdit_CreateFcn(handles.ClusterRepEdit,eventdata,handles); -handles = ClusterPpEdit_CreateFcn(handles.ClusterPpEdit,eventdata,handles); -handles = ClusterPnEdit_CreateFcn(handles.ClusterPnEdit,eventdata,handles); -handles = Percentile_Edit_CreateFcn(handles.Percentile_Edit,eventdata,handles); - -% Resets the consensus clustering parameters themselves -handles.Kmax = 12; -handles.PCC = 80; - -set(handles.CCButton,'Visible','off'); -set(handles.ClusterButton,'Visible','off'); - -set(handles.PIE_S1,'Visible','off'); -set(handles.PIE_S2,'Visible','off'); -set(handles.PIE_S3,'Visible','off'); -set(handles.PIE_S1S2,'Visible','off'); -set(handles.PIE_S2S3,'Visible','off'); -set(handles.PIE_S1S3,'Visible','off'); -set(handles.PIE_S1S2S3,'Visible','off'); - -% Resets the parameters themselves -handles.K = 5; -handles.n_rep = 20; -handles.Pp = 100; -handles.Pn = 100; -handles.percentile = 5; - -% Resets the CAP parameters (CAPs, standard deviation within CAPs and -% indices of the CAPs to which all retained frames were assigned) -handles.CAP = []; -handles.STDCAP = []; -handles.idx = {}; - -% Resets the graph display of the CAP colorbar -handles = ResetGraphDisplay(handles.ColorbarCAP,handles); - -% Reset all graph displays for the CAPs -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z}; -tmpF = {handles.CAP1_Frames,handles.CAP2_Frames,handles.CAP3_Frames,handles.CAP4_Frames,handles.CAP5_Frames}; - - -for i_CAP = 1:5 - set(tmpF{i_CAP},'Visible','off'); - handles = ResetGraphDisplay(tmpX{i_CAP},handles); - handles = ResetGraphDisplay(tmpY{i_CAP},handles); - handles = ResetGraphDisplay(tmpZ{i_CAP},handles); -end - -% Resets the sliders and the textboxes for the CAPs -set(handles.CAP_SliderX,'Visible','off'); -set(handles.CAP_SliderY,'Visible','off'); -set(handles.CAP_SliderZ,'Visible','off'); -set(handles.CAP_XC,'Visible','off'); -set(handles.CAP_YC,'Visible','off'); -set(handles.CAP_ZC,'Visible','off'); - -% Resets the slider and textbox for the CAPs visualization threshold -set(handles.TVIS_Slider,'Visible','off'); -set(handles.TVIS,'Visible','off'); - -% Resets the pie charts -handles = ResetGraphDisplay(handles.pie1,handles); -handles = ResetGraphDisplay(handles.pie2,handles); -handles = ResetGraphDisplay(handles.pie3,handles); -handles = ResetGraphDisplay(handles.pie4,handles); -handles = ResetGraphDisplay(handles.pie5,handles); - -handles = ResetGraphDisplay(handles.ColorbarSimMat,handles); -handles = ResetGraphDisplay(handles.CAP_Mat,handles); - - - -% Clears the content of section 4 only -function handles = ClearSection4(eventdata, handles) - -set(handles.MetricsButton,'Enable','off'); -set(handles.MetricsButton,'Visible','off'); - -% Resets the metrics variables -handles.TPM = {}; -handles.Counts = {}; -handles.Number = {}; -handles.Avg_Duration = {}; -handles.Duration = {}; -handles.TM = {}; -handles.TPMCum = {}; - -% Set the sliding lists of subjects invisible again -set(handles.SubjectMenuMetrics,'Visible','off'); -set(handles.StateMenu,'Visible','off'); - -% Resets the colorbars from the metrics part -handles = ResetGraphDisplay(handles.ColorbarTransMat,handles); - -% Resets all the graphs from the metrics part -handles = ResetGraphDisplay(handles.TMGraph,handles); -handles = ResetGraphDisplay(handles.TM_Subject,handles); -handles = ResetGraphDisplay(handles.DynStates,handles); -handles = ResetGraphDisplay(handles.CumStates,handles); -handles = ResetGraphDisplay(handles.ViolinCounts,handles); -handles = ResetGraphDisplay(handles.ViolinCountsFrac,handles); -handles = ResetGraphDisplay(handles.ViolinNumber,handles); -handles = ResetGraphDisplay(handles.ViolinDuration,handles); - -% Removes all the labels linked to Metrics displays -set(handles.DS_Scrubbed,'Visible','off'); -set(handles.DS_NotSelected,'Visible','off'); -set(handles.DS_Unassigned,'Visible','off'); - -tmp = {handles.DS_CAP1,handles.DS_CAP2,handles.DS_CAP3,handles.DS_CAP4,... - handles.DS_CAP5,handles.DS_CAP6,handles.DS_CAP7,handles.DS_CAP8,... - handles.DS_CAP9,handles.DS_CAP10,handles.DS_CAP11,handles.DS_CAP12}; - -for i = 1:length(tmp) - set(tmp{i},'Visible','off'); -end - -clear tmp - -tmp = {handles.V_POP1,handles.V_POP2,handles.V_POP3,handles.V_POP4}; - -for i = 1:length(tmp) - set(tmp{i},'Visible','off'); -end - -clear tmp - - -% The following functions enable to modify the text of the project title -function ProjectTitleText_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - -function handles = ProjectTitleText_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function ProjectTitleText_Callback(hObject, eventdata, handles) - -% If we have entered a valid string, then we name the project as such -if ~isempty((get(hObject,'String'))) - handles.project_title = get(hObject,'String'); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid project title entered',{handles.project_title},{'New project title'}); - -% If we haven't entered anything, the project is just named 'untitled' -else - handles.project_title = 'Untitled'; - set(hObject,'BackgroundColor',[204,146,146]/255); -end - -guidata(hObject, handles); - - - - - -%% Consensus clustering functions to compute optimal K -% The functions below enable to determine the optimal values of cluster -% number into which to disentangle the CAPs data - -% Executes when pressing on the button to run consensus clustering -function CCButton_Callback(hObject, eventdata, handles) - - % Computes the consensus results - [Consensus] = CAP_ConsensusClustering(handles.Xonp{handles.ReferencePopulation},2:handles.Kmax,'items',handles.PCC/100,handles.n_rep,'correlation'); - - % Calculates the quality metrics - [~,Lorena] = ComputeClusteringQuality(Consensus,2:handles.Kmax); - - set(handles.CCPlot,'Visible','on'); - tmp_plot = bar(2:handles.Kmax,1-Lorena,'Parent',handles.CCPlot); - xlabel(get(tmp_plot(1),'Parent'),'Cluster number K'); - ylabel(get(tmp_plot(1),'Parent'),'Stability'); - xlim(get(tmp_plot(1),'Parent'),[2-0.6,handles.Kmax+0.6]); - ylim(get(tmp_plot(1),'Parent'),[0,1]); - custom_cm = cbrewer('seq','Reds',25); - colormap(handles.CCPlot,custom_cm(6:25,:)); - -guidata(hObject,handles); - - - -function KRange_Edit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 1) && (str2double(get(hObject,'String')) <= 12) - handles.Kmax = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid number of Kmax chosen',{handles.K},{'Max cluster number'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.Kmax = 12; -end - -guidata(hObject, handles); - - - -function handles = KRange_Edit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function KRange_Edit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - -function PCC_Edit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 50) && (str2double(get(hObject,'String')) <= 100) - handles.PCC = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentage of items chosen',{handles.K},{'Percentage items to cluster'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.PCC = 12; -end - -guidata(hObject, handles); - - - -function handles = PCC_Edit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function PCC_Edit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - - - -%% Editing of all the CAP generation parameters - -% Number of clusters -function ClusterEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 1) && (str2double(get(hObject,'String')) <= 12) - handles.K = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid number of clusters chosen',{handles.K},{'Number of clusters'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.K = 5; -end - -guidata(hObject, handles); - - - -function handles = ClusterEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function ClusterEdit_ButtonDownFcn(hObject,eventdata,handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - -% Number of k-means repetitions -function ClusterRepEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 50) - handles.n_rep = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid number of replicates chosen',{handles.n_rep},{'Number of replicates'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.n_rep = 20; -end - -guidata(hObject, handles); - - - -function handles = ClusterRepEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function ClusterRepEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - -% Percentage of positive-valued voxels to keep -function ClusterPpEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.Pp = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentage positive voxels chosen',{handles.Pp},{'Percentage positive voxels'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.Pp = 20; -end - -guidata(hObject, handles); - - - -function handles = ClusterPpEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function ClusterPpEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - -% Percentage of negative-valued voxels to keep -function ClusterPnEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.Pn = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentage negative voxels chosen',{handles.Pn},{'Percentage negative voxels'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.Pn = 20; -end - -guidata(hObject, handles); - - - -function handles = ClusterPnEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - - - -function ClusterPnEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - - - - - -%% Clustering control -% When pressing on the 'Cluster' button, we want to run clustering for the -% specified mode (Activation frames, Deactivation frames, or both types of -% frames together), using the previously declared parameters - -% Upon clicking on 'Cluster' -function ClusterButton_Callback(hObject, eventdata, handles) - -% We perform clustering -[handles.CAP,~,handles.STDCAP,handles.idx{handles.ReferencePopulation},... - handles.CorrDist,handles.sfrac] = Run_Clustering(cell2mat(handles.Xonp{handles.ReferencePopulation}),... - handles.K,handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn,handles.n_rep,handles.idx_sep_seeds{handles.ReferencePopulation},handles.SeedType); - -% Makes the sliders visible, and the related text too (CAP MNI coordinates) -set(handles.CAP_SliderX,'Visible','on'); -set(handles.CAP_SliderY,'Visible','on'); -set(handles.CAP_SliderZ,'Visible','on'); -set(handles.CAP_XC,'Visible','on'); -set(handles.CAP_YC,'Visible','on'); -set(handles.CAP_ZC,'Visible','on'); -set(handles.CAP_XC,'String',['X: ',sprintf('%.2f',get(handles.CAP_SliderX,'Value'))]); -set(handles.CAP_YC,'String',['Y: ',sprintf('%.2f',get(handles.CAP_SliderY,'Value'))]); -set(handles.CAP_ZC,'String',['Z: ',sprintf('%.2f',get(handles.CAP_SliderZ,'Value'))]); - -% Computation of the similarity -SimMat = corr(handles.CAP',handles.CAP'); -SimMat(isnan(SimMat))=0; - -% Graph set visible, and plotting -handles = ResetGraphDisplay(handles.CAP_Mat,handles); -set(handles.CAP_Mat,'Visible','on'); -imagesc(SimMat,'Parent',handles.CAP_Mat); - -tmp_cb2 = cbrewer('div','RdBu',1000); - -colormap(handles.CAP_Mat,flipud(tmp_cb2)); - -% Correlation ranges from -1 to 1, so this is what we make the graph -% colorbar vary within. We also make the graph square and remove the axes -caxis(handles.CAP_Mat,[-1 1]); -axis(handles.CAP_Mat,'square','on'); -axis(handles.CAP_Mat,'off'); - -% Addition of the colorbar just below -set(handles.ColorbarSimMat,'Visible','on'); -handles.ColorbarSimMat = Create_CAP_colorbar(-1,1,0.5,0,'',... - handles.ColorbarSimMat,'Vertical','div','RdBu',1000); - -% If using the 'Intersection' option... -if strcmp(handles.SeedType,'Intersection') - - % Custom colormap - custom_cm = 1/255*[211,36,36;11,170,65;51,75,163;255,255,180;58,221,221;186,59,204;242,242,242]; - - % Graph displays are stored in a common tmp_sfrac cell array - tmp_sfrac = {handles.pie1,handles.pie2,handles.pie3,handles.pie4,... - handles.pie5}; - - % The pie charts for each cluster are created - for cc = 1:min([handles.K,5]) - - % Pie charts - set(tmp_sfrac{cc},'Visible','on'); - for tt = 1:size(handles.sfrac,3) - lab{tt} = ''; - end - - pie(tmp_sfrac{cc},realmin*ones(size(handles.sfrac,3),1)+squeeze(mean(handles.sfrac(:,cc,:),1)),lab); - - switch handles.n_seed - case 1 - errordlg('You managed the impossible, congratulations!'); - case 2 - colormap(tmp_sfrac{cc},flipud(custom_cm)); - set(handles.PIE_S1,'Visible','on'); - set(handles.PIE_S2,'Visible','on'); - set(handles.PIE_S3,'Visible','on'); - case 3 - colormap(tmp_sfrac{cc},flipud(custom_cm)); - set(handles.PIE_S1,'Visible','on'); - set(handles.PIE_S2,'Visible','on'); - set(handles.PIE_S3,'Visible','on'); - set(handles.PIE_S2S3,'Visible','on'); - set(handles.PIE_S1S2,'Visible','on'); - set(handles.PIE_S1S3,'Visible','on'); - set(handles.PIE_S1S2S3,'Visible','on'); - end - end -end - -% Same for the slider for the visualization threshold -set(handles.TVIS,'Visible','on'); -set(handles.TVIS_Slider,'Visible','on'); -set(handles.TVIS,'String',['Tv: ',sprintf('%.2f',get(handles.TVIS_Slider,'Value'))]); - -% Makes the colorbar for the CAPs visible -handles.ColorbarCAP = Create_CAP_colorbar(-1.5,1.5,0.5,get(handles.TVIS_Slider,'Value'),'',handles.ColorbarCAP,'Horizontal','div','RdBu',1000); -set(handles.ColorbarCAP,'Visible','on'); - -% Concatenates all CAP information into metavariables for easier subsequent -% changes -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z}; -tmpF = {handles.CAP1_Frames,handles.CAP2_Frames,handles.CAP3_Frames,handles.CAP4_Frames,handles.CAP5_Frames}; - -% For each CAP... -for i_CAP = 1:min([handles.K,5]) - - % Clears the display for each dimension - cla(tmpX{i_CAP}); - cla(tmpY{i_CAP}); - cla(tmpZ{i_CAP}); - - % Plots the new slice for each dimension - tmpX{i_CAP} = plot_slice(handles.CAP(i_CAP,:),... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'X',get(handles.CAP_SliderX,'Value'),tmpX{i_CAP}); - - tmpY{i_CAP} = plot_slice(handles.CAP(i_CAP,:),... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Y',get(handles.CAP_SliderY,'Value'),tmpY{i_CAP}); - - tmpZ{i_CAP} = plot_slice(handles.CAP(i_CAP,:),... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Z',get(handles.CAP_SliderZ,'Value'),tmpZ{i_CAP}); - - % Sets the frame percentage text visible and at the right value (number - % of frames from a CAP/total frame number, and then percentage that it - % stands for) - set(tmpF{i_CAP},'Visible','on'); - set(tmpF{i_CAP},'String',{[num2str(sum(handles.idx{handles.ReferencePopulation}==i_CAP)),'/',... - num2str(size(handles.idx{handles.ReferencePopulation},1))],[sprintf('%.2f',... - sum(handles.idx{handles.ReferencePopulation}==i_CAP)/size(handles.idx{handles.ReferencePopulation},1)*100),' [%]']}); -end - -% Fills that subject menu with the subjects from the reference population -handles = FillSubjectList(handles.SubjectMenuMetrics,handles); - -% Also enables and fills the state menu -handles = FillStateList(handles.StateMenu,handles); - -% Enables the Metrics button for the next part of the analysis if we -% only deal with one dataset -if handles.n_datasets == 1 - set(handles.MetricsButton,'Enable','on'); - set(handles.MetricsButton,'Visible','on'); - -% Else, we enable the assignment before enabling the metrics computation -elseif handles.n_datasets > 1 - set(handles.AssignButton,'Enable','on'); - set(handles.AssignButton,'Visible','on'); - - set(handles.CAP_TP,'Visible','on'); - set(handles.Percentile_Edit,'Visible','on'); -end - -handles.Log = CAP_AddToLog(handles.Log,'Clustering performed',... - {handles.ReferencePopulation,handles.K,handles.n_rep,handles.Pp,... - handles.Pn},{'Reference group index',... - 'Number of clusters','Number of replicates',... - 'Percentage positive voxels','Percentage negative voxels'}); - -guidata(hObject, handles); - - - - - -%% Frame assignment control -% This button is only enabled after clustering has been performed on the -% reference population. It assigns frames from the other populations to the -% computed CAPs - -% Happens upon clicking on the 'Assign' buttons -function AssignButton_Callback(hObject, eventdata, handles) - -tmp_notref = []; -tmp_computedTPsel = []; - -% For each non-reference dataset... -for n_ds = 1:handles.n_datasets - if n_ds ~= handles.ReferencePopulation - - tmp_notref = [tmp_notref,n_ds]; - - % Attempts to access the frames for a given dataset; if it fails, it - % means we must compute activity. If it works, we do nothing because - % activity has already been computed - try - justtotest = handles.Xonp{n_ds}; - catch - - [handles.Xonp{n_ds},handles.Xonn{n_ds},p,handles.FrameIndices{n_ds},handles.idx_sep_seeds{n_ds}] = ... - CAP_find_activity(handles.TC{n_ds},handles.seed,handles.T,handles.FD{n_ds},handles.Tmot,handles.SelMode,handles.SeedType); - - handles.RetainedPercentage{n_ds} = p(4:5,:); - - tmp_computedTPsel = [tmp_computedTPsel,n_ds]; - end - - try - handles.idx{n_ds} = CAP_AssignFrames(handles.CAP,cell2mat(handles.Xonp{n_ds}),handles.CorrDist,handles.percentile)'; - catch - errordlg('You computed CAPs with a different CAP type compared to the one used now; please use the same CAP type !'); - end - end -end - -% We then enable the computation of metrics -set(handles.MetricsButton,'Enable','on'); -set(handles.MetricsButton,'Visible','on'); - -handles.Log = CAP_AddToLog(handles.Log,'Frame assignment performed',... - {handles.ReferencePopulation,num2str(tmp_computedTPsel),... - num2str(tmp_notref)},{'Reference group index','Group indices for which frames were computed',... - 'Group indices for which frames were assigned'}); - -guidata(hObject, handles); - - - - - -%% Parameter control: percentile to use for frame assignment -% This asks for the percentile to use in frame assignment (i.e. the -% threshold of correlation below which frames are left unassigned) - -function Percentile_Edit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.percentile = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [101,140,196]/255); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentile chosen',{handles.percentile},{'Percentile'}); - -else - set(hObject,'BackgroundColor',[204,146,146]/255); - handles.percentile = 5; -end - -guidata(hObject, handles); - - - -function handles = Percentile_Edit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function Percentile_Edit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject, handles); - - - - - -%% Sliders for CAP visualization (MNI coordinates) -% When changing along a slider, we want to update the graphs and the text of -% the MNI coordinate below the slider - -% X dimension slider -function CAP_SliderX_Callback(hObject, eventdata, handles) - -set(handles.CAP_XC,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X}; - -for i_CAP = 1:min([handles.K,5]) - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject, handles); - - - -function CAP_SliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -guidata(hObject,handles); - - - -% Y dimension slider -function CAP_SliderY_Callback(hObject, eventdata, handles) - -set(handles.CAP_YC,'String',['Y: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y}; - -for i_CAP = 1:min([handles.K,5]) - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject,handles); - - - -function CAP_SliderY_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -guidata(hObject,handles); - - - -% Z dimension slider -function CAP_SliderZ_Callback(hObject, eventdata, handles) - -set(handles.CAP_ZC,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z}; - -for i_CAP = 1:min([handles.K,5]) - - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject,handles); - - - -function CAP_SliderZ_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -guidata(hObject,handles); - - - - - -%% Sliders for threshold visualization (CAP analysis) -% Again, we want to update the slices and the text if we change those -% sliders - -function TVIS_Slider_Callback(hObject, eventdata, handles) - -% The text is changed -set(handles.TVIS,'String',['Tv: ',sprintf('%.2f',get(hObject,'Value'))]); - -% The colorbar graph is modified to suit the new threshold value -cla(handles.ColorbarCAP); -handles.ColorbarCAP = Create_CAP_colorbar(-1.5,1.5,0.5,get(hObject,'Value'),'',handles.ColorbarCAP,'Horizontal','div','RdBu',1000); - -% The brain slices are replotted -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z}; - -for i_CAP = 1:min([handles.K,5]) - - cla(tmpX{i_CAP}); - cla(tmpY{i_CAP}); - cla(tmpZ{i_CAP}); - - tmpX{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(handles.CAP_SliderX,'Value'),tmpX{i_CAP}); - - tmpY{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',get(handles.CAP_SliderY,'Value'),tmpY{i_CAP}); - - tmpZ{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',get(handles.CAP_SliderZ,'Value'),tmpZ{i_CAP}); -end - -guidata(hObject,handles); - - - -function TVIS_Slider_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - - - - -%% Metrics computation control -% When pressing on the 'Compute metrics' button, the different metrics for -% CAP analysis are computed, including: -% - Similarity between CAPs -% - Transition probabilities from a state to the other (average + subject) -% - Sequence of states for each subject -% - Cumulative state sequence for all subjects -% - Counts (number of frames in a state) -% - Number of times entering a state, and duration spent in a state - -function MetricsButton_Callback(hObject, eventdata, handles) - -% All the metrics are computed for all the datasets -for n_ds = 1:handles.n_datasets - if n_ds == handles.ReferencePopulation - tmp_nclust = handles.K; - else - tmp_nclust = handles.K+1; - end - - try - [handles.TPM{n_ds},handles.Counts{n_ds},... - handles.Number{n_ds},handles.Avg_Duration{n_ds},... - handles.Duration{n_ds},handles.TM{n_ds}] =... - Compute_Metrics(handles.idx{n_ds},handles.FrameIndices{n_ds}.kept.active,... - handles.FrameIndices{n_ds}.scrubbed,... - tmp_nclust,handles.TR); - catch - - errordlg('You tried computing metrics using parameter values different from the ones that were employed to generate CAPs; please check !'); - end -end - -handles.Log = CAP_AddToLog(handles.Log,'Metrics computed',... - {handles.n_datasets,handles.K,handles.TR},... - {'Number of datasets','Number of clusters','TR'}); - -tmp_cb = cbrewer('seq','Greys',1000); - -% 2. Transition matrix for all subjects together - -tmp_toplot = squeeze(mean(handles.TM{handles.ReferencePopulation},3)); -tmp_toplot = tmp_toplot(3:end,3:end); - -% Make graph visible and plotting -handles = ResetGraphDisplay(handles.TMGraph,handles); -set(handles.TMGraph,'Visible','on'); -imagesc(tmp_toplot,'Parent',handles.TMGraph); - -colormap(handles.TMGraph,flipud(tmp_cb)); - -clear tmp_toplot - -% Arbitrary setting of probability scale from 0 to 0.03 -caxis(handles.TMGraph,[0 0.03]); -axis(handles.TMGraph,'square','on'); -axis(handles.TMGraph,'off'); - -% 3. Transition matrix for one subject - -tmp_toplot = squeeze(handles.TM{handles.ReferencePopulation}(:,:,get(handles.SubjectMenuMetrics,'Value'))); -tmp_toplot = tmp_toplot(3:end,3:end); - -% makes graph visible and plots the information given by the Subject popup -handles = ResetGraphDisplay(handles.TM_Subject,handles); -set(handles.TM_Subject,'Visible','on'); -imagesc(tmp_toplot,... - 'Parent',handles.TM_Subject); - -colormap(handles.TM_Subject,flipud(tmp_cb)); - -clear tmp_toplot - -% Same setting for the axes as for the average graph -caxis(handles.TM_Subject,[0 0.03]); -axis(handles.TM_Subject,'square','on'); -axis(handles.TM_Subject,'off'); - -% We then create the colorbar for both cases -set(handles.ColorbarTransMat,'Visible','on'); -handles.ColorbarTransMat = Create_CAP_colorbar(0,0.03,0.01,0,'',... - handles.ColorbarTransMat,'Vertical','seq','Greys',1000); - -% Makes the subject menu visible -set(handles.SubjectMenuMetrics,'Visible','on'); - -% 4. Dynamic state plotting - -% Makes the graph visible -handles = ResetGraphDisplay(handles.DynStates,handles); -set(handles.DynStates,'Visible','on'); - -% Concatenates information from the different datasets -tmp_toplot = []; - -for i = 1:handles.n_datasets - tmp_toplot = [tmp_toplot; handles.TPM{i}; 0*ones(5,handles.SubjSize.TP)]; -end -tmp_toplot = tmp_toplot(1:end-5,:); - -custom_cm = cbrewer('qual','Set1',handles.K+1); -custom_cm = [0.05,0.05,0.05;1,1,1;custom_cm]; - -% If the TR has been properly entered, the x-axis is time; else, it depicts -% time index. In any case, we plot the states -if handles.isTROK - imagesc(tmp_toplot,'Parent',handles.DynStates); - colormap(handles.DynStates,(custom_cm)); - xlabel(handles.DynStates,'Time [s]'); -else - imagesc(tmp_toplot,'Parent',handles.DynStates); - colormap(handles.DynStates,(custom_cm)); - xlabel(handles.DynStates,'Time index [-]'); -end - -ylabel(handles.DynStates,'Subjects [-]'); -axis(handles.DynStates,'off'); -caxis(handles.DynStates,[-1,handles.K+1]); - -clear tmp_toplot - -% 5. Cumulative state distributions - -% Makes the graph visible -handles = ResetGraphDisplay(handles.CumStates,handles); -set(handles.CumStates,'Visible','on'); - -for i = 1:handles.n_datasets - % Cumulative distribution for the state that we want to be displayed (i.e. - % the state from the popup menu) - handles.TPMCum{i} = cumsum(handles.TPM{i} == get(handles.StateMenu,'Value'),2); - - % Average of the considered state across subjects - tmp_TPMCum{i} = mean(handles.TPMCum{i},1); -end - -% Similarly as above, we plot time if we have a valid TR; else, we plot -% 'time index' -if handles.isTROK == false - - for i = 1:handles.n_datasets - % We first plot each subject curve - for j = 1:size(handles.TPMCum{i},1) - plot(1:size(handles.TPM{i},2),handles.TPMCum{i}(j,:),'Color',handles.PopColor{1}(i,:),... - 'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - % Then, we plot a bold average across subjects - plot(1:size(handles.TPM{i},2),tmp_TPMCum{i},'Color',handles.PopColor{2}(i,:),... - 'LineWidth',2,'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time index [-]','FontSize',10); - xlim(handles.CumStates,[1,size(handles.TPM{i},2)]); - end -else - for i = 1:handles.n_datasets - for j = 1:size(handles.TPMCum{i},1) - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - handles.TPMCum{i}(j,:),... - 'Color',handles.PopColor{1}(i,:),'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - tmp_TPMCum{i},... - 'LineWidth',2,'Color',handles.PopColor{2}(i,:),'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time [s]','FontSize',10); - xlim(handles.CumStates,[0,(size(handles.TPM{i},2)-1)*handles.TR]); - end -end - - -ylabel(handles.CumStates,'Cumul. sum [-]','FontSize',10); -set(handles.CumStates,'Box','off'); - -% Makes the state menu visible -set(handles.StateMenu,'Visible','on'); - -% 6. Violin plots -% Below, we plot violin plots depicting: -% - Raw counts of state excursions -% - Fractional counts of state excursions -% - Number of times entering a state -% - Duration of state excursions - -% We build the legend used to plot the violins -% leg_viol = cell(handles.K); -for i = 1:handles.K - leg_viol{i} = num2str(i); -end - -% Makes graphs ready -handles = ResetGraphDisplay(handles.ViolinCounts,handles); -set(handles.ViolinCounts,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinCountsFrac,handles); -set(handles.ViolinCountsFrac,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinNumber,handles); -set(handles.ViolinNumber,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinDuration,handles); -set(handles.ViolinDuration,'Visible','on'); - -% Concatenates the values from the different populations -tmp_toplot = ConcatMat(handles.Counts,handles.n_datasets,handles.K,handles.n_subjects,'Raw counts'); - -% Plots the raw count values -[~,~,handles.ViolinCounts] = MakeViolin(tmp_toplot,... - handles.ViolinCounts,leg_viol,'Raw counts [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - -tmp_toplot = ConcatMat(handles.Counts,handles.n_datasets,handles.K,handles.n_subjects,'Normalized counts'); - -% Plots the normalized count values -[~,~,handles.ViolinCountsFrac] = MakeViolin(tmp_toplot,... - handles.ViolinCountsFrac,leg_viol,'Norm counts [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - -tmp_toplot = ConcatMat(handles.Number,handles.n_datasets,handles.K,handles.n_subjects,'Number'); - -% Plots the number of times a state is entered -[~,~,handles.ViolinNumber] = MakeViolin(tmp_toplot,... - handles.ViolinNumber,leg_viol,'Number [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - -% Plots the duration graph -if handles.isTROK - - tmp_toplot = ConcatMat(handles.Avg_Duration,handles.n_datasets,handles.K,handles.n_subjects,'Duration'); - - [~,~,handles.ViolinDuration] = MakeViolin(tmp_toplot,... - handles.ViolinDuration,leg_viol,'Dur. [s]',handles.PopColor,handles.n_datasets,handles.K); - - clear tmp_toplot - -else - errordlg('Not showing duration violin plot as TR was not entered !'); - set(handles.ViolinDuration,'Visible','off'); -end - -% Makes the displays visible -set(handles.DS_Scrubbed,'Visible','on'); -set(handles.DS_Scrubbed,'ForegroundColor',custom_cm(1,:)); - -set(handles.DS_NotSelected,'Visible','on'); -set(handles.DS_NotSelected,'ForegroundColor',[0.9,0.9,0.9]); - -set(handles.DS_Unassigned,'Visible','on'); -set(handles.DS_Unassigned,'ForegroundColor',custom_cm(handles.K+3,:)); - -tmp = {handles.DS_CAP1,handles.DS_CAP2,handles.DS_CAP3,handles.DS_CAP4,... - handles.DS_CAP5,handles.DS_CAP6,handles.DS_CAP7,handles.DS_CAP8,... - handles.DS_CAP9,handles.DS_CAP10,handles.DS_CAP11,handles.DS_CAP12}; - -for i = 1:handles.K - set(tmp{i},'Visible','on'); - set(tmp{i},'ForegroundColor',custom_cm(2+i,:)); -end - -clear tmp - -tmp = {handles.V_POP1,handles.V_POP2,handles.V_POP3,handles.V_POP4}; - -for i = 1:handles.n_datasets - set(tmp{i},'Visible','on'); -end - -clear tmp - -guidata(hObject,handles); - - - - - -%% Subject popup menu control (metrics computation) -% When a new subject is chosen, the display of the transition matrix graph -% is changed - -function SubjectMenuMetrics_Callback(hObject, eventdata, handles) - -% In the case when we have something to plot... -try - % ... we reset the graph display, make the graph visible, and plot - % again - handles = ResetGraphDisplay(handles.TM_Subject,handles); - set(handles.TM_Subject,'Visible','on'); - - tmp_toplot = squeeze(handles.TM{handles.ReferencePopulation}(:,:,get(handles.SubjectMenuMetrics,'Value'))); - tmp_toplot = tmp_toplot(3:end,3:end); - - imagesc(tmp_toplot,'Parent',handles.TM_Subject); - caxis(handles.TM_Subject,[0 0.03]); - axis(handles.TM_Subject,'square','on'); - axis(handles.TM_Subject,'off'); - - tmp_cb = cbrewer('seq','Greys',1000); - colormap(handles.TM_Subject,flipud(tmp_cb)); - - clear tmp_toplot - - handles.Log = CAP_AddToLog(handles.Log,'Subject index changed (metrics)',... - {get(hObject,'Value')},... - {'Subject index'}); - -catch - errordlg('Please recompute metrics for the presently considered population !'); -end - -guidata(hObject,handles); - - - -function SubjectMenuMetrics_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - - - -%% State menu popup control -% When we change our state of interest, we will change the display of the -% cumulative state being displayed - -function StateMenu_Callback(hObject, eventdata, handles) - -handles = ResetGraphDisplay(handles.CumStates,handles); -set(handles.CumStates,'Visible','on'); - -% In the case of a non-null matrix... -if ~isempty(handles.TPM) - - for i = 1:handles.n_datasets - % Cumulative distribution for the state that we want to be displayed (i.e. - % the state from the popup menu) - handles.TPMCum{i} = cumsum(handles.TPM{i} == get(handles.StateMenu,'Value'),2); - - % Average of the considered state across subjects - tmp_TPMCum{i} = mean(handles.TPMCum{i},1); - end - - % Similarly as above, we plot time if we have a valid TR; else, we plot - % 'time index' - if handles.isTROK == false - - for i = 1:handles.n_datasets - % We first plot each subject curve - for j = 1:size(handles.TPMCum{i},1) - plot(handles.TPMCum{i}(j,:),'Color',handles.PopColor{1}(i,:),... - 'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - % Then, we plot a bold average across subjects - plot(tmp_TPMCum{i},'Color',handles.PopColor{2}(i,:),... - 'LineWidth',2,'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time index [-]','FontSize',8); - end - else - for i = 1:handles.n_datasets - for j = 1:size(handles.TPMCum{i},1) - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - handles.TPMCum{i}(j,:),... - 'Color',handles.PopColor{1}(i,:),'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - tmp_TPMCum{i},... - 'LineWidth',2,'Color',handles.PopColor{2}(i,:),'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time [s]','FontSize',8); - end - end - - -ylabel(handles.CumStates,'Cumul. sum [-]','FontSize',8); -set(handles.CumStates,'Box','off'); - -end - -guidata(hObject,handles); - - - -function StateMenu_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - - - -%% General utilities - -% Resets the display of a graph object -function handles = ResetGraphDisplay(Graph,handles) - -cla(Graph); -set(Graph,'Visible','off'); - - - -% Fills the entries of a pop-up menu with 'Subject _' entries from the -% reference population -function handles = FillSubjectList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.n_subjects{handles.ReferencePopulation} - tmp_string{ns} = ['Subject ',num2str(ns)]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - - - -% Fills the entries of a pop-up menu with the different population entries -function handles = FillPopulationList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.n_datasets - tmp_string{ns} = [handles.SubjNames{ns}]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - - - -% Fills the entries of a pop-up menu with the different population entries -function handles = FillStateList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.K - tmp_string{ns} = ['State ',num2str(ns)]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - - - -% Removes NaN-containing lines from a matrix (used for the plotting of -% duration violin plots) -function M2 = DiscardNaN(M) - -% We initialize the output matrix as a void one -M2 = []; - -% For each row, we count the amount of NaN entries; if not equal to zero, -% then we discard the line -for i = 1:size(M,1) - if sum(isnan(M(i,:))) > 0 - else - M2 = [M2;M(i,:)]; - end -end - - - -% Concatenates populations appropriately for Violin plotting -function M2 = ConcatMat(M,n_pop,n_states,n_subjects,type) - -% Creates the data matrix (nan values are used to have the same amount of -% data for each group) -M2 = nan(n_pop*n_states,max(cell2mat(n_subjects))); - -for i = 1:n_pop - - switch type - case 'Raw counts' - - tmp = M{i}.raw.state(:,1:n_states)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Normalized counts' - - tmp = M{i}.frac.state(:,1:n_states)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Number' - - tmp = M{i}(:,3:3+n_states-1)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Duration' - tmp = DiscardNaN(M{i}(:,3:3+n_states-1))'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - case 'FD' - tmp = M{i}; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - end -end diff --git a/CAP_TB_Validation.m b/CAP_TB_Validation.m deleted file mode 100755 index 9a97c75..0000000 --- a/CAP_TB_Validation.m +++ /dev/null @@ -1,144 +0,0 @@ -%% This script intends to validate the CAP toolbox proper functioning with -% simulated data of different types - -%% 1. Determination of ground truth data parameters - -% Number of states that we define -K = 4; - -% Number of voxels (10x10x10) -V = [10 10 10]; - -% For now, the mask keeps all the voxels -mask = logical(ones(prod(V),1)); - -% Number of time points -T = 100; - -% Number of subjects -S = 4; - -% FD is said to be null for now -FD = zeros(T,S); - -% We try a simple brain_info -brain_info.dim = [10 10 10]; -brain_info.mat = [20 0 0 -90; 0 20 0 -90; 0 0 20 -90; 0 0 0 1]; - - -%% 2. Determination of the ground truth co-activation patterns -% For the moment, we select four partially spatially overlapping states: a -% cylinder along Z, a cube along Z, and two stripe patterns - - -% We must first define the four states -Circle = zeros(10,10); -for i = -4.5:4.5 - for j = -4.5:4.5 - if sqrt((i*i+j*j))<3 - Circle(i+5.5,j+5.5)=1; - else - Circle(i+5.5,j+5.5)=0; - end - end -end - -for z = 1:10 - State1(:,:,z) = Circle; -end - -Square = zeros(10,10); -Square(1:5,1:5) = ones(5,5); - -for z = 1:10 - State2(:,:,z) = Square; -end - -Vertical = zeros(10,10); -for j = 1:10 - - if mod(j,2)==0 - Vertical(:,j)=ones(10,1); - end -end - -for z = 1:10 - State3(:,:,z) = Vertical; -end - -Horizontal = zeros(10,10); -for i = 1:10 - - if mod(i,2)==0 - Horizontal(i,:)=ones(1,10); - end -end - -for z = 1:10 - State4(:,:,z) = Horizontal; -end - -State1 = State1(:); -State2 = State2(:); -State3 = State3(:); -State4 = State4(:); - -%% 3. Determination of seed parameters - -% The seeda are created spatially -seed1 = zeros(10,10,10); -seed1(9,9,5) = 1; -seed1 = seed1(:); -seed1 = seed1(mask); -seed1 = logical(seed1); -seed2 = zeros(10,10,10); -seed2(1,5,8) = 1; -seed2 = seed2(:); -seed2 = seed2(mask); -seed2 = logical(seed2); -seed3 = zeros(10,10,10); -seed3(5,5,5) = 1; -seed3 = seed3(:); -seed3 = seed3(mask); -seed3 = logical(seed3); - -State1(seed1) = 1; -State1(seed2) = 0; -State1(seed3) = 1; -State2(seed1) = 0; -State2(seed2) = 1; -State2(seed3) = 0; -State3(seed1) = 1; -State3(seed2) = 1; -State3(seed3) = 1; -State4(seed1) = 0; -State4(seed2) = 1; -State4(seed3) = 1; - -States = {State1,State2,State3,State4}; - -% Now that we defined the four states, we must define time courses for the -% different subjects. We assume that at each time point, only one state can -% be entered -idx = [ones(1,10),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10),3*ones(1,5),4*ones(1,5),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10);... - ones(1,10),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10),3*ones(1,5),4*ones(1,5),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10);... - ones(1,10),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10),3*ones(1,5),4*ones(1,5),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10);... - ones(1,10),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10),3*ones(1,5),4*ones(1,5),3*ones(1,5),4*ones(1,5),ones(1,10),2*ones(1,10),ones(1,10)]; - - -% TC contains the above time courses -TC = cell(1,4); - -for s = 1:S - for t = 1:T - TC{s}(t,:) = States{idx(s,t)}(:)';% + 0.1*rand(1,prod(V)); - end -end - -save('TC','TC'); -save('FD','FD'); -save('mask','mask'); -save('seed1','seed1'); -save('seed2','seed2'); -save('seed3','seed3'); -save('brain_info','brain_info'); \ No newline at end of file diff --git a/CAP_TBsmall.fig b/CAP_TBsmall.fig deleted file mode 100644 index 059bc3e..0000000 Binary files a/CAP_TBsmall.fig and /dev/null differ diff --git a/CAP_TBsmall.m b/CAP_TBsmall.m deleted file mode 100644 index 1d8b5d3..0000000 --- a/CAP_TBsmall.m +++ /dev/null @@ -1,2683 +0,0 @@ -%% This is the script of what is supposed to be a friendly user interface -% for application of co-activation pattern analysis. - -function varargout = CAP_TBsmall(varargin) -% CAP_TBsmall MATLAB code for CAP_TBsmall.fig -% CAP_TBsmall, by itself, creates a new CAP_TBsmall or raises the existing -% singleton*. -% -% H = CAP_TBsmall returns the handle to a new CAP_TBsmall or the handle to -% the existing singleton*. -% -% CAP_TBsmall('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in CAP_TBsmall.M with the given input arguments. -% -% CAP_TBsmall('Property','Value',...) creates a new CAP_TBsmall or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before CAP_TBsmall_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to CAP_TBsmall_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help CAP_TBsmall - -% Last Modified by GUIDE v2.5 03-Mar-2017 13:41:05 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @CAP_TBsmall_OpeningFcn, ... - 'gui_OutputFcn', @CAP_TBsmall_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 -% End initialization code - DO NOT EDIT - -% Executes when the window opens; all handle variables are created at this -% time -function CAP_TBsmall_OpeningFcn(hObject, eventdata, handles, varargin) - -%%%%%%%%%%%%%%%%%%%% -% Path and other miscellaneous settings - -% Adds the paths to the subfolders of the toolbox that will be important -% for the plotting and the analysis -addpath(genpath('./Plotting')); -addpath(genpath('./Analysis')); -addpath(genpath('./DefaultData')); - -% Sets warnings off -warning('off'); - -% Choose default command line output for CAP_TBsmall -handles.output = hObject; - - - -%%%%%%%%%%%%%%%%%%%% -% Data loading - -% TC will contain the time courses of the subjects from the different -% populations -handles.TC = {}; - -% FD contains the traces of framewise displacement for the subjects (n_TP x -% n_subj per cell of the array, one cell per dataset) -handles.FD = {}; - -% Information on the NIFTI files from which the data originate -handles.brain_info = {}; - -% Mask used prior to CAP analysis -handles.mask = {}; - -% Number of datasets added to the interface. A dataset is defined as a -% population of subjects from the same experimental group (e.g. an ensemble -% of subjects suffering from the same disorder) -handles.n_datasets = 0; - -% Stores the number of subjects that have been loaded -handles.n_subjects = {}; - -% SubjNames contains the names of the files from which subject data have -% been sampled (full paths) -handles.SubjNames = {}; - -% MotName contains the name(s) of the file(s) loaded as motion ones -handles.MotName = {}; - -% TP and VOX contain the number of time points (of frames) and of brain -% voxels that are present in the loaded datasets. Those values are -% initialized at -inf, and then take the values of the first file that is -% being loaded if that file looks reasonable dimensionally speaking. In the -% scripts below, it is assumed that all subject populations loaded have a -% similar number of time points and of voxels -handles.SubjSize.TP = -inf; -handles.SubjSize.VOX = -inf; - -% By default, the reference population from which CAPs will be extracted -% will be the first uploaded one -handles.ReferencePopulation = 1; - -% Loads and sets the brain underlay used for plotting purposes -Underlay = load_nii('Underlay.nii'); -Underlay_mat = [Underlay.hdr.hist.srow_x; Underlay.hdr.hist.srow_y; Underlay.hdr.hist.srow_z; 0 0 0 1]; -Underlay_dim = Underlay.hdr.dime.dim; -Underlay_dim = Underlay_dim(2:4); -handles.Underlay_info.dim = Underlay_dim; -handles.Underlay_info.mat = Underlay_mat; -clear Underlay -clear Underlay_dim -clear Underlay_mat -load('brain.mat'); -assignin('base','brain', brain); -handles.brain = brain; -clear brain - -% Handles for the TR -handles.TR = -inf; -handles.isTROK = false; - -%%%%%%%%%%%%%%%%%%%% -% Seed selection and seed maps - -% Seed used for the analysis -handles.seed = []; -handles.seed2 = []; - -% One map per subject -handles.SeedMaps = {}; - -% One average map throughout subjects -handles.AvgSeedMap = []; - -%%%%%%%%%%%%%%%%%%%% -% Time points selection - -% Motion threshold for scrubbing -handles.Tmot = 0.5; - -% Threshold for frame selection in the analysis -handles.T = 0.5; - -% Sets the right text header in front of the frame selection threshold box -% (threshold or retention percentage) -if get(handles.TRadio,'Value') - set(handles.TText,'String','T [-]'); - handles.SelMode = 'Threshold'; -else - set(handles.TText,'String','P [%]'); - handles.SelMode = 'Percentage'; -end - - - -% Activation and deactivation frames kept for all datasets -handles.Xonp = {}; -handles.Xonn = {}; - -% Percentage of frames retained for CAP analysis (discarding both the -% baseline time points and the scrubbed time points) -handles.RetainedPercentage = {}; - -% Indices of the frames that have been retained (i.e. when do they occur in -% the full time course), of baseline frames, and of scrubbed frames -handles.FrameIndices = {}; - -%%%%%%%%%%%%%%%%%%%% -% CAP analysis - -% Number of times that clustering is run -handles.n_rep = 20; - -% Percentage voxels to keep for clustering (positive - Pp - and negative - -% Pn - ones) -handles.Pp = 100; -handles.Pn = 100; - -% Number of clusters to use in the analysis -handles.K = 5; - -% Type of CAPs computed: can take a value of 'Act','Deact' or 'Both' -handles.CAPType = ''; - -% Indices of the CAP to which frames from the reference population and from -% the other populations are assigned -handles.idx = {}; - -% Value of correlation of the control group frame that is the Tper-th least -% close to its CAP -handles.CorrDist = []; - -% Contains the CAPs -handles.CAP = []; - -% Contains the standard deviation for the CAPs -handles.STDCAP = []; - -% Parameters for the GMM -handles.Gamma_GMM = []; -handles.Priors_GMM = []; -handles.Mu_GMM = []; -% This one must be put into a structure to have several sparse matrices -% filling it -handles.Sigma_GMM = {}; - -% Percentile threshold used in frame assignment -handles.percentile = 5; - -%%%%%%%%%%%%%%%%%%%% -% Metrics - -% Will contain the metrics -% State matrix (n_subjects x n_time points) -handles.TPM = {}; - -% State counts (raw and frac) -handles.Counts = {}; - -% Number of times entering a state -handles.Number = {}; - -% Average duration within a state -handles.Avg_Duration = {}; - -% Duration of all the excursions within a state -handles.Duration = {}; - -% Transition probabilities -handles.TM = {}; - -% Cumulative sum of states -handles.TPMCum = {}; - -%%%%%%%%%%%%%%%%%%%% -% General utilities - -% Log containing the different events summoned from the toolbox -handles.Log = {}; - -% Colors used in plotting of all populations -handles.PopColor{1} = [1,0.9,0.4; 0.8, 1.0, 1.0; 0.2, 1, 0.2; 0.9, 0.9, 0.9]; -handles.PopColor{2} = [1, 0, 0.2; 0.2, 0.2, 0.8; 0, 0.4, 0; 0, 0, 0]; - -% Project title, by default 'Untitled' -handles.project_title = 'Untitled'; - -% Directory to which data is to be saved (initially loaded as ./SavedData) -handles.savedir = fullfile(pwd,'SavedData'); -set(handles.SaveFolderText,'String',handles.savedir); - -% Update handles structure -guidata(hObject, handles); - -% --- Outputs from this function are returned to the command line. -function varargout = CAP_TBsmall_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%% SECTION 1: LOADING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Data Button Click - -% Executes when adding a subject population (clicking on 'A. Load data') -function DataButton_Callback(hObject, eventdata, handles) -% Opens up a menu to choose the required files for the analysis; the user -% must select four files: -% 1. Data file -% 2. Mask file -% 3. Info file (header of NIFTI) -% 4. Motion file -% -% He can select them in the order he likes -[filename1,pathname1]=uigetfile({'*.*','All Files'},... - 'Select data, motion, mask and brain info files...','MultiSelect','on'); - -% If the user has indeed entered files -if ~isequal(filename1,0) || ~isequal(pathname1,0) - % There should be four selected files. In this switch, we test - % for the amount of entered files - if length(filename1) == 4 - - % The files are loaded sequentially - for i = 1:length(filename1) - File{i} = fullfile(pathname1, filename1{i}); - tmp = load(File{i}); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - - % Finds what type of file DataType is between the four - % possibilities - DataType = CAP_FindDataType(tmp); - - % Accordingly, fill the right handle with the information - switch DataType - case 'Data' - % We store the data into handles.TC and the file name that goes - % with it - handles.TC{handles.n_datasets+1} = tmp; - - % Takes only the last two parts of the file name and - % puts them in tmp_file - [tmp_file,n_delim] = strsplit(File{i},'/'); - - if isempty(n_delim) - tmp_file = strsplit(File{i},'\'); - end - - tmp_file = tmp_file(end-1:end); - - % This is what is saved and displayed in the main - % window then - handles.SubjNames{handles.n_datasets+1} = fullfile(tmp_file{1},tmp_file{2}); - handles.n_subjects{handles.n_datasets+1} = size(handles.TC{handles.n_datasets+1},2); - - % Some commands are run only for the first dataset that we add - if handles.n_datasets == 0 - % We compute and store the number of voxels and the number of time - % points, as well as the number of subjects - handles.SubjSize.VOX = size(handles.TC{1}{1},2); - handles.SubjSize.TP = size(handles.TC{1}{1},1); - end - - % Sets the text label about data dimensions - set(handles.Dimensionality_Text, 'String', [num2str(handles.SubjSize.TP),... - ' frames x ',num2str(handles.SubjSize.VOX),' voxels (',... - strjoin(arrayfun(@(x) num2str(x),cell2mat(handles.n_subjects),... - 'UniformOutput',false),'+'),')']); - - case 'Motion' - % We store the path of the motion file added - handles.MotName{handles.n_datasets+1} = File{i}; - % If the dimensions hold, we store the file into the FD variable - % and then plot the FD ribbon graph - handles.FD{handles.n_datasets+1} = tmp; - - case 'Mask' - handles.mask{handles.n_datasets+1} = tmp; - case 'Info' - % If so, we store the value and we validate the choice - handles.brain_info{handles.n_datasets+1} = tmp; - - % If the data file is unknown, then we return an error and - % the user must enter files again - case 'Unknown' - errordlg('At least one of the selected files is not recognized; please try again !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - end - - % Check if the dimensionality of the entered data holds between - % the file types. It may be that the user entered four files of - % the same type (e.g. four data files), rather than one of each - % type as required - [is_DataOK,Data_problems] = CAP_IsDataOK(handles.TC{handles.n_datasets+1},handles.FD{handles.n_datasets+1},... - handles.mask{handles.n_datasets+1},handles.brain_info{handles.n_datasets+1}); - if is_DataOK - - % We increment handles.n_datasets - handles.n_datasets = handles.n_datasets + 1; - - % We fill the list of loaded populations, and make it visible - handles = FillPopulationList(handles.RefPop,handles); - set(handles.RefPop,'Visible','on'); - - % We also fill the list of subjects from the seed menu, but do - % not make it visible yet - handles = FillSubjectList(handles.SubjectMenu,handles); - - % We can now enable the seed selection - set(handles.SeedButton,'Enable','on'); - - % Also, we can now color the button in green - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - % If we are loading the first dataset, we convert the underlay - % to the resolution of the functional data for plotting - if handles.n_datasets == 1 - - % The brain variable now contains a good resolution - % underlay that can directly be overlapped with the - % functional data - handles.brain = CAP_V2V(handles.brain,handles.Underlay_info.dim,... - handles.Underlay_info.mat,handles.brain_info{1}.dim,handles.brain_info{1}.mat); - - elseif handles.n_datasets > 1 && handles.n_datasets < 5 && ~isempty(handles.CAP) - set(handles.AssignButton,'Enable','on'); - elseif handles.n_datasets > 4 - errordlg('Please enter at most four different populations in the interface !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - handles.Log = CAP_AddToLog(handles.Log,'Data correctly loaded'); - - % If it doesn't hold, then we return an error - else - errordlg(['There is a dimensionality problem in your data: ',Data_problems]); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end - - % If a different number of files is entered, then there is a problem, - % and everything is reset - else - errordlg('You did not enter the correct number of files !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); - end -% Else, an error is displayed and the user is prompted to enter files -else - errordlg('Cancelling data entry will not solve your problems !'); - handles = ClearDataButton_Callback(handles.ClearDataButton, eventdata, handles); -end - - -% Update handles structure -guidata(hObject, handles); - -%% TR Textbox Interaction - -% Executes when we go to the TR field to add the TR of the experiment -function TR_Entry_Callback(hObject, eventdata, handles) - -% If the TR takes a reasonable value, then we validate it -if (~isempty(str2double(get(hObject,'String')))) && ... - (str2double(get(hObject,'String')) > 0.5) && ... - (str2double(get(hObject,'String')) <= 5) - - handles.TR = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - handles.isTROK = true; - - handles.Log = CAP_AddToLog(handles.Log,'Correct value of TR entered',{handles.TR},{'TR'}); - -% Else, the TR value is not accepted -else - set(hObject,'BackgroundColor', [0.93 0.84 0.84]); - handles.isTROK = false; -end - -guidata(hObject, handles); - -% Executes during creation of the TR textbox -function handles = TR_Entry_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','r'); -end - -guidata(hObject, handles); - -% Executes when clicking on the TR text space -function TR_Entry_ButtonDownFcn(hObject, eventdata, handles) -% hObject handle to TMotEdit (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); -guidata(hObject, handles); - -%% Seed sliders interactions -% For the below functions, the goal is to change the value of the slider -% textboxes when the sliders are moved, and to update the graph display -% accordingly. For this purpose, cla is used to clear graph content prior -% to a new display - -% --- Executes on slider movement. -function SliderX_Callback(hObject, eventdata, handles) - -cla(handles.SeedGraphX); -set(handles.XCoordText,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); -handles.SeedGraphX = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),handles.SeedGraphX); -guidata(hObject, handles); - -% --- Executes during object creation, after setting all properties. -function SliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject, handles); - -% --- Executes on slider movement. -function SliderY_Callback(hObject, eventdata, handles) - -cla(handles.SeedGraphY); -set(handles.YCoordText,'String',['Y: ',sprintf('%.2f',get(hObject,'Value'))]); -handles.SeedGraphY = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(hObject,'Value'),handles.SeedGraphY); -guidata(hObject, handles); - -% --- Executes during object creation, after setting all properties. -function SliderY_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject, handles); - -% --- Executes on slider movement. -function SliderZ_Callback(hObject, eventdata, handles) - -cla(handles.SeedGraphZ); -set(handles.ZCoordText,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); -handles.SeedGraphZ = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),handles.SeedGraphZ); -guidata(hObject, handles); - -% --- Executes during object creation, after setting all properties. -function SliderZ_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end -guidata(hObject, handles); - - -%% Seed Button Controls -% We want to define what happens when loading data (SeedButton) or when -% attempting to plot them (PlotSeedButton) - -% Executes when clicking on 'B. Select a seed' -function SeedButton_Callback(hObject, eventdata, handles) - -% No seed union asked -if ~get(handles.Union_Checkbox,'Value') - - [filename_seed,pathname_seed]=uigetfile({'*.*','All Files'},... - 'Select Seed File...'); - - File_seed = fullfile(pathname_seed, filename_seed); - tmp = load(File_seed); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); -% Seed union asked -else - - [filename_seed,pathname_seed]=uigetfile({'*.*','All Files'},... - 'Select Seed File...','MultiSelect','on'); - - File_seed = fullfile(pathname_seed, filename_seed{1}); - tmp = load(File_seed); - assignin('base','tmp', tmp); - tmp = struct2array(tmp); - handles.seed = tmp; - - File_seed = fullfile(pathname_seed, filename_seed{2}); - tmp2 = load(File_seed); - assignin('base','tmp2', tmp2); - tmp2 = struct2array(tmp2); - handles.seed2 = tmp2; -end - -% If the user has indeed entered files -if ~isequal(filename_seed,0) || ~isequal(pathname_seed,0) - - % If the file is of suitable dimensions - if islogical(tmp) && size(tmp,2) == 1 && size(tmp,1) == sum(handles.mask{1}) - - % Then we put it in the handles, enable the plotting button, and - % make the seed selection button green - handles.seed = tmp; - set(handles.PlotSeedButton,'Enable','on'); - set(handles.SeedButton,'BackgroundColor', [0.4 0.6 0.4]); - - % We can now go through the next parts of the analysis, so we - % enable the related buttons - set(handles.TPSelectionButton,'Enable','on'); - set(handles.SeedMapPushButton,'Enable','on'); - - handles.Log = CAP_AddToLog(handles.Log,'Seed chosen',{File_seed},{'Seed file'}); - else - errordlg('The file you entered appears to be of wrong dimensions...'); - end - -else - errordlg('Please enter a seed file !'); -end - -guidata(hObject, handles); - -% Change in the status of the checkbox for seed union -function Union_Checkbox_Callback(hObject, eventdata, handles) - -handles.Log = CAP_AddToLog(handles.Log,'Seed union status changed',{get(hObject,'Value')},{'Status'}); - -guidata(hObject, handles); - -% Executes when clicking on 'Plot Seed' -function PlotSeedButton_Callback(hObject, eventdata, handles) - -% Clears the present graph content -cla(handles.SeedGraphX); -cla(handles.SeedGraphX); -cla(handles.SeedGraphX); - -% Plots the slices within the graph windows -handles.SeedGraphX = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(handles.SliderX,'Value'),handles.SeedGraphX); -handles.SeedGraphY = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(handles.SliderY,'Value'),handles.SeedGraphY); -handles.SeedGraphZ = plot_slice(handles.seed,get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SliderZ,'Value'),handles.SeedGraphZ); - -% Sets the sliders to visible -set(handles.SliderX,'Visible','on'); -set(handles.SliderY,'Visible','on'); -set(handles.SliderZ,'Visible','on'); - -% Sets the text values at the ones of the sliders -set(handles.XCoordText,'String',['X: ',sprintf('%.2f',get(handles.SliderX,'Value'))]); -set(handles.YCoordText,'String',['Y: ',sprintf('%.2f',get(handles.SliderY,'Value'))]); -set(handles.ZCoordText,'String',['Z: ',sprintf('%.2f',get(handles.SliderZ,'Value'))]); - -% Sets the visibility of the slider texts to on -set(handles.XCoordText,'Visible','on'); -set(handles.YCoordText,'Visible','on'); -set(handles.ZCoordText,'Visible','on'); - -handles.Log = CAP_AddToLog(handles.Log,'Seed plots activated'); - -guidata(hObject, handles); - -%% Reference group List Control -% If we change the entry from this list, we change the reference group on -% which seed maps will be computed, and CAPs calculated - -% Executes on selection change in RefPop -function RefPop_Callback(hObject, eventdata, handles) - -% We take the actual value of the population as the reference group -handles.ReferencePopulation = get(hObject,'Value'); - -% We want to fill the subject lists again, according to how many subjects -% now lie in the considered reference population -handles = FillSubjectList(handles.SubjectMenu,handles); -handles = FillSubjectList(handles.SubjectMenuMetrics,handles); - -% We want to reset the graph displays and only enable what can be computed - -% Resetting the seed map section -set(handles.SubjectMenu,'Visible','off'); -set(handles.SubjectMenu,'Value',1); - -handles = ResetGraphDisplay(handles.SeedMapX,handles); -handles = ResetGraphDisplay(handles.SeedMapY,handles); -handles = ResetGraphDisplay(handles.SeedMapZ,handles); - -handles = ResetGraphDisplay(handles.SubjSeedMapX,handles); -handles = ResetGraphDisplay(handles.SubjSeedMapY,handles); -handles = ResetGraphDisplay(handles.SubjSeedMapZ,handles); - -set(handles.SeedMap_SliderX,'Visible','off'); -set(handles.SeedMapSliderX,'Visible','off'); -set(handles.SeedMap_SliderY,'Visible','off'); -set(handles.SeedMapSliderY,'Visible','off'); -set(handles.SeedMap_SliderZ,'Visible','off'); -set(handles.SeedMapSliderZ,'Visible','off'); - -handles = ResetGraphDisplay(handles.ColorbarSeed,handles); -set(handles.TSeed,'Visible','off'); -set(handles.TSeed_Slider,'Visible','off'); - -% Resetting the time points selection section -handles = ResetGraphDisplay(handles.TPViolin,handles); - -% Resetting the CAP analysis section -set(handles.ClusterButton,'Enable','off'); -set(handles.GMM_Button,'Enable','off'); - -set(handles.TVIS,'Visible','off'); -set(handles.TVIS_Slider,'Visible','off'); - -handles = ResetGraphDisplay(handles.ColorbarCAP,handles); - -set(handles.CAP1_Frames,'Visible','off'); -set(handles.CAP2_Frames,'Visible','off'); -set(handles.CAP3_Frames,'Visible','off'); -set(handles.CAP4_Frames,'Visible','off'); -set(handles.CAP5_Frames,'Visible','off'); -set(handles.CAP6_Frames,'Visible','off'); - -tmp_CAPX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; -tmp_CAPY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; -tmp_CAPZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; - -for i = 1:6 - handles = ResetGraphDisplay(tmp_CAPX{i},handles); - handles = ResetGraphDisplay(tmp_CAPY{i},handles); - handles = ResetGraphDisplay(tmp_CAPZ{i},handles); -end - -set(handles.CAP_XC,'Visible','off'); -set(handles.CAP_YC,'Visible','off'); -set(handles.CAP_ZC,'Visible','off'); - -set(handles.CAP_SliderX,'Visible','off'); -set(handles.CAP_SliderY,'Visible','off'); -set(handles.CAP_SliderZ,'Visible','off'); - -% Resetting the metrics section -set(handles.MetricsButton,'Enable','off'); - -handles = ResetGraphDisplay(handles.CAP_Mat,handles); -handles = ResetGraphDisplay(handles.TMGraph,handles); -handles = ResetGraphDisplay(handles.TM_Subject,handles); -handles = ResetGraphDisplay(handles.ColorbarSimMat,handles); -handles = ResetGraphDisplay(handles.ColorbarTransMat,handles); -handles = ResetGraphDisplay(handles.DynStates,handles); -handles = ResetGraphDisplay(handles.CumStates,handles); -handles = ResetGraphDisplay(handles.ViolinCounts,handles); -handles = ResetGraphDisplay(handles.ViolinCountsFrac,handles); -handles = ResetGraphDisplay(handles.ViolinNumber,handles); -handles = ResetGraphDisplay(handles.ViolinDuration,handles); - -set(handles.SubjectMenuMetrics,'Visible','off'); -set(handles.SubjectMenuMetrics,'Value',1); - -set(handles.StateMenu,'Visible','off'); - -handles.Log = CAP_AddToLog(handles.Log,'Reference population change',{handles.ReferencePopulation},{'New reference population index'}); - -guidata(hObject,handles); - -% --- Executes during object creation, after setting all properties. -function RefPop_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%SECTION 2: SEED MAPS COMPUTATION%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Seed Map Computation Button -% When pressing on this button, classical seed maps are computed for the -% population of subjects chosen as the reference one in the loading part. -% The last entered seed is used - -function SeedMapPushButton_Callback(hObject, eventdata, handles) - -% Computes seed maps for each subject and for the population, using the -% data from the chosen reference population -[handles.SeedMaps,handles.AvgSeedMap] = CAP_Compute_SeedMap(handles.TC{handles.ReferencePopulation},handles.seed); - -% Graphical displays - -% Making the plots, texts and sliders visible -set(handles.SubjectMenu,'Visible','on'); -set(handles.SeedMapX,'Visible','on'); -set(handles.SeedMapY,'Visible','on'); -set(handles.SeedMapZ,'Visible','on'); -set(handles.SubjSeedMapX,'Visible','on'); -set(handles.SubjSeedMapY,'Visible','on'); -set(handles.SubjSeedMapZ,'Visible','on'); -set(handles.SeedMap_SliderX,'Visible','on'); -set(handles.SeedMap_SliderY,'Visible','on'); -set(handles.SeedMap_SliderZ,'Visible','on'); -set(handles.SeedMapSliderX,'Visible','on'); -set(handles.SeedMapSliderY,'Visible','on'); -set(handles.SeedMapSliderZ,'Visible','on'); -set(handles.TSeed_Slider,'Visible','on'); -set(handles.TSeed,'Visible','on'); -set(handles.ColorbarSeed,'Visible','on'); - -% Writing down the text with current MNI coordinates -set(handles.SeedMap_SliderX,'String',['X: ',sprintf('%.2f',get(handles.SeedMapSliderX,'Value'))]); -set(handles.SeedMap_SliderY,'String',['Y: ',sprintf('%.2f',get(handles.SeedMapSliderY,'Value'))]); -set(handles.SeedMap_SliderZ,'String',['Z: ',sprintf('%.2f',get(handles.SeedMapSliderZ,'Value'))]); - -% Clears previous plot contents (in case we want to re-plot after changing -% the seed) -cla(handles.SeedMapX); -cla(handles.SeedMapY); -cla(handles.SeedMapZ); -cla(handles.SubjSeedMapX); -cla(handles.SubjSeedMapY); -cla(handles.SubjSeedMapZ); - -% Plots new slices -handles.SeedMapX = plot_slice(handles.AvgSeedMap,0.25,1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(handles.SeedMapSliderX,'Value'),handles.SeedMapX); -handles.SeedMapY = plot_slice(handles.AvgSeedMap,0.25,1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(handles.SeedMapSliderY,'Value'),handles.SeedMapY); -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,0.25,1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SeedMapSliderZ,'Value'),handles.SeedMapZ); - -% Plots subject specific slices after having selected the subject -handles.SubjSeedMapX = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(handles.SeedMapSliderX,'Value'),handles.SubjSeedMapX); -handles.SubjSeedMapY = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(handles.SeedMapSliderY,'Value'),handles.SubjSeedMapY); -handles.SubjSeedMapZ = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SeedMapSliderZ,'Value'),handles.SubjSeedMapZ); - -% Adds the colorbar for the seed maps (between -1 and 1) -handles.ColorbarSeed = Create_CAP_colorbar(-1,1,0.5,get(handles.TSeed_Slider,'Value'),'',handles.ColorbarSeed,'Horizontal'); - -handles.Log = CAP_AddToLog(handles.Log,'Seed maps displayed'); - -guidata(hObject,handles); - -%% Slider Controls (MNI coordinates) -% We want to reload the seed images with the new parameters when changing a -% slider, so we clear the previous display, change the text summarizing the -% MNI coordinate where we stand, and plot the new image - -function SeedMapSliderX_Callback(hObject, eventdata, handles) - -% Clears graphs -cla(handles.SeedMapX); -cla(handles.SubjSeedMapX); - -% Changes slider texts -set(handles.SeedMap_SliderX,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Plots new slices -handles.SeedMapX = plot_slice(handles.AvgSeedMap,get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),handles.SeedMapX); -handles.SubjSeedMapX = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),handles.SubjSeedMapX); -guidata(hObject, handles); - -function SeedMapSliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -function SeedMapSliderY_Callback(hObject, eventdata, handles) - -% Clears graphs -cla(handles.SeedMapY); -cla(handles.SubjSeedMapY); - -% Changes slider texts -set(handles.SeedMap_SliderY,'String',['Y: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Plots new slices -handles.SeedMapY = plot_slice(handles.AvgSeedMap,get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(hObject,'Value'),handles.SeedMapY); -handles.SubjSeedMapY = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(hObject,'Value'),handles.SubjSeedMapY); -guidata(hObject, handles); - -function SeedMapSliderY_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -function SeedMapSliderZ_Callback(hObject, eventdata, handles) - -cla(handles.SeedMapZ); -cla(handles.SubjSeedMapZ); - -% Changes slider texts -set(handles.SeedMap_SliderZ,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Plots new slices -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),handles.SeedMapZ); -handles.SubjSeedMapZ = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),handles.SubjSeedMapZ); -guidata(hObject, handles); - -% --- Executes during object creation, after setting all properties. -function SeedMapSliderZ_CreateFcn(hObject, eventdata, handles) -% hObject handle to SeedMapSliderZ (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called - -% Hint: slider controls usually have a light gray background. -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -%% Slider controls (visualization threshold) -% We want to replot and modify the colorbar according to the visualization -% threshold that we select (and also change the text) - -function TSeed_Slider_Callback(hObject, eventdata, handles) - -% Clears previous plot contents -cla(handles.SeedMapX); -cla(handles.SeedMapY); -cla(handles.SeedMapZ); -cla(handles.SubjSeedMapX); -cla(handles.SubjSeedMapY); -cla(handles.SubjSeedMapZ); - -% Plots new slices (average seed maps) -handles.SeedMapX = plot_slice(handles.AvgSeedMap,get(hObject,'Value'),1,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',... - get(handles.SeedMapSliderX,'Value'),handles.SeedMapX); - -handles.SeedMapY = plot_slice(handles.AvgSeedMap,get(hObject,'Value'),1,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',... - get(handles.SeedMapSliderY,'Value'),handles.SeedMapY); - -handles.SeedMapZ = plot_slice(handles.AvgSeedMap,get(hObject,'Value'),1,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',... - get(handles.SeedMapSliderZ,'Value'),handles.SeedMapZ); - -% Plots subject specific slices after having selected the subject -handles.SubjSeedMapX = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},... - get(hObject,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(handles.SeedMapSliderX,... - 'Value'),handles.SubjSeedMapX); - -handles.SubjSeedMapY = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},... - get(hObject,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',get(handles.SeedMapSliderY,... - 'Value'),handles.SubjSeedMapY); - -handles.SubjSeedMapZ = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},... - get(hObject,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SeedMapSliderZ,... - 'Value'),handles.SubjSeedMapZ); - -% Modifies the text -set(handles.TSeed,'String',['Tv: ',sprintf('%.2f',get(hObject,'Value'))]); - -% Clears and replots the colorbar -cla(handles.ColorbarSeed); -handles.ColorbarSeed = Create_CAP_colorbar(-1,1,0.5,get(hObject,'Value'),'',handles.ColorbarSeed,'Horizontal'); - -guidata(hObject,handles); - -function TSeed_Slider_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - -%% Subject Menu Control -% We want that when we change the value of the subject menu, the displays -% from the graphs change too (if the graphs already contain something) - -function SubjectMenu_Callback(hObject, eventdata, handles) - -% If the seed maps have already been computed (i.e. if we have already -% pressed on the computation button), then we adjust the displays of the -% subject-specific maps -try - cla(handles.SubjSeedMapX); - cla(handles.SubjSeedMapY); - cla(handles.SubjSeedMapZ); - handles.SubjSeedMapX = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'X',get(handles.SeedMapSliderX,'Value'),handles.SubjSeedMapX); - handles.SubjSeedMapY = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Y',get(handles.SeedMapSliderY,'Value'),handles.SubjSeedMapY); - handles.SubjSeedMapZ = plot_slice(handles.SeedMaps{get(handles.SubjectMenu,'Value')},get(handles.TSeed_Slider,'Value'),1,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(handles.SeedMapSliderZ,'Value'),handles.SubjSeedMapZ); -catch - errordlg('Please recompute seed maps for the presently considered population !'); -end - -handles.Log = CAP_AddToLog(handles.Log,'Changed displayed subjectwise seed map',{get(handles.SubjectMenu,'Value')},{'New subject index'}); - -guidata(hObject, handles); - -function SubjectMenu_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%PART 3: CAP ANALYSIS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Motion parameter entry - -function TMotEdit_Callback(hObject, eventdata, handles) - -% If we enter a reasonable value, it is taken as a new threshold -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 0.5) - handles.Tmot = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid motion threshold value entered',{handles.Tmot},{'Motion threshold value'}); - -% If we set something wrong again, we set the threshold value back to the -% default of 0.5 -else - set(hObject,'BackgroundColor', [0.93 0.84 0.84]); - handles.Tmot = 0.5; -end - -guidata(hObject, handles); - -% When clicking on the motion button -function handles = TMotEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject, handles); - -% When the object is created -function handles = TMotEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','r'); -end -guidata(hObject, handles); - -%% Frame selection parameter entry - -function TEdit_Callback(hObject, eventdata, handles) - -% If we enter a reasonable value, it is taken as the new threshold -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.T = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid (de)activation threshold entered',{handles.T},{'Threshold value'}); - -% If we set something wrong again, we set the threshold value back to the -% default of 0.5 -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.T = 0.5; -end - -guidata(hObject, handles); - -% When the object is created -function handles = TEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end -guidata(hObject, handles); - -% When clicking on it -function TEdit_ButtonDownFcn(hObject,eventdata,handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - -%% Frame selection mode control buttons - -% If we select threshold, we update the Selmode accordingly -function TRadio_Callback(hObject, eventdata, handles) - -set(handles.TText,'String','T [-]'); -handles.SelMode = 'Threshold'; - -handles.Log = CAP_AddToLog(handles.Log,'Changed time points selection scheme',{handles.SelMode},{'Selected mode'}); - -guidata(hObject,handles); - -% Same for percentage -function PRadio_Callback(hObject, eventdata, handles) - -set(handles.TText,'String','P [%]'); -handles.SelMode = 'Percentage'; - -handles.Log = CAP_AddToLog(handles.Log,'Changed time points selection scheme',{handles.SelMode},{'Selected mode'}); - -guidata(hObject,handles); - -%% Time points selection control -% When clicking on the select time points button, the frames matching the -% provided thresholds for scrubbing and for frame retention are selected. -% Both activation and deactivation frames are selected. This is performed -% on all the loaded populations of subjects - -% Upon clicking on the 'Select time points' button -function TPSelectionButton_Callback(hObject, eventdata, handles) - -% Clears the current plot display (for the case of having already computed -% something before with other parameters) -cla(handles.TPViolin); - -% Performs the analysis to extract frames of activity for all loaded -% populations (done for each dataset) -for n_ds = 1:handles.n_datasets - % Xonp and Xonn contain the frames (deactivation frames have been - % switched in sign, so that deactivation is positive) - if ~get(handles.Union_Checkbox,'Value') - [handles.Xonp{n_ds},handles.Xonn{n_ds},p,Indices] = CAP_find_activity(handles.TC{n_ds},handles.seed,handles.T,handles.FD{n_ds},handles.Tmot,handles.SelMode); - else - [handles.Xonp{n_ds},handles.Xonn{n_ds},p,Indices] = CAP_find_activity_twoseed(handles.TC{n_ds},handles.seed,handles.seed2,handles.T,handles.FD{n_ds},handles.Tmot); - end - % Percentage of retained frames for both activation and deactivation - % cases across subjects - handles.RetainedPercentage{n_ds} = p(4:5,:); - - % Indices of the frames that have been retained (used later for metrics - % computations) - handles.FrameIndices{n_ds} = Indices; -end - -% Enables to go to the next step of the analysis and cluster the extracted -% frames -set(handles.ClusterButton,'Enable','on'); - -tmp_toplot = ConcatMat(handles.RetainedPercentage,handles.n_datasets,2,handles.n_subjects,'FD'); - -% Displays the violin plot of subject scrubbing percentage for the -% reference population -[~,~,handles.TPViolin] = MakeViolin(tmp_toplot,handles.TPViolin,{'A','D'},'Frames ret. [%]',handles.PopColor,handles.n_datasets,2); -set(handles.TPViolin,'Visible','on'); - -handles.Log = CAP_AddToLog(handles.Log,'Time points selected',{['1 to ',num2str(handles.n_datasets)],handles.SelMode,handles.T,handles.Tmot},{'Datasets indices','Selection mode','Activation threshold','Motion threshold'}); - -guidata(hObject, handles); - - -%% Parameter control: number of clusters to use - -function ClusterEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 1) && (str2double(get(hObject,'String')) <= 12) - handles.K = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid number of clusters chosen',{handles.K},{'Number of clusters'}); - -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.K = 5; -end - -guidata(hObject, handles); - -function handles = ClusterEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - -function ClusterEdit_ButtonDownFcn(hObject,eventdata,handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - -%% Parameter control: number of replicates of the k-means algorithm - -function ClusterRepEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 50) - handles.n_rep = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid number of replicates chosen',{handles.n_rep},{'Number of replicates'}); - -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.n_rep = 20; -end - -guidata(hObject, handles); - -function handles = ClusterRepEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - -function ClusterRepEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - -%% Parameter control: percentage of positive voxels on which to cluster - -function ClusterPpEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.Pp = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentage positive voxels chosen',{handles.Pp},{'Percentage positive voxels'}); - -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.Pp = 20; -end - -guidata(hObject, handles); - -function handles = ClusterPpEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - -function ClusterPpEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - -%% Parameter control: percentage of negative voxels on which to cluster - -function ClusterPnEdit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.Pn = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentage negative voxels chosen',{handles.Pn},{'Percentage negative voxels'}); - -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.Pn = 20; -end - -guidata(hObject, handles); - -function handles = ClusterPnEdit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - -function ClusterPnEdit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject,handles); - -%% Clustering control -% When pressing on the 'Cluster' button, we want to run clustering for the -% specified mode (Activation frames, Deactivation frames, or both types of -% frames together), using the previously declared parameters - -% Upon clicking on 'Cluster' -function ClusterButton_Callback(hObject, eventdata, handles) - -% Determines which type of clustering we want to perform, and runs -% clustering accordingly - -% Clustering activation frames -if get(handles.ActRadio,'Value') - - handles.CAPType = 'Act'; - [handles.CAP,~,handles.STDCAP,handles.idx{handles.ReferencePopulation},... - handles.CorrDist] = Run_Clustering(cell2mat(handles.Xonp{handles.ReferencePopulation}),... - handles.K,handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn,handles.n_rep); - -% Clustering deactivation frames -elseif get(handles.DeactRadio,'Value') - - handles.CAPType = 'Deact'; - [handles.CAP,~,handles.STDCAP,handles.idx{handles.ReferencePopulation},... - handles.CorrDist] = Run_Clustering(cell2mat(handles.Xonn{handles.ReferencePopulation}),... - handles.K,handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn,handles.n_rep); - -% Clustering both activation and deactivation frames -elseif get(handles.BothFramesRadio,'Value') - - handles.CAPType = 'Both'; - - % In this last case, we want the activation and deactivation frames to - % be of opposite sign, so we invert the sign of Xonn - [handles.CAP,~,handles.STDCAP,handles.idx{handles.ReferencePopulation},... - handles.CorrDist] = Run_Clustering([cell2mat(handles.Xonp{handles.ReferencePopulation}),... - (-1)*cell2mat(handles.Xonn{handles.ReferencePopulation})],... - handles.K,handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn,handles.n_rep); - -% Normally we should NEVER enter this -else - errordlg('I have no idea how you got there, but yes, you made everything crash in a way I do not get... Congrats...'); -end - -% Makes the sliders visible, and the related text too (CAP MNI coordinates) -set(handles.CAP_SliderX,'Visible','on'); -set(handles.CAP_SliderY,'Visible','on'); -set(handles.CAP_SliderZ,'Visible','on'); -set(handles.CAP_XC,'Visible','on'); -set(handles.CAP_YC,'Visible','on'); -set(handles.CAP_ZC,'Visible','on'); -set(handles.CAP_XC,'String',['X: ',sprintf('%.2f',get(handles.CAP_SliderX,'Value'))]); -set(handles.CAP_YC,'String',['Y: ',sprintf('%.2f',get(handles.CAP_SliderY,'Value'))]); -set(handles.CAP_ZC,'String',['Z: ',sprintf('%.2f',get(handles.CAP_SliderZ,'Value'))]); - -% Same for the slider for the visualization threshold -set(handles.TVIS,'Visible','on'); -set(handles.TVIS_Slider,'Visible','on'); -set(handles.TVIS,'String',['Tv: ',sprintf('%.2f',get(handles.TVIS_Slider,'Value'))]); - -% Makes the colorbar for the CAPs visible -handles.ColorbarCAP = Create_CAP_colorbar(-1.5,1.5,0.5,get(handles.TVIS_Slider,'Value'),'',handles.ColorbarCAP,'Horizontal'); -set(handles.ColorbarCAP,'Visible','on'); - -% Concatenates all CAP information into metavariables for easier subsequent -% changes -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; -tmpF = {handles.CAP1_Frames,handles.CAP2_Frames,handles.CAP3_Frames,handles.CAP4_Frames,handles.CAP5_Frames,handles.CAP6_Frames}; - -% For each CAP... -for i_CAP = 1:min([handles.K,6]) - - % Clears the display for each dimension - cla(tmpX{i_CAP}); - cla(tmpY{i_CAP}); - cla(tmpZ{i_CAP}); - - % Plots the new slice for each dimension - tmpX{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'X',get(handles.CAP_SliderX,'Value'),tmpX{i_CAP}); - - tmpY{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Y',get(handles.CAP_SliderY,'Value'),tmpY{i_CAP}); - - tmpZ{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Z',get(handles.CAP_SliderZ,'Value'),tmpZ{i_CAP}); - - % Sets the frame percentage text visible and at the right value (number - % of frames from a CAP/total frame number, and then percentage that it - % stands for) - set(tmpF{i_CAP},'Visible','on'); - set(tmpF{i_CAP},'String',{[num2str(sum(handles.idx{handles.ReferencePopulation}==i_CAP)),'/',... - num2str(size(handles.idx{handles.ReferencePopulation},1))],[sprintf('%.2f',... - sum(handles.idx{handles.ReferencePopulation}==i_CAP)/size(handles.idx{handles.ReferencePopulation},1)*100),' [%]']}); -end - -% Fills that subject menu with the subjects from the reference population -handles = FillSubjectList(handles.SubjectMenuMetrics,handles); - -% Also enables and fills the state menu -handles = FillStateList(handles.StateMenu,handles); - - -% Enables the Metrics button for the next part of the analysis if we -% only deal with one dataset -if handles.n_datasets == 1 - set(handles.MetricsButton,'Enable','on'); -% Else, we enable the assignment before enabling the metrics computation -elseif handles.n_datasets > 1 - set(handles.AssignButton,'Enable','on'); -end - -handles.Log = CAP_AddToLog(handles.Log,'Clustering performed',... - {handles.ReferencePopulation,handles.K,handles.n_rep,handles.Pp,... - handles.Pn,handles.CAPType},{'Reference group index',... - 'Number of clusters','Number of replicates',... - 'Percentage positive voxels','Percentage negative voxels','Type of CAPs'}); - -% When we have done one k-means clustering run and thus have 'meaningful' -% brain states, we are allowed to go for the GMM option -set(handles.GMM_Button,'Enable','on'); - -guidata(hObject, handles); - -%% Clustering with the more elaborate GMM (Gaussian Mixture Model) method -function GMM_Button_Callback(hObject, eventdata, handles) - -if handles.K ~= size(handles.CAP,1) - errordlg('Please choose a matching value of K with respect to the latest run k-means trial!'); -end - -% Initializes GMM parameters with the results from k-means -for i = 1:handles.K - handles.Mu_GMM(:,i) = handles.CAP(i,:)'; - handles.Sigma_GMM{i} = sparse(1:handles.SubjSize.VOX,1:handles.SubjSize.VOX,handles.STDCAP(:,i)); - handles.Priors_GMM(i) = 1/handles.K; -end - -% handles.Mu_GMM = 2*rand(1000,4)-ones(1000,4); -% handles.Sigma_GMM = rand(1000,1000,4); - -% Clustering activation frames -if get(handles.ActRadio,'Value') - - handles.CAPType = 'Act'; - - [handles.Gamma_GMM,handles.Priors_GMM,handles.Mu_GMM,handles.Sigma_GMM,handles.CorrDist,handles.idx{handles.ReferencePopulation}] =... - CAP_GMM(cell2mat(handles.Xonp{handles.ReferencePopulation}),handles.K,... - handles.Priors_GMM,... - handles.Mu_GMM,... - handles.Sigma_GMM,... - handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn); - -% Clustering deactivation frames -elseif get(handles.DeactRadio,'Value') - - handles.CAPType = 'Deact'; - - [handles.Gamma_GMM,handles.Priors_GMM,handles.Mu_GMM,handles.Sigma_GMM,handles.CorrDist,handles.idx{handles.ReferencePopulation}] =... - CAP_GMM(cell2mat(handles.Xonn{handles.ReferencePopulation}),handles.K,... - handles.Priors_GMM,... - handles.Mu_GMM,... - handles.Sigma_GMM,... - handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn); - -% Clustering both activation and deactivation frames -elseif get(handles.BothFramesRadio,'Value') - - handles.CAPType = 'Both'; - - % In this last case, we want the activation and deactivation frames to - % be of opposite sign, so we invert the sign of Xonn - [handles.Gamma_GMM,handles.Priors_GMM,handles.Mu_GMM,handles.Sigma_GMM,handles.CorrDist,handles.idx{handles.ReferencePopulation}] =... - CAP_GMM([cell2mat(handles.Xonp{handles.ReferencePopulation}),... - (-1)*cell2mat(handles.Xonn{handles.ReferencePopulation})],handles.K,... - handles.Priors_GMM,... - handles.Mu_GMM,... - handles.Sigma_GMM,... - handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.Pp,handles.Pn); - -% Normally we should NEVER enter this -else - errordlg('I have no idea how you got there, but yes, you made everything crash in a way I do not get... Congrats...'); -end - -% Calculates 'CAP equivalents' from the GMM outcomes -handles.CAP = handles.Mu_GMM'; - -for i = 1:handles.K - handles.STDCAP(:,i) = sqrt(diag(handles.Sigma_GMM{i})); -end - -% Makes the sliders visible, and the related text too (CAP MNI coordinates) -set(handles.CAP_SliderX,'Visible','on'); -set(handles.CAP_SliderY,'Visible','on'); -set(handles.CAP_SliderZ,'Visible','on'); -set(handles.CAP_XC,'Visible','on'); -set(handles.CAP_YC,'Visible','on'); -set(handles.CAP_ZC,'Visible','on'); -set(handles.CAP_XC,'String',['X: ',sprintf('%.2f',get(handles.CAP_SliderX,'Value'))]); -set(handles.CAP_YC,'String',['Y: ',sprintf('%.2f',get(handles.CAP_SliderY,'Value'))]); -set(handles.CAP_ZC,'String',['Z: ',sprintf('%.2f',get(handles.CAP_SliderZ,'Value'))]); - -% Same for the slider for the visualization threshold -set(handles.TVIS,'Visible','on'); -set(handles.TVIS_Slider,'Visible','on'); -set(handles.TVIS,'String',['Tv: ',sprintf('%.2f',get(handles.TVIS_Slider,'Value'))]); - -% Makes the colorbar for the CAPs visible -handles.ColorbarCAP = Create_CAP_colorbar(-1.5,1.5,0.5,get(handles.TVIS_Slider,'Value'),'',handles.ColorbarCAP,'Horizontal'); -set(handles.ColorbarCAP,'Visible','on'); - -% Concatenates all CAP information into metavariables for easier subsequent -% changes -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; -tmpF = {handles.CAP1_Frames,handles.CAP2_Frames,handles.CAP3_Frames,handles.CAP4_Frames,handles.CAP5_Frames,handles.CAP6_Frames}; - -% For each CAP... -for i_CAP = 1:min([handles.K,6]) - - % Clears the display for each dimension - cla(tmpX{i_CAP}); - cla(tmpY{i_CAP}); - cla(tmpZ{i_CAP}); - - % Plots the new slice for each dimension - tmpX{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'X',get(handles.CAP_SliderX,'Value'),tmpX{i_CAP}); - - tmpY{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Y',get(handles.CAP_SliderY,'Value'),tmpY{i_CAP}); - - tmpZ{i_CAP} = plot_slice(handles.CAP(i_CAP,:)./handles.STDCAP(:,i_CAP)',... - get(handles.TVIS_Slider,'Value'),1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},... - 'Z',get(handles.CAP_SliderZ,'Value'),tmpZ{i_CAP}); - - % Sets the frame percentage text visible and at the right value (number - % of frames from a CAP/total frame number, and then percentage that it - % stands for) - set(tmpF{i_CAP},'Visible','on'); - set(tmpF{i_CAP},'String',{[num2str(sum(handles.idx{handles.ReferencePopulation}==i_CAP)),'/',... - num2str(size(handles.idx{handles.ReferencePopulation},1))],[sprintf('%.2f',... - sum(handles.idx{handles.ReferencePopulation}==i_CAP)/size(handles.idx{handles.ReferencePopulation},1)*100),' [%]']}); -end - -% Fills that subject menu with the subjects from the reference population -handles = FillSubjectList(handles.SubjectMenuMetrics,handles); - -% Also enables and fills the state menu -handles = FillStateList(handles.StateMenu,handles); - -% Enables the Metrics button for the next part of the analysis if we -% only deal with one dataset -if handles.n_datasets == 1 - set(handles.MetricsButton,'Enable','on'); -% Else, we enable the assignment before enabling the metrics computation -elseif handles.n_datasets > 1 - set(handles.AssignButton,'Enable','on'); -end - -handles.Log = CAP_AddToLog(handles.Log,'Clustering performed',... - {handles.ReferencePopulation,handles.K,handles.n_rep,handles.Pp,... - handles.Pn,handles.CAPType},{'Reference group index',... - 'Number of clusters','Number of replicates',... - 'Percentage positive voxels','Percentage negative voxels','Type of CAPs'}); - -guidata(hObject, handles); - - - -%% Frame assignment control -% This button is only enabled after clustering has been performed on the -% reference population. It assigns frames from the other populations to the -% computed CAPs - -% Happens upon clicking on the 'Assign' buttons -function AssignButton_Callback(hObject, eventdata, handles) - -tmp_notref = []; -tmp_computedTPsel = []; - -% For each non-reference dataset... -for n_ds = 1:handles.n_datasets - if n_ds ~= handles.ReferencePopulation - - tmp_notref = [tmp_notref,n_ds]; - - % Attempts to access the frames for a given dataset; if it fails, it - % means we must compute activity. If it works, we do nothing because - % activity has already been computed - try - justtotest = handles.Xonp{n_ds}; - catch - if get(handles.Union_Checkbox,'Value') - [handles.Xonp{n_ds},handles.Xonn{n_ds},p,handles.FrameIndices{n_ds}] = ... - CAP_find_activity_twoseed(handles.TC{n_ds},handles.seed,handles.seed2,handles.T,handles.FD{n_ds},handles.Tmot); - else - [handles.Xonp{n_ds},handles.Xonn{n_ds},p,handles.FrameIndices{n_ds}] = ... - CAP_find_activity(handles.TC{n_ds},handles.seed,handles.T,handles.FD{n_ds},handles.Tmot,handles.SelMode); - end - handles.RetainedPercentage{n_ds} = p(4:5,:); - - tmp_computedTPsel = [tmp_computedTPsel,n_ds]; - end - - try - % Assigning activation frames - if strcmp(handles.CAPType,'Act') && get(handles.ActRadio,'Value') - handles.idx{n_ds} = CAP_AssignFrames(handles.CAP,cell2mat(handles.Xonp{n_ds}),handles.CorrDist,handles.percentile)'; - - % Assigning deactivation frames - elseif strcmp(handles.CAPType,'Deact') && get(handles.DeactRadio,'Value') - handles.idx{n_ds} = CAP_AssignFrames(handles.CAP,cell2mat(handles.Xonn{n_ds}),handles.CorrDist,handles.percentile)'; - - % Assigning both activation and deactivation frames - elseif strcmp(handles.CAPType,'Both') && get(handles.BothFramesRadio,'Value') - handles.idx{n_ds} = CAP_AssignFrames(handles.CAP,[cell2mat(handles.Xonp{n_ds}),cell2mat((-1)*handles.Xonn{n_ds})],handles.CorrDist,handles.percentile)'; - - % Normally we should NEVER enter this - else - errordlg('I have no idea how you got there, but yes, you made everything crash in a way I do not get... Congrats...'); - end - catch - errordlg('You computed CAPs with a different CAP type compared to the one used now; please use the same CAP type !'); - end - end -end - -% We then enable the computation of metrics -set(handles.MetricsButton,'Enable','on'); - -handles.Log = CAP_AddToLog(handles.Log,'Frame assignment performed',... - {handles.ReferencePopulation,num2str(tmp_computedTPsel),num2str(tmp_notref),... - handles.CAPType},{'Reference group index','Group indices for which frames were computed',... - 'Group indices for which frames were assigned','Type of CAPs'}); - -guidata(hObject, handles); - -%% Parameter control: percentile to use for frame assignment -% This asks for the percentile to use in frame assignment (i.e. the -% threshold of correlation below which frames are left unassigned) - -function Percentile_Edit_Callback(hObject, eventdata, handles) - -if ~isempty(str2double(get(hObject,'String'))) && (str2double(get(hObject,'String')) > 0) && (str2double(get(hObject,'String')) <= 100) - handles.percentile = str2double(get(hObject,'String')); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid percentile chosen',{handles.percentile},{'Percentile'}); - -else - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); - handles.percentile = 5; -end - -guidata(hObject, handles); - -function handles = Percentile_Edit_CreateFcn(hObject, eventdata, handles) - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -function Percentile_Edit_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -guidata(hObject, handles); - - -%% Sliders for CAP visualization (MNI coordinates) -% When changing along a slider, we want to update the graphs and the text of -% the MNI coordinate below the slider - -% X dimension slider -function CAP_SliderX_Callback(hObject, eventdata, handles) - -set(handles.CAP_XC,'String',['X: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; - -for i_CAP = 1:min([handles.K,6]) - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject, handles); - -function CAP_SliderX_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -% Y dimension slider -function CAP_SliderY_Callback(hObject, eventdata, handles) - -set(handles.CAP_YC,'String',['Y: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; - -for i_CAP = 1:min([handles.K,6]) - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject,handles); - -function CAP_SliderY_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -% Z dimension slider -function CAP_SliderZ_Callback(hObject, eventdata, handles) - -set(handles.CAP_ZC,'String',['Z: ',sprintf('%.2f',get(hObject,'Value'))]); -tmp_struct = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; - -for i_CAP = 1:min([handles.K,6]) - - cla(tmp_struct{i_CAP}); - tmp_struct{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(handles.TVIS_Slider,'Value'),... - 1.5,handles.mask{handles.ReferencePopulation},handles.brain,handles.brain_info{handles.ReferencePopulation},'Z',get(hObject,'Value'),tmp_struct{i_CAP}); -end - -guidata(hObject,handles); - -function CAP_SliderZ_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - -%% Sliders for threshold visualization (CAP analysis) -% Again, we want to update the slices and the text if we change those -% sliders - -function TVIS_Slider_Callback(hObject, eventdata, handles) - -% The text is changed -set(handles.TVIS,'String',['Tv: ',sprintf('%.2f',get(hObject,'Value'))]); - -% The colorbar graph is modified to suit the new threshold value -cla(handles.ColorbarCAP); -handles.ColorbarCAP = Create_CAP_colorbar(-1.5,1.5,0.5,get(hObject,'Value'),'',handles.ColorbarCAP,'Horizontal'); - -% The brain slices are replotted -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; - -for i_CAP = 1:min([handles.K,6]) - - cla(tmpX{i_CAP}); - cla(tmpY{i_CAP}); - cla(tmpZ{i_CAP}); - - tmpX{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'X',get(handles.CAP_SliderX,'Value'),tmpX{i_CAP}); - - tmpY{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Y',get(handles.CAP_SliderY,'Value'),tmpY{i_CAP}); - - tmpZ{i_CAP} = plot_slice(handles.CAP(i_CAP,:),get(hObject,'Value'),1.5,... - handles.mask{handles.ReferencePopulation},handles.brain,... - handles.brain_info{handles.ReferencePopulation},'Z',get(handles.CAP_SliderZ,'Value'),tmpZ{i_CAP}); -end - -guidata(hObject,handles); - -function TVIS_Slider_CreateFcn(hObject, eventdata, handles) - -if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor',[.9 .9 .9]); -end - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%% PART 4: METRICS COMPUTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Metrics computation control -% When pressing on the 'Compute metrics' button, the different metrics for -% CAP analysis are computed, including: -% - Similarity between CAPs -% - Transition probabilities from a state to the other (average + subject) -% - Sequence of states for each subject -% - Cumulative state sequence for all subjects -% - Counts (number of frames in a state) -% - Number of times entering a state, and duration spent in a state - -function MetricsButton_Callback(hObject, eventdata, handles) - -% All the metrics are computed for all the datasets -for n_ds = 1:handles.n_datasets - if n_ds == handles.ReferencePopulation - tmp_nclust = handles.K; - else - tmp_nclust = handles.K+1; - end - - try - [handles.TPM{n_ds},handles.Counts{n_ds},... - handles.Number{n_ds},handles.Avg_Duration{n_ds},... - handles.Duration{n_ds},handles.TM{n_ds}] =... - Compute_Metrics(handles.idx{n_ds},handles.FrameIndices{n_ds}.kept.active,... - handles.FrameIndices{n_ds}.kept.deactive,handles.FrameIndices{n_ds}.scrubbed,... - tmp_nclust,handles.TR,handles.CAPType); - catch - - errordlg('You tried computing metrics using parameter values different from the ones that were employed to generate CAPs; please check !'); - end -end - -handles.Log = CAP_AddToLog(handles.Log,'Metrics computed',... - {handles.n_datasets,handles.K,handles.TR,handles.CAPType},... - {'Number of datasets','Number of clusters','TR','CAP type'}); - -% 1. Display of the similarity matrix between CAPs - -% Computation of the similarity -SimMat = corr(handles.CAP',handles.CAP'); - -% Graph set visible, and plotting -handles = ResetGraphDisplay(handles.CAP_Mat,handles); -set(handles.CAP_Mat,'Visible','on'); -imagesc(SimMat,'Parent',handles.CAP_Mat); - -% Correlation ranges from -1 to 1, so this is what we make the graph -% colorbar vary within. We also make the graph square and remove the axes -caxis(handles.CAP_Mat,[-1 1]); -axis(handles.CAP_Mat,'square','on'); -axis(handles.CAP_Mat,'off'); - -% Addition of the colorbar just below -set(handles.ColorbarSimMat,'Visible','on'); -handles.ColorbarSimMat = Create_CAP_colorbar(-1,1,0.5,0,'',... - handles.ColorbarSimMat,'Horizontal'); - - -% 2. Transition matrix for all subjects together - -tmp_toplot = squeeze(mean(handles.TM{handles.ReferencePopulation},3)); -tmp_toplot = tmp_toplot(4:end,4:end); - -% Make graph visible and plotting -handles = ResetGraphDisplay(handles.TMGraph,handles); -set(handles.TMGraph,'Visible','on'); -imagesc(tmp_toplot,'Parent',handles.TMGraph); - -clear tmp_toplot - -% Arbitrary setting of probability scale from 0 to 0.03 -caxis(handles.TMGraph,[0 0.03]); -axis(handles.TMGraph,'square','on'); -axis(handles.TMGraph,'off'); - -% 3. Transition matrix for one subject - -tmp_toplot = squeeze(handles.TM{handles.ReferencePopulation}(:,:,get(handles.SubjectMenuMetrics,'Value'))); -tmp_toplot = tmp_toplot(4:end,4:end); - -% makes graph visible and plots the information given by the Subject popup -handles = ResetGraphDisplay(handles.TM_Subject,handles); -set(handles.TM_Subject,'Visible','on'); -imagesc(tmp_toplot,... - 'Parent',handles.TM_Subject); - -clear tmp_toplot - -% Same setting for the axes as for the average graph -caxis(handles.TM_Subject,[0 0.03]); -axis(handles.TM_Subject,'square','on'); -axis(handles.TM_Subject,'off'); - -% We then create the colorbar for both cases -set(handles.ColorbarTransMat,'Visible','on'); -handles.ColorbarTransMat = Create_CAP_colorbar(0,0.03,0.01,0,'',... - handles.ColorbarTransMat,'Horizontal'); - -% Makes the subject menu visible -set(handles.SubjectMenuMetrics,'Visible','on'); - -% 4. Dynamic state plotting - -%%%%%%%% TO SOLVE SOMEHOW: for the moment, the states are displayed with -%%%%%%%% the classical colorbar. The problem is that using another colorbar -%%%%%%%% instead will make all the figures use that colorbar. For now, I -%%%%%%%% could not find a solution to have only that specific figure be -%%%%%%%% plotted with different colors - -% Makes the graph visible -handles = ResetGraphDisplay(handles.DynStates,handles); -set(handles.DynStates,'Visible','on'); - -% Concatenates information from the different datasets -tmp_toplot = []; - -for i = 1:handles.n_datasets - tmp_toplot = [tmp_toplot; handles.TPM{i}; -2*ones(5,handles.SubjSize.TP)]; -end -tmp_toplot = tmp_toplot(1:end-5,:); - -% If the TR has been properly entered, the x-axis is time; else, it depicts -% time index. In any case, we plot the states -if handles.isTROK - imagesc(tmp_toplot,'Parent',handles.DynStates); - xlabel(handles.DynStates,'Time [s]'); -else - imagesc(tmp_toplot,'Parent',handles.DynStates); - xlabel(handles.DynStates,'Time index [-]'); -end - -ylabel(handles.DynStates,'Subjects [-]'); -axis(handles.DynStates,'off'); -caxis(handles.DynStates,[-2.5,handles.K+0.5]); - -clear tmp_toplot - -% 5. Cumulative state distributions - -% Makes the graph visible -handles = ResetGraphDisplay(handles.CumStates,handles); -set(handles.CumStates,'Visible','on'); - -for i = 1:handles.n_datasets - % Cumulative distribution for the state that we want to be displayed (i.e. - % the state from the popup menu) - handles.TPMCum{i} = cumsum(handles.TPM{i} == get(handles.StateMenu,'Value'),2); - - % Average of the considered state across subjects - tmp_TPMCum{i} = mean(handles.TPMCum{i},1); -end - -% Similarly as above, we plot time if we have a valid TR; else, we plot -% 'time index' -if handles.isTROK == false - - for i = 1:handles.n_datasets - % We first plot each subject curve - for j = 1:size(handles.TPMCum{i},1) - plot(handles.TPMCum{i}(j,:),'Color',handles.PopColor{1}(i,:),... - 'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - % Then, we plot a bold average across subjects - plot(tmp_TPMCum{i},'Color',handles.PopColor{2}(i,:),... - 'LineWidth',2,'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time index [-]','FontSize',8); - end -else - for i = 1:handles.n_datasets - for j = 1:size(handles.TPMCum{i},1) - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - handles.TPMCum{i}(j,:),... - 'Color',handles.PopColor{1}(i,:),'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - tmp_TPMCum{i},... - 'LineWidth',2,'Color',handles.PopColor{2}(i,:),'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time [s]','FontSize',8); - end -end - - -ylabel(handles.CumStates,'Cumul. sum [-]','FontSize',8); -set(handles.CumStates,'Box','off'); - -% Makes the state menu visible -set(handles.StateMenu,'Visible','on'); - -% 6. Violin plots -% Below, we plot violin plots depicting: -% - Raw counts of state excursions -% - Fractional counts of state excursions -% - Number of times entering a state -% - Duration of state excursions - -% We build the legend used to plot the violins -% leg_viol = cell(handles.K); -for i = 1:handles.K - leg_viol{i} = num2str(i); -end - -% Makes graphs ready -handles = ResetGraphDisplay(handles.ViolinCounts,handles); -set(handles.ViolinCounts,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinCountsFrac,handles); -set(handles.ViolinCountsFrac,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinNumber,handles); -set(handles.ViolinNumber,'Visible','on'); - -handles = ResetGraphDisplay(handles.ViolinDuration,handles); -set(handles.ViolinDuration,'Visible','on'); - -% Concatenates the values from the different populations -tmp_toplot = ConcatMat(handles.Counts,handles.n_datasets,handles.K,handles.n_subjects,'Raw counts'); - -% Plots the raw count values -[~,~,handles.ViolinCounts] = MakeViolin(tmp_toplot,... - handles.ViolinCounts,leg_viol,'Raw counts [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - -tmp_toplot = ConcatMat(handles.Counts,handles.n_datasets,handles.K,handles.n_subjects,'Normalized counts'); - -% Plots the normalized count values -[~,~,handles.ViolinCountsFrac] = MakeViolin(tmp_toplot,... - handles.ViolinCountsFrac,leg_viol,'Norm counts [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - -tmp_toplot = ConcatMat(handles.Number,handles.n_datasets,handles.K,handles.n_subjects,'Number'); - -% Plots the number of times a state is entered -[~,~,handles.ViolinNumber] = MakeViolin(tmp_toplot,... - handles.ViolinNumber,leg_viol,'Number [-]',handles.PopColor,handles.n_datasets,handles.K); - -clear tmp_toplot - - -% Plots the duration graph -if handles.isTROK - - tmp_toplot = ConcatMat(handles.Avg_Duration,handles.n_datasets,handles.K,handles.n_subjects,'Duration'); - - [~,~,handles.ViolinDuration] = MakeViolin(tmp_toplot,... - handles.ViolinDuration,leg_viol,'Dur. [s]',handles.PopColor,handles.n_datasets,handles.K); - - clear tmp_toplot - -else - errordlg('Not showing duration violin plot as TR was not entered !'); - set(handles.ViolinDuration,'Visible','off'); -end - -guidata(hObject,handles); - -%% Subject popup menu control (metrics computation) -% When a new subject is chosen, the display of the transition matrix graph -% is changed - -function SubjectMenuMetrics_Callback(hObject, eventdata, handles) - -% In the case when we have something to plot... -try - % ... we reset the graph display, make the graph visible, and plot - % again - handles = ResetGraphDisplay(handles.TM_Subject,handles); - set(handles.TM_Subject,'Visible','on'); - - tmp_toplot = squeeze(handles.TM{handles.ReferencePopulation}(:,:,get(handles.SubjectMenuMetrics,'Value'))); - tmp_toplot = tmp_toplot(4:end,4:end); - - imagesc(tmp_toplot,'Parent',handles.TM_Subject); - caxis(handles.TM_Subject,[0 0.06]); - axis(handles.TM_Subject,'square','on'); - axis(handles.TM_Subject,'off'); - - clear tmp_toplot - - handles.Log = CAP_AddToLog(handles.Log,'Subject index changed (metrics)',... - {get(hObject,'Value')},... - {'Subject index'}); - -catch - errordlg('Please recompute metrics for the presently considered population !'); -end - -guidata(hObject,handles); - -function SubjectMenuMetrics_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -%% State menu popup control -% When we change our state of interest, we will change the display of the -% cumulative state being displayed - -function StateMenu_Callback(hObject, eventdata, handles) - -handles = ResetGraphDisplay(handles.CumStates,handles); -set(handles.CumStates,'Visible','on'); - -% In the case of a non-null matrix... -if ~isempty(handles.TPM) - - for i = 1:handles.n_datasets - % Cumulative distribution for the state that we want to be displayed (i.e. - % the state from the popup menu) - handles.TPMCum{i} = cumsum(handles.TPM{i} == get(handles.StateMenu,'Value'),2); - - % Average of the considered state across subjects - tmp_TPMCum{i} = mean(handles.TPMCum{i},1); - end - - % Similarly as above, we plot time if we have a valid TR; else, we plot - % 'time index' - if handles.isTROK == false - - for i = 1:handles.n_datasets - % We first plot each subject curve - for j = 1:size(handles.TPMCum{i},1) - plot(handles.TPMCum{i}(j,:),'Color',handles.PopColor{1}(i,:),... - 'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - % Then, we plot a bold average across subjects - plot(tmp_TPMCum{i},'Color',handles.PopColor{2}(i,:),... - 'LineWidth',2,'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time index [-]','FontSize',8); - end - else - for i = 1:handles.n_datasets - for j = 1:size(handles.TPMCum{i},1) - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - handles.TPMCum{i}(j,:),... - 'Color',handles.PopColor{1}(i,:),'Parent',handles.CumStates); - hold(handles.CumStates,'on'); - end - end - - for i = 1:handles.n_datasets - plot(((1:size(handles.TPM{i},2))-1)*handles.TR,... - tmp_TPMCum{i},... - 'LineWidth',2,'Color',handles.PopColor{2}(i,:),'Parent',handles.CumStates); - xlabel(handles.CumStates,'Time [s]','FontSize',8); - end - end - - -ylabel(handles.CumStates,'Cumul. sum [-]','FontSize',8); -set(handles.CumStates,'Box','off'); - -end - -guidata(hObject,handles); - -function StateMenu_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%% GENERAL UTILITIES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Save Folder Control -% Upon clicking on the 'select save folder' button, the user can choose the -% directory where data will be saved. - -function SaveFolderButton_Callback(hObject, eventdata, handles) - -% Selection of a directory -[dirname]=uigetdir('*.*','Please select a save directory'); -handles.savedir = dirname; - -% If the user has indeed chosen a directory, we set it as the new save -% folder -if ~isequal(dirname,0) - set(handles.SaveFolderText,'String',handles.savedir); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Save folder changed',... - {handles.savedir},... - {'Save folder'}); -else - errordlg('Please select a directory !'); -end - - -%% Save Button Control -% Upon clicking on the 'SAVE' button, the data will be saved entirely under -% a file name partly chosen by the user and partly depending on the present -% date and time - -function SaveButton_Callback(hObject, eventdata, handles) - -% Upon pressing the save button, we want to save all the important -% information into a big matlab structure -SAVED = []; - -% General information on the project -SAVED.ProjectInfo.title = handles.project_title; -SAVED.ProjectInfo.date = date; - -% Name of the files that were loaded -SAVED.SubjData.SubjFileNames = handles.SubjNames; -SAVED.SubjData.MotFileNames = handles.MotName; - -% Dimension over time and voxels of the files analyzed -SAVED.SubjData.Dimensions.TP = handles.SubjSize.TP; -SAVED.SubjData.Dimensions.VOX = handles.SubjSize.VOX; - -% Number of subjects considered -SAVED.SubjData.n_subjects = handles.n_subjects; - -% TR of the experiment -SAVED.SubjData.TR = handles.TR; - -% Information about the NIFTI files used (dimensions, mapping between real -% world and index) -SAVED.BrainData.brain_info = handles.brain_info; - -% Mask that was used on the considered data -SAVED.BrainData.mask = handles.mask; - -% Seed used for the analysis -SAVED.BrainData.seed = handles.seed; -SAVED.BrainData.seed2 = handles.seed2; - -% Motion threshold and activation threshold used in time points selection -SAVED.TPSelData.Tmot = handles.Tmot; -SAVED.TPSelData.T = handles.T; - -% Type of frame selection used -SAVED.TPSelData.SelMode = handles.SelMode; - -% Frames that were considered in the clustering process -SAVED.TPSelData.Act = handles.Xonp; -SAVED.TPSelData.Deact = handles.Xonn; - -% Percentage frames retained for the clustering -SAVED.TPSelData.PercRetained = handles.RetainedPercentage; - -% Computed seed maps (average and subject-wise) -SAVED.SeedMap.AvgMap = handles.AvgSeedMap; -SAVED.SeedMap.SubjMaps = handles.SeedMaps; - -% Parameters used for clustering -SAVED.ClusterData.N = handles.n_rep; -SAVED.ClusterData.K = handles.K; -SAVED.ClusterData.Pp = handles.Pp; -SAVED.ClusterData.Pn = handles.Pn; -SAVED.ClusterData.CAPType = handles.CAPType; - -% CAP data -SAVED.ClusterData.CAPs = handles.CAP; -SAVED.ClusterData.StdCAPs = handles.STDCAP; -SAVED.ClusterData.idx = handles.idx; - -% GMM data -SAVED.GMMData.Mu = handles.Mu_GMM; -SAVED.GMMData.Sigma = handles.Sigma_GMM; -SAVED.GMMData.Priors = handles.Priors_GMM; -SAVED.GMMData.Gamma = handles.Gamma_GMM; - -% Computed metrics -SAVED.Metrics.TPM = handles.TPM; -SAVED.Metrics.Counts = handles.Counts; -SAVED.Metrics.Number = handles.Number; -SAVED.Metrics.Avg_Duration = handles.Avg_Duration; -SAVED.Metrics.Duration = handles.Duration; -SAVED.Metrics.TM = handles.TM; - -[tmp_date,tmp_date2] = strtok(date,'-'); -[tmp_date2,tmp_date3] = strtok(tmp_date2,'-'); -tmp_date3 = strtok(tmp_date3,'-'); - -% Name that will be given to the saved files -fancy_name = [handles.project_title,'_',tmp_date,'_',tmp_date2,'_',tmp_date3,'_',... - num2str(hour(now)),'_',num2str(minute(now)),'_',... - num2str(round(second(now)))]; - -% Saves NIFTI files storing the CAPs (already 'normalized'), in MNI space -CAPToNIFTI(handles.CAP./handles.STDCAP',... - handles.mask{handles.ReferencePopulation},handles.brain_info{handles.ReferencePopulation},... - handles.savedir,['CAP_NIFTI_',fancy_name]); - -% Saves the different variables from the program -save(fullfile(handles.savedir,fancy_name),'SAVED','-v7.3'); - -% Adds the save process to the log -handles.Log = CAP_AddToLog(handles.Log,'Data saved'); - -% Writes a log .txt file with what has been done so far -file_ID = fopen(fullfile(handles.savedir,[fancy_name,'.txt']),'wt'); - -for i = 1:length(handles.Log) - for j = 1:length(handles.Log{i}) - fprintf(file_ID,[handles.Log{i}{j},'\n']); - end - fprintf(file_ID,'\n'); -end - -fclose(file_ID); - -% Clears the structure now that it has been saved -clear SAVED - - -%% Clear functions -% Executes when pressing on the 'CLEAR' button for data loading; supposed -% to set everything back to normal (when the window opened) - -function handles = ClearDataButton_Callback(hObject, eventdata, handles) - -%%%%%%%%%% Putting the loading part (top) back to normal %%%%%%%%%%% - -% Makes 'A. Load data' red again -set(handles.DataButton,'BackgroundColor',[0.93 0.84 0.84]); - -% Resets the time point and voxel parameters -handles.SubjSize.TP = -inf; -handles.SubjSize.VOX = -inf; - -% Resets the TR -handles.TR = -inf; -handles.isTROK = false; - -% Resets the reference population -handles.ReferencePopulation = 1; -set(handles.RefPop_Text,'String','Reference group'); - -% Also resets the number of subjects variable and associated text -set(handles.Dimensionality_Text, 'String','_ frames x _ voxels (_)'); -handles.n_subjects = {}; - -% Resets the number of datasets entered to 0 -handles.n_datasets = 0; - -% Makes the reference population list invisible again -set(handles.RefPop,'Visible','off'); - -% Empties the data, motion, brain information and mask variables -handles.TC = {}; -handles.FD = {}; -handles.mask = {}; -handles.brain_info = {}; - -%%%%%%%%%% Putting the loading part (bottom) back to normal %%%%%%%%%%% - -% We also want to set the TR textbox back to its initial state -handles = TR_Entry_CreateFcn(handles.TR_Entry, eventdata, handles); - -% Puts back the seed buttons information to original state -handles.seed = []; -handles.seed2 = []; -set(handles.SeedButton,'BackgroundColor',[0.93 0.84 0.84]); -set(handles.SeedButton,'Enable','off'); -set(handles.PlotSeedButton,'Enable','off'); - -% Removes graph display for the seed -cla(handles.SeedGraphX); -cla(handles.SeedGraphY); -cla(handles.SeedGraphZ); -set(handles.SeedGraphX,'Visible','off'); -set(handles.SeedGraphY,'Visible','off'); -set(handles.SeedGraphZ,'Visible','off'); -set(handles.SliderX,'Visible','off'); -set(handles.SliderY,'Visible','off'); -set(handles.SliderZ,'Visible','off'); -set(handles.XCoordText,'Visible','off'); -set(handles.YCoordText,'Visible','off'); -set(handles.ZCoordText,'Visible','off'); - -%%%%%%%%%%%% Putting the seed map part back to normal %%%%%%%%%%%%%%%%%%% - -% Resets the variable containing the seed maps of the subjects -handles.SeedMaps = {}; -handles.AvgSeedMap = []; - -% Not clickable anymore -set(handles.SeedMapPushButton,'Enable','off'); - -% No more subject list visible -set(handles.SubjectMenu,'Visible','off'); - -% Resets colorbar display -handles = ResetGraphDisplay(handles.ColorbarSeed,handles); - -% Makes the slider and the text linked to slider of the seed map threshold -% back to invisible -set(handles.TSeed_Slider,'Visible','off'); -set(handles.TSeed,'Visible','off'); - -% Resets graphs with seed map plots -handles = ResetGraphDisplay(handles.SeedMapX,handles); -handles = ResetGraphDisplay(handles.SeedMapY,handles); -handles = ResetGraphDisplay(handles.SeedMapZ,handles); -handles = ResetGraphDisplay(handles.SubjSeedMapX,handles); -handles = ResetGraphDisplay(handles.SubjSeedMapY,handles); -handles = ResetGraphDisplay(handles.SubjSeedMapZ,handles); - -% Resets associated sliders -set(handles.SeedMapSliderX,'Visible','off'); -set(handles.SeedMapSliderY,'Visible','off'); -set(handles.SeedMapSliderZ,'Visible','off'); - -% Resets associated slider texts -set(handles.SeedMap_SliderX,'Visible','off'); -set(handles.SeedMap_SliderY,'Visible','off'); -set(handles.SeedMap_SliderZ,'Visible','off'); - -%%%%%%%%%% Putting the CAP analysis part back to normal %%%%%%%%%%%%%%%%%% - -% Buttons not clickable anymore (frame selection and clustering) -set(handles.TPSelectionButton,'Enable','off'); -set(handles.ClusterButton,'Enable','off'); -set(handles.GMM_Button,'Enable','off'); -set(handles.AssignButton,'Enable','off'); - -% Reinitializes motion and the motion box -handles.Tmot = 0.5; -handles = TMotEdit_CreateFcn(handles.TMotEdit,eventdata,handles); - -% Reinitializes frame selection threshold and the linked box -handles.T = 0.5; -handles = TEdit_CreateFcn(handles.TEdit,eventdata,handles); - -% Resets the frame and percentage retention variables -handles.Xonp = {}; -handles.Xonn = {}; -handles.RetainedPercentage = {}; -handles.FrameIndices = {}; - -% Resets the violin plot with percentage retained frames -handles = ResetGraphDisplay(handles.TPViolin,handles); - -% Resets the parameter input boxes -handles = ClusterEdit_CreateFcn(handles.ClusterEdit,eventdata,handles); -handles = ClusterRepEdit_CreateFcn(handles.ClusterRepEdit,eventdata,handles); -handles = ClusterPpEdit_CreateFcn(handles.ClusterPpEdit,eventdata,handles); -handles = ClusterPnEdit_CreateFcn(handles.ClusterPnEdit,eventdata,handles); -handles = Percentile_Edit_CreateFcn(handles.Percentile_Edit,eventdata,handles); - -% Resets the parameters themselves -handles.K = 5; -handles.n_rep = 20; -handles.Pp = 100; -handles.Pn = 100; -handles.percentile = 5; - -% Resets the type of performed clustering -handles.CAPType = ''; - -% Resets the CAP parameters (CAPs, standard deviation within CAPs and -% indices of the CAPs to which all retained frames were assigned) -handles.CAP = []; -handles.STDCAP = []; -handles.idx = {}; - -% Resets the graph display of the CAP colorbar -handles = ResetGraphDisplay(handles.ColorbarCAP,handles); - -% Reset all graph displays for the CAPs -tmpX = {handles.CAP1X,handles.CAP2X,handles.CAP3X,handles.CAP4X,handles.CAP5X,handles.CAP6X}; -tmpY = {handles.CAP1Y,handles.CAP2Y,handles.CAP3Y,handles.CAP4Y,handles.CAP5Y,handles.CAP6Y}; -tmpZ = {handles.CAP1Z,handles.CAP2Z,handles.CAP3Z,handles.CAP4Z,handles.CAP5Z,handles.CAP6Z}; -tmpF = {handles.CAP1_Frames,handles.CAP2_Frames,handles.CAP3_Frames,handles.CAP4_Frames,handles.CAP5_Frames,handles.CAP6_Frames}; - - -for i_CAP = 1:6 - set(tmpF{i_CAP},'Visible','off'); - handles = ResetGraphDisplay(tmpX{i_CAP},handles); - handles = ResetGraphDisplay(tmpY{i_CAP},handles); - handles = ResetGraphDisplay(tmpZ{i_CAP},handles); -end - -% Resets the sliders and the textboxes for the CAPs -set(handles.CAP_SliderX,'Visible','off'); -set(handles.CAP_SliderY,'Visible','off'); -set(handles.CAP_SliderZ,'Visible','off'); -set(handles.CAP_XC,'Visible','off'); -set(handles.CAP_YC,'Visible','off'); -set(handles.CAP_ZC,'Visible','off'); - -% Resets the slider and textbox for the CAPs visualization threshold -set(handles.TVIS_Slider,'Visible','off'); -set(handles.TVIS,'Visible','off'); - -%%%%%%%%%%% Putting the metrics part back to normal %%%%%%%%%%%%%%%%%%%%%% - -set(handles.MetricsButton,'Enable','off'); - -% Resets the metrics variables -handles.TPM = {}; -handles.Counts = {}; -handles.Number = {}; -handles.Avg_Duration = {}; -handles.Duration = {}; -handles.TM = {}; -handles.TPMCum = {}; - -% Set the sliding lists of subjects invisible again -set(handles.SubjectMenuMetrics,'Visible','off'); -set(handles.StateMenu,'Visible','off'); - -% Resets the colorbars from the metrics part -handles = ResetGraphDisplay(handles.ColorbarSimMat,handles); -handles = ResetGraphDisplay(handles.ColorbarTransMat,handles); - -% Resets all the graphs from the metrics part -handles = ResetGraphDisplay(handles.CAP_Mat,handles); -handles = ResetGraphDisplay(handles.TMGraph,handles); -handles = ResetGraphDisplay(handles.TM_Subject,handles); -handles = ResetGraphDisplay(handles.DynStates,handles); -handles = ResetGraphDisplay(handles.CumStates,handles); -handles = ResetGraphDisplay(handles.ViolinCounts,handles); -handles = ResetGraphDisplay(handles.ViolinCountsFrac,handles); -handles = ResetGraphDisplay(handles.ViolinNumber,handles); -handles = ResetGraphDisplay(handles.ViolinDuration,handles); - -handles.Log = CAP_AddToLog(handles.Log,'Data cleared'); - -guidata(hObject, handles); - -% Resets the display of a graph object (called within the clear function) -function handles = ResetGraphDisplay(Graph,handles) -cla(Graph); -set(Graph,'Visible','off'); - -%% Popup Filling Utilities - -% Fills the entries of a pop-up menu with 'Subject _' entries from the -% reference population -function handles = FillSubjectList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.n_subjects{handles.ReferencePopulation} - tmp_string{ns} = ['Subject ',num2str(ns)]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - -% Fills the entries of a pop-up menu with the different population entries -function handles = FillPopulationList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.n_datasets - tmp_string{ns} = [handles.SubjNames{ns}]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - -% Fills the entries of a pop-up menu with the different population entries -function handles = FillStateList(ToFill,handles) - -tmp_string = {}; - -for ns = 1:handles.K - tmp_string{ns} = ['State ',num2str(ns)]; -end - -set(ToFill,'String',tmp_string); - -clear tmp_string - -%% Project Title Controls -% Selects the title to give to the project - -function ProjectTitleText_ButtonDownFcn(hObject, eventdata, handles) - -set(hObject,'Enable','on'); -set(hObject,'String',''); -set(hObject,'FontAngle','normal'); -uicontrol(hObject); - -function ProjectTitleText_CreateFcn(hObject, eventdata, handles) - -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - -set(hObject,'Enable','off'); -set(hObject,'String','Click to enter...'); -set(hObject,'FontAngle','italic'); - -guidata(hObject, handles); - -function ProjectTitleText_Callback(hObject, eventdata, handles) - -% If we have entered a valid string, then we name the project as such -if ~isempty((get(hObject,'String'))) - handles.project_title = get(hObject,'String'); - set(hObject,'BackgroundColor', [0.4 0.6 0.4]); - - handles.Log = CAP_AddToLog(handles.Log,'Valid project title entered',{handles.project_title},{'New project title'}); - -% If we haven't entered anything, the project is just named 'untitled' -else - handles.project_title = 'Untitled'; - set(hObject,'BackgroundColor',[0.93 0.84 0.84]); -end - -guidata(hObject, handles); - -%% Matrix modulation utilities - -% Removes NaN-containing lines from a matrix (used for the plotting of -% duration violin plots) -function M2 = DiscardNaN(M) - -% We initialize the output matrix as a void one -M2 = []; - -% For each row, we count the amount of NaN entries; if not equal to zero, -% then we discard the line -for i = 1:size(M,1) - if sum(isnan(M(i,:))) > 0 - else - M2 = [M2;M(i,:)]; - end -end - -% Concatenates populations appropriately for Violin plotting -function M2 = ConcatMat(M,n_pop,n_states,n_subjects,type) - -% Creates the data matrix (nan values are used to have the same amount of -% data for each group) -M2 = nan(n_pop*n_states,max(cell2mat(n_subjects))); - -for i = 1:n_pop - - switch type - case 'Raw counts' - - tmp = M{i}.raw.state(:,1:n_states)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Normalized counts' - - tmp = M{i}.frac.state(:,1:n_states)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Number' - - tmp = M{i}(:,4:4+n_states-1)'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - - case 'Duration' - tmp = DiscardNaN(M{i}(:,4:4+n_states-1))'; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - - clear tmp - case 'FD' - tmp = M{i}; - - for j = 1:n_states - M2(i+(j-1)*n_pop,1:size(tmp,2)) = tmp(j,:); - end - end -end diff --git a/ComputeClusteringQuality.m b/ComputeClusteringQuality.m deleted file mode 100755 index 4259d93..0000000 --- a/ComputeClusteringQuality.m +++ /dev/null @@ -1,57 +0,0 @@ -function [CDF,Lorena] = ComputeClusteringQuality(Consensus,K_range) - - % Number of K values to check - K = size(Consensus,3); - - % Number of pairs of frames - n_items = size(Consensus,1); - - % Creates the CDF range - c = 0:0.005:1; - - % Quality criterion computations are run for each explored K value... - for k = 1:K - - % Sorted consensus entries - Cons_val = sort(jUpperTriMatToVec(squeeze(Consensus(:,:,k))),'ascend'); - - % Computation of CDF - for i = 1:length(c) - CDF(k,i) = sum(Cons_val <= c(i))/(n_items*(n_items-1)/2); - end - - - idx_dp = 1; - - for delta_perc = 0.5:0.5:10 - - Lorena(k,idx_dp) = prctile(CDF(k,:),100-delta_perc) - prctile(CDF(k,:),delta_perc); - idx_dp = idx_dp + 1; - end - - - - - % Computation of the AUC -% AUC(k) = 0; -% -% for i = 2:(n_items*(n_items-1)/2) -% AUC(k) = AUC(k) + (Cons_val(i)-Cons_val(i-1))* interp1q(c',CDF(k,:)',Cons_val(i)); -% end - - clear Cons_val - end - -% for k = 2:K -% -% % Computation of Delta -% -% tmp_max_AUC = max(AUC(1:k-1)); -% -% Delta(k) = (AUC(k) - tmp_max_AUC)/tmp_max_AUC; -% -% end -% -% Delta(1) = AUC(1); - -end \ No newline at end of file diff --git a/DefaultData/Underlay.nii b/DefaultData/Underlay.nii deleted file mode 100755 index 23d0901..0000000 Binary files a/DefaultData/Underlay.nii and /dev/null differ diff --git a/DefaultData/brain.mat b/DefaultData/brain.mat deleted file mode 100755 index 4023a14..0000000 Binary files a/DefaultData/brain.mat and /dev/null differ diff --git a/DefaultData/load_nii.m b/DefaultData/load_nii.m deleted file mode 100755 index 42415a5..0000000 --- a/DefaultData/load_nii.m +++ /dev/null @@ -1,138 +0,0 @@ -% Load NIFTI or ANALYZE dataset. Support both *.nii and *.hdr/*.img -% file extension. If file extension is not provided, *.hdr/*.img will -% be used as default. -% -% A subset of NIFTI transform is included. For non-orthogonal rotation, -% shearing etc., please use 'reslice_nii.m' to reslice the NIFTI file. -% It will not cause negative effect, as long as you remember not to do -% slice time correction after reslicing the NIFTI file. Output variable -% nii will be in RAS orientation, i.e. X axis from Left to Right, -% Y axis from Posterior to Anterior, and Z axis from Inferior to -% Superior. -% -% Usage: nii = load_nii(filename, [img_idx], [dim5_idx], [dim6_idx], ... -% [dim7_idx], [old_RGB], [tolerance], [preferredForm]) -% -% filename - NIFTI or ANALYZE file name. -% -% img_idx (optional) - a numerical array of 4th dimension indices, -% which is the indices of image scan volume. The number of images -% scan volumes can be obtained from get_nii_frame.m, or simply -% hdr.dime.dim(5). Only the specified volumes will be loaded. -% All available image volumes will be loaded, if it is default or -% empty. -% -% dim5_idx (optional) - a numerical array of 5th dimension indices. -% Only the specified range will be loaded. All available range -% will be loaded, if it is default or empty. -% -% dim6_idx (optional) - a numerical array of 6th dimension indices. -% Only the specified range will be loaded. All available range -% will be loaded, if it is default or empty. -% -% dim7_idx (optional) - a numerical array of 7th dimension indices. -% Only the specified range will be loaded. All available range -% will be loaded, if it is default or empty. -% -% old_RGB (optional) - a scale number to tell difference of new RGB24 -% from old RGB24. New RGB24 uses RGB triple sequentially for each -% voxel, like [R1 G1 B1 R2 G2 B2 ...]. Analyze 6.0 from AnalyzeDirect -% uses old RGB24, in a way like [R1 R2 ... G1 G2 ... B1 B2 ...] for -% each slices. If the image that you view is garbled, try to set -% old_RGB variable to 1 and try again, because it could be in -% old RGB24. It will be set to 0, if it is default or empty. -% -% tolerance (optional) - distortion allowed in the loaded image for any -% non-orthogonal rotation or shearing of NIfTI affine matrix. If -% you set 'tolerance' to 0, it means that you do not allow any -% distortion. If you set 'tolerance' to 1, it means that you do -% not care any distortion. The image will fail to be loaded if it -% can not be tolerated. The tolerance will be set to 0.1 (10%), if -% it is default or empty. -% -% preferredForm (optional) - selects which transformation from voxels -% to RAS coordinates; values are s,q,S,Q. Lower case s,q indicate -% "prefer sform or qform, but use others if preferred not present". -% Upper case indicate the program is forced to use the specificied -% tranform or fail loading. 'preferredForm' will be 's', if it is -% default or empty. - Jeff Gunter -% -% Returned values: -% -% nii structure: -% -% hdr - struct with NIFTI header fields. -% -% filetype - Analyze format .hdr/.img (0); -% NIFTI .hdr/.img (1); -% NIFTI .nii (2) -% -% fileprefix - NIFTI filename without extension. -% -% machine - machine string variable. -% -% img - 3D (or 4D) matrix of NIFTI data. -% -% original - the original header before any affine transform. -% -% Part of this file is copied and modified from: -% http://www.mathworks.com/matlabcentral/fileexchange/1878-mri-analyze-tools -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function nii = load_nii(filename, img_idx, dim5_idx, dim6_idx, dim7_idx, ... - old_RGB, tolerance, preferredForm) - - if ~exist('filename','var') - error('Usage: nii = load_nii(filename, [img_idx], [dim5_idx], [dim6_idx], [dim7_idx], [old_RGB], [tolerance], [preferredForm])'); - end - - if ~exist('img_idx','var') | isempty(img_idx) - img_idx = []; - end - - if ~exist('dim5_idx','var') | isempty(dim5_idx) - dim5_idx = []; - end - - if ~exist('dim6_idx','var') | isempty(dim6_idx) - dim6_idx = []; - end - - if ~exist('dim7_idx','var') | isempty(dim7_idx) - dim7_idx = []; - end - - if ~exist('old_RGB','var') | isempty(old_RGB) - old_RGB = 0; - end - - if ~exist('tolerance','var') | isempty(tolerance) - tolerance = 0.1; % 10 percent - end - - if ~exist('preferredForm','var') | isempty(preferredForm) - preferredForm= 's'; % Jeff - end - - % Read the dataset header - % - [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename); - - % Read the header extension - % -% nii.ext = load_nii_ext(filename); - - % Read the dataset body - % - [nii.img,nii.hdr] = load_nii_img(nii.hdr,nii.filetype,nii.fileprefix, ... - nii.machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB); - - % Perform some of sform/qform transform - % - nii = xform_nii(nii, tolerance, preferredForm); - - return % load_nii - diff --git a/DefaultData/load_nii_hdr.m b/DefaultData/load_nii_hdr.m deleted file mode 100755 index a915a74..0000000 --- a/DefaultData/load_nii_hdr.m +++ /dev/null @@ -1,320 +0,0 @@ -% Load NIFTI dataset header. Support both *.nii and *.hdr/*.img file -% extension. If file extension is not provided, *.hdr/*.img will be -% used as default. -% -% Usage: [hdr, filetype, fileprefix, machine] = load_nii_hdr(filename) -% -% filename - NIFTI file name. -% -% Returned values: -% -% hdr - struct with NIFTI header fields. -% -% filetype - 0 for Analyze format (*.hdr/*.img); -% 1 for NIFTI format in 2 files (*.hdr/*.img); -% 2 for NIFTI format in 1 file (*.nii). -% -% fileprefix - NIFTI file name without extension. -% -% machine - a string, see below for details. The default here is 'ieee-le'. -% -% 'native' or 'n' - local machine format - the default -% 'ieee-le' or 'l' - IEEE floating point with little-endian -% byte ordering -% 'ieee-be' or 'b' - IEEE floating point with big-endian -% byte ordering -% 'vaxd' or 'd' - VAX D floating point and VAX ordering -% 'vaxg' or 'g' - VAX G floating point and VAX ordering -% 'cray' or 'c' - Cray floating point with big-endian -% byte ordering -% 'ieee-le.l64' or 'a' - IEEE floating point with little-endian -% byte ordering and 64 bit long data type -% 'ieee-be.l64' or 's' - IEEE floating point with big-endian byte -% ordering and 64 bit long data type. -% -% Number of scanned images in the file can be obtained by: -% num_scan = hdr.dime.dim(5) -% -% Part of this file is copied and modified from: -% http://www.mathworks.com/matlabcentral/fileexchange/1878-mri-analyze-tools -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function [hdr, filetype, fileprefix, machine] = load_nii_hdr(fileprefix) - - if ~exist('fileprefix','var'), - error('Usage: [hdr, filetype, fileprefix, machine] = load_nii_hdr(filename)'); - end - - machine = 'ieee-le'; - new_ext = 0; - - if findstr('.nii',fileprefix) - new_ext = 1; - fileprefix = strrep(fileprefix,'.nii',''); - end - - if findstr('.hdr',fileprefix) - fileprefix = strrep(fileprefix,'.hdr',''); - end - - if findstr('.img',fileprefix) - fileprefix = strrep(fileprefix,'.img',''); - end - - if new_ext - fn = sprintf('%s.nii',fileprefix); - - if ~exist(fn) - msg = sprintf('Cannot find file "%s.nii".', fileprefix); - error(msg); - end - else - fn = sprintf('%s.hdr',fileprefix); - - if ~exist(fn) - msg = sprintf('Cannot find file "%s.hdr".', fileprefix); - error(msg); - end - end - - fid = fopen(fn,'r',machine); - - if fid < 0, - msg = sprintf('Cannot open file %s.',fn); - error(msg); - else - fseek(fid,0,'bof'); - - if fread(fid,1,'int32') == 348 - hdr = read_header(fid); - fclose(fid); - else - fclose(fid); - - % first try reading the opposite endian to 'machine' - % - switch machine, - case 'ieee-le', machine = 'ieee-be'; - case 'ieee-be', machine = 'ieee-le'; - end - - fid = fopen(fn,'r',machine); - - if fid < 0, - msg = sprintf('Cannot open file %s.',fn); - error(msg); - else - fseek(fid,0,'bof'); - - if fread(fid,1,'int32') ~= 348 - - % Now throw an error - % - msg = sprintf('File "%s" is corrupted.',fn); - error(msg); - end - - hdr = read_header(fid); - fclose(fid); - end - end - end - - if strcmp(hdr.hist.magic, 'n+1') - filetype = 2; - elseif strcmp(hdr.hist.magic, 'ni1') - filetype = 1; - else - filetype = 0; - end - - return % load_nii_hdr - - -%--------------------------------------------------------------------- -function [ dsr ] = read_header(fid) - - % Original header structures - % struct dsr - % { - % struct header_key hk; /* 0 + 40 */ - % struct image_dimension dime; /* 40 + 108 */ - % struct data_history hist; /* 148 + 200 */ - % }; /* total= 348 bytes*/ - - dsr.hk = header_key(fid); - dsr.dime = image_dimension(fid); - dsr.hist = data_history(fid); - - % For Analyze data format - % - if ~strcmp(dsr.hist.magic, 'n+1') & ~strcmp(dsr.hist.magic, 'ni1') - dsr.hist.qform_code = 0; - dsr.hist.sform_code = 0; - end - - return % read_header - - -%--------------------------------------------------------------------- -function [ hk ] = header_key(fid) - - fseek(fid,0,'bof'); - - % Original header structures - % struct header_key /* header key */ - % { /* off + size */ - % int sizeof_hdr /* 0 + 4 */ - % char data_type[10]; /* 4 + 10 */ - % char db_name[18]; /* 14 + 18 */ - % int extents; /* 32 + 4 */ - % short int session_error; /* 36 + 2 */ - % char regular; /* 38 + 1 */ - % char dim_info; % char hkey_un0; /* 39 + 1 */ - % }; /* total=40 bytes */ - % - % int sizeof_header Should be 348. - % char regular Must be 'r' to indicate that all images and - % volumes are the same size. - - v6 = version; - if str2num(v6(1))<6 - directchar = '*char'; - else - directchar = 'uchar=>char'; - end - - hk.sizeof_hdr = fread(fid, 1,'int32')'; % should be 348! - hk.data_type = deblank(fread(fid,10,directchar)'); - hk.db_name = deblank(fread(fid,18,directchar)'); - hk.extents = fread(fid, 1,'int32')'; - hk.session_error = fread(fid, 1,'int16')'; - hk.regular = fread(fid, 1,directchar)'; - hk.dim_info = fread(fid, 1,'uchar')'; - - return % header_key - - -%--------------------------------------------------------------------- -function [ dime ] = image_dimension(fid) - - % Original header structures - % struct image_dimension - % { /* off + size */ - % short int dim[8]; /* 0 + 16 */ - % /* - % dim[0] Number of dimensions in database; usually 4. - % dim[1] Image X dimension; number of *pixels* in an image row. - % dim[2] Image Y dimension; number of *pixel rows* in slice. - % dim[3] Volume Z dimension; number of *slices* in a volume. - % dim[4] Time points; number of volumes in database - % */ - % float intent_p1; % char vox_units[4]; /* 16 + 4 */ - % float intent_p2; % char cal_units[8]; /* 20 + 4 */ - % float intent_p3; % char cal_units[8]; /* 24 + 4 */ - % short int intent_code; % short int unused1; /* 28 + 2 */ - % short int datatype; /* 30 + 2 */ - % short int bitpix; /* 32 + 2 */ - % short int slice_start; % short int dim_un0; /* 34 + 2 */ - % float pixdim[8]; /* 36 + 32 */ - % /* - % pixdim[] specifies the voxel dimensions: - % pixdim[1] - voxel width, mm - % pixdim[2] - voxel height, mm - % pixdim[3] - slice thickness, mm - % pixdim[4] - volume timing, in msec - % ..etc - % */ - % float vox_offset; /* 68 + 4 */ - % float scl_slope; % float roi_scale; /* 72 + 4 */ - % float scl_inter; % float funused1; /* 76 + 4 */ - % short slice_end; % float funused2; /* 80 + 2 */ - % char slice_code; % float funused2; /* 82 + 1 */ - % char xyzt_units; % float funused2; /* 83 + 1 */ - % float cal_max; /* 84 + 4 */ - % float cal_min; /* 88 + 4 */ - % float slice_duration; % int compressed; /* 92 + 4 */ - % float toffset; % int verified; /* 96 + 4 */ - % int glmax; /* 100 + 4 */ - % int glmin; /* 104 + 4 */ - % }; /* total=108 bytes */ - - dime.dim = fread(fid,8,'int16')'; - dime.intent_p1 = fread(fid,1,'float32')'; - dime.intent_p2 = fread(fid,1,'float32')'; - dime.intent_p3 = fread(fid,1,'float32')'; - dime.intent_code = fread(fid,1,'int16')'; - dime.datatype = fread(fid,1,'int16')'; - dime.bitpix = fread(fid,1,'int16')'; - dime.slice_start = fread(fid,1,'int16')'; - dime.pixdim = fread(fid,8,'float32')'; - dime.vox_offset = fread(fid,1,'float32')'; - dime.scl_slope = fread(fid,1,'float32')'; - dime.scl_inter = fread(fid,1,'float32')'; - dime.slice_end = fread(fid,1,'int16')'; - dime.slice_code = fread(fid,1,'uchar')'; - dime.xyzt_units = fread(fid,1,'uchar')'; - dime.cal_max = fread(fid,1,'float32')'; - dime.cal_min = fread(fid,1,'float32')'; - dime.slice_duration = fread(fid,1,'float32')'; - dime.toffset = fread(fid,1,'float32')'; - dime.glmax = fread(fid,1,'int32')'; - dime.glmin = fread(fid,1,'int32')'; - - return % image_dimension - - -%--------------------------------------------------------------------- -function [ hist ] = data_history(fid) - - % Original header structures - % struct data_history - % { /* off + size */ - % char descrip[80]; /* 0 + 80 */ - % char aux_file[24]; /* 80 + 24 */ - % short int qform_code; /* 104 + 2 */ - % short int sform_code; /* 106 + 2 */ - % float quatern_b; /* 108 + 4 */ - % float quatern_c; /* 112 + 4 */ - % float quatern_d; /* 116 + 4 */ - % float qoffset_x; /* 120 + 4 */ - % float qoffset_y; /* 124 + 4 */ - % float qoffset_z; /* 128 + 4 */ - % float srow_x[4]; /* 132 + 16 */ - % float srow_y[4]; /* 148 + 16 */ - % float srow_z[4]; /* 164 + 16 */ - % char intent_name[16]; /* 180 + 16 */ - % char magic[4]; % int smin; /* 196 + 4 */ - % }; /* total=200 bytes */ - - v6 = version; - if str2num(v6(1))<6 - directchar = '*char'; - else - directchar = 'uchar=>char'; - end - - hist.descrip = deblank(fread(fid,80,directchar)'); - hist.aux_file = deblank(fread(fid,24,directchar)'); - hist.qform_code = fread(fid,1,'int16')'; - hist.sform_code = fread(fid,1,'int16')'; - hist.quatern_b = fread(fid,1,'float32')'; - hist.quatern_c = fread(fid,1,'float32')'; - hist.quatern_d = fread(fid,1,'float32')'; - hist.qoffset_x = fread(fid,1,'float32')'; - hist.qoffset_y = fread(fid,1,'float32')'; - hist.qoffset_z = fread(fid,1,'float32')'; - hist.srow_x = fread(fid,4,'float32')'; - hist.srow_y = fread(fid,4,'float32')'; - hist.srow_z = fread(fid,4,'float32')'; - hist.intent_name = deblank(fread(fid,16,directchar)'); - hist.magic = deblank(fread(fid,4,directchar)'); - - fseek(fid,253,'bof'); - hist.originator = fread(fid, 5,'int16')'; - - return % data_history - diff --git a/DefaultData/load_nii_img.m b/DefaultData/load_nii_img.m deleted file mode 100755 index e8d6e5f..0000000 --- a/DefaultData/load_nii_img.m +++ /dev/null @@ -1,386 +0,0 @@ -% internal function - -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) - -function [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB) - - if ~exist('hdr','var') | ~exist('filetype','var') | ~exist('fileprefix','var') | ~exist('machine','var') - error('Usage: [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,[img_idx],[dim5_idx],[dim6_idx],[dim7_idx],[old_RGB]);'); - end - - if ~exist('img_idx','var') | isempty(img_idx) | hdr.dime.dim(5)<1 - img_idx = []; - end - - if ~exist('dim5_idx','var') | isempty(dim5_idx) | hdr.dime.dim(6)<1 - dim5_idx = []; - end - - if ~exist('dim6_idx','var') | isempty(dim6_idx) | hdr.dime.dim(7)<1 - dim6_idx = []; - end - - if ~exist('dim7_idx','var') | isempty(dim7_idx) | hdr.dime.dim(8)<1 - dim7_idx = []; - end - - if ~exist('old_RGB','var') | isempty(old_RGB) - old_RGB = 0; - end - - % check img_idx - % - if ~isempty(img_idx) & ~isnumeric(img_idx) - error('"img_idx" should be a numerical array.'); - end - - if length(unique(img_idx)) ~= length(img_idx) - error('Duplicate image index in "img_idx"'); - end - - if ~isempty(img_idx) & (min(img_idx) < 1 | max(img_idx) > hdr.dime.dim(5)) - max_range = hdr.dime.dim(5); - - if max_range == 1 - error(['"img_idx" should be 1.']); - else - range = ['1 ' num2str(max_range)]; - error(['"img_idx" should be an integer within the range of [' range '].']); - end - end - - % check dim5_idx - % - if ~isempty(dim5_idx) & ~isnumeric(dim5_idx) - error('"dim5_idx" should be a numerical array.'); - end - - if length(unique(dim5_idx)) ~= length(dim5_idx) - error('Duplicate index in "dim5_idx"'); - end - - if ~isempty(dim5_idx) & (min(dim5_idx) < 1 | max(dim5_idx) > hdr.dime.dim(6)) - max_range = hdr.dime.dim(6); - - if max_range == 1 - error(['"dim5_idx" should be 1.']); - else - range = ['1 ' num2str(max_range)]; - error(['"dim5_idx" should be an integer within the range of [' range '].']); - end - end - - % check dim6_idx - % - if ~isempty(dim6_idx) & ~isnumeric(dim6_idx) - error('"dim6_idx" should be a numerical array.'); - end - - if length(unique(dim6_idx)) ~= length(dim6_idx) - error('Duplicate index in "dim6_idx"'); - end - - if ~isempty(dim6_idx) & (min(dim6_idx) < 1 | max(dim6_idx) > hdr.dime.dim(7)) - max_range = hdr.dime.dim(7); - - if max_range == 1 - error(['"dim6_idx" should be 1.']); - else - range = ['1 ' num2str(max_range)]; - error(['"dim6_idx" should be an integer within the range of [' range '].']); - end - end - - % check dim7_idx - % - if ~isempty(dim7_idx) & ~isnumeric(dim7_idx) - error('"dim7_idx" should be a numerical array.'); - end - - if length(unique(dim7_idx)) ~= length(dim7_idx) - error('Duplicate index in "dim7_idx"'); - end - - if ~isempty(dim7_idx) & (min(dim7_idx) < 1 | max(dim7_idx) > hdr.dime.dim(8)) - max_range = hdr.dime.dim(8); - - if max_range == 1 - error(['"dim7_idx" should be 1.']); - else - range = ['1 ' num2str(max_range)]; - error(['"dim7_idx" should be an integer within the range of [' range '].']); - end - end - - [img,hdr] = read_image(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB); - - return % load_nii_img - - -%--------------------------------------------------------------------- -function [img,hdr] = read_image(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB) - - switch filetype - case {0, 1} - fn = [fileprefix '.img']; - case 2 - fn = [fileprefix '.nii']; - end - - fid = fopen(fn,'r',machine); - - if fid < 0, - msg = sprintf('Cannot open file %s.',fn); - error(msg); - end - - % Set bitpix according to datatype - % - % /*Acceptable values for datatype are*/ - % - % 0 None (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN - % 1 Binary (ubit1, bitpix=1) % DT_BINARY - % 2 Unsigned char (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8 - % 4 Signed short (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16 - % 8 Signed integer (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32 - % 16 Floating point (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32 - % 32 Complex, 2 float32 (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64 - % 64 Double precision (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64 - % 128 uint8 RGB (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24 - % 256 Signed char (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8 - % 511 Single RGB (Use float32, bitpix=96) % DT_RGB96, NIFTI_TYPE_RGB96 - % 512 Unsigned short (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16 - % 768 Unsigned integer (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32 - % 1024 Signed long long (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64 - % 1280 Unsigned long long (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64 - % 1536 Long double, float128 (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128 - % 1792 Complex128, 2 float64 (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 - % 2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 - % - switch hdr.dime.datatype - case 1, - hdr.dime.bitpix = 1; precision = 'ubit1'; - case 2, - hdr.dime.bitpix = 8; precision = 'uint8'; - case 4, - hdr.dime.bitpix = 16; precision = 'int16'; - case 8, - hdr.dime.bitpix = 32; precision = 'int32'; - case 16, - hdr.dime.bitpix = 32; precision = 'float32'; - case 32, - hdr.dime.bitpix = 64; precision = 'float32'; - case 64, - hdr.dime.bitpix = 64; precision = 'float64'; - case 128, - hdr.dime.bitpix = 24; precision = 'uint8'; - case 256 - hdr.dime.bitpix = 8; precision = 'int8'; - case 511 - hdr.dime.bitpix = 96; precision = 'float32'; - case 512 - hdr.dime.bitpix = 16; precision = 'uint16'; - case 768 - hdr.dime.bitpix = 32; precision = 'uint32'; - case 1024 - hdr.dime.bitpix = 64; precision = 'int64'; - case 1280 - hdr.dime.bitpix = 64; precision = 'uint64'; - case 1792, - hdr.dime.bitpix = 128; precision = 'float64'; - otherwise - error('This datatype is not supported'); - end - - hdr.dime.dim(find(hdr.dime.dim < 1)) = 1; - - % move pointer to the start of image block - % - switch filetype - case {0, 1} - fseek(fid, 0, 'bof'); - case 2 - fseek(fid, hdr.dime.vox_offset, 'bof'); - end - - % Load whole image block for old Analyze format or binary image; - % otherwise, load images that are specified in img_idx, dim5_idx, - % dim6_idx, and dim7_idx - % - % For binary image, we have to read all because pos can not be - % seeked in bit and can not be calculated the way below. - % - if hdr.dime.datatype == 1 | isequal(hdr.dime.dim(5:8),ones(1,4)) | ... - (isempty(img_idx) & isempty(dim5_idx) & isempty(dim6_idx) & isempty(dim7_idx)) - - % For each frame, precision of value will be read - % in img_siz times, where img_siz is only the - % dimension size of an image, not the byte storage - % size of an image. - % - img_siz = prod(hdr.dime.dim(2:8)); - - % For complex float32 or complex float64, voxel values - % include [real, imag] - % - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 - img_siz = img_siz * 2; - end - - %MPH: For RGB24, voxel values include 3 separate color planes - % - if hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - img_siz = img_siz * 3; - end - - img = fread(fid, img_siz, sprintf('*%s',precision)); - - d1 = hdr.dime.dim(2); - d2 = hdr.dime.dim(3); - d3 = hdr.dime.dim(4); - d4 = hdr.dime.dim(5); - d5 = hdr.dime.dim(6); - d6 = hdr.dime.dim(7); - d7 = hdr.dime.dim(8); - - if isempty(img_idx) - img_idx = 1:d4; - end - - if isempty(dim5_idx) - dim5_idx = 1:d5; - end - - if isempty(dim6_idx) - dim6_idx = 1:d6; - end - - if isempty(dim7_idx) - dim7_idx = 1:d7; - end - else - - img = []; - - d1 = hdr.dime.dim(2); - d2 = hdr.dime.dim(3); - d3 = hdr.dime.dim(4); - d4 = hdr.dime.dim(5); - d5 = hdr.dime.dim(6); - d6 = hdr.dime.dim(7); - d7 = hdr.dime.dim(8); - - if isempty(img_idx) - img_idx = 1:d4; - end - - if isempty(dim5_idx) - dim5_idx = 1:d5; - end - - if isempty(dim6_idx) - dim6_idx = 1:d6; - end - - if isempty(dim7_idx) - dim7_idx = 1:d7; - end - - for i7=1:length(dim7_idx) - for i6=1:length(dim6_idx) - for i5=1:length(dim5_idx) - for t=1:length(img_idx) - - % Position is seeked in bytes. To convert dimension size - % to byte storage size, hdr.dime.bitpix/8 will be - % applied. - % - pos = sub2ind([d1 d2 d3 d4 d5 d6 d7], 1, 1, 1, ... - img_idx(t), dim5_idx(i5),dim6_idx(i6),dim7_idx(i7)) -1; - pos = pos * hdr.dime.bitpix/8; - - img_siz = prod(hdr.dime.dim(2:4)); - - % For complex float32 or complex float64, voxel values - % include [real, imag] - % - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 - img_siz = img_siz * 2; - end - - %MPH: For RGB24, voxel values include 3 separate color planes - % - if hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - img_siz = img_siz * 3; - end - - if filetype == 2 - fseek(fid, pos + hdr.dime.vox_offset, 'bof'); - else - fseek(fid, pos, 'bof'); - end - - % For each frame, fread will read precision of value - % in img_siz times - % - img = [img fread(fid, img_siz, sprintf('*%s',precision))]; - end - end - end - end - end - - % For complex float32 or complex float64, voxel values - % include [real, imag] - % - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 - img = reshape(img, [2, length(img)/2]); - img = complex(img(1,:)', img(2,:)'); - end - - fclose(fid); - - % Update the global min and max values - % - hdr.dime.glmax = double(max(img(:))); - hdr.dime.glmin = double(min(img(:))); - - % old_RGB treat RGB slice by slice, now it is treated voxel by voxel - % - if old_RGB & hdr.dime.datatype == 128 & hdr.dime.bitpix == 24 - % remove squeeze - img = (reshape(img, [hdr.dime.dim(2:3) 3 hdr.dime.dim(4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)])); - img = permute(img, [1 2 4 3 5 6 7 8]); - elseif hdr.dime.datatype == 128 & hdr.dime.bitpix == 24 - % remove squeeze - img = (reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)])); - img = permute(img, [2 3 4 1 5 6 7 8]); - elseif hdr.dime.datatype == 511 & hdr.dime.bitpix == 96 - img = double(img(:)); - img = (img - min(img))/(max(img) - min(img)); - % remove squeeze - img = (reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)])); - img = permute(img, [2 3 4 1 5 6 7 8]); - else - % remove squeeze - img = (reshape(img, [hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)])); - end - - if ~isempty(img_idx) - hdr.dime.dim(5) = length(img_idx); - end - - if ~isempty(dim5_idx) - hdr.dime.dim(6) = length(dim5_idx); - end - - if ~isempty(dim6_idx) - hdr.dime.dim(7) = length(dim6_idx); - end - - if ~isempty(dim7_idx) - hdr.dime.dim(8) = length(dim7_idx); - end - - return % read_image - diff --git a/DefaultData/make_nii.m b/DefaultData/make_nii.m deleted file mode 100755 index b89fe66..0000000 --- a/DefaultData/make_nii.m +++ /dev/null @@ -1,243 +0,0 @@ -% Make NIfTI structure specified by an N-D matrix. Usually, N is 3 for -% 3D matrix [x y z], or 4 for 4D matrix with time series [x y z t]. -% However, NIfTI allows a maximum of 7D matrix. For RGB24 datatype, an -% extra dimension for RGB should be inserted immediately after [x y z]. -% Optional parameters can also be included, such as: voxel_size, -% origin, datatype, and description. -% -% Once the NIfTI structure is made, it can be saved into NIfTI file -% using "save_nii" command (for more detail, type: help save_nii). -% -% Usage: nii = make_nii(img, [voxel_size], [origin], [datatype], ... -% [description]) -% -% Where: -% -% img: Usually, img is a 3D matrix [x y z], or a 4D -% matrix with time series [x y z t]. However, -% NIfTI allows a maximum of 7D matrix. For RGB -% datatype, an extra dimension for RGB should -% be inserted immediately after [x y z]. -% -% voxel_size (optional): Voxel size in millimeter for each -% dimension. Default is [1 1 1]. -% -% origin (optional): The AC origin. Default is [0 0 0]. -% -% datatype (optional): Storage data type: -% 2 - uint8, 4 - int16, 8 - int32, 16 - float32, -% 32 - complex64, 64 - float64, 128 - RGB24, -% 256 - int8, 512 - uint16, 768 - uint32, -% 1792 - complex128 -% Default will use the data type of 'img' matrix -% -% description (optional): Description of data. Default is ''. -% -% e.g.: -% origin = [33 44 13]; datatype = 64; -% nii = make_nii(img, [], origin, datatype); % default voxel_size -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function nii = make_nii(varargin) - - nii.img = varargin{1}; - dims = size(nii.img); - dims = [length(dims) dims ones(1,8)]; - dims = dims(1:8); - - voxel_size = [0 ones(1,7)]; - origin = zeros(1,5); - descrip = ''; - - switch class(nii.img) - case 'uint8' - datatype = 2; - case 'int16' - datatype = 4; - case 'int32' - datatype = 8; - case 'single' - datatype = 16; - case 'double' - datatype = 64; - case 'int8' - datatype = 256; - case 'uint16' - datatype = 512; - case 'uint32' - datatype = 768; - otherwise - error('Datatype is not supported by make_nii.'); - end - - if nargin > 1 & ~isempty(varargin{2}) - voxel_size(2:4) = double(varargin{2}); - end - - if nargin > 2 & ~isempty(varargin{3}) - origin(1:3) = double(varargin{3}); - end - - if nargin > 3 & ~isempty(varargin{4}) - datatype = double(varargin{4}); - end - - if nargin > 4 & ~isempty(varargin{5}) - descrip = varargin{5}; - end - - if datatype == 128 - if ndims(nii.img) > 8 - error('NIfTI only allows a maximum of 7 Dimension matrix.'); - end - - dims(1) = dims(1)-1; - dims(5:8) = [dims(6:8) 1]; - - else - if ndims(nii.img) > 7 - error('NIfTI only allows a maximum of 7 Dimension matrix.'); - end - end - - maxval = round(double(max(nii.img(:)))); - minval = round(double(min(nii.img(:)))); - - nii.hdr = make_header(dims, voxel_size, origin, datatype, ... - descrip, maxval, minval); - - switch nii.hdr.dime.datatype - case 2 - nii.img = uint8(nii.img); - case 4 - nii.img = int16(nii.img); - case 8 - nii.img = int32(nii.img); - case 16 - nii.img = single(nii.img); - case 32 - nii.img = single(nii.img); - case 64 - nii.img = double(nii.img); - case 128 - nii.img = uint8(nii.img); - case 256 - nii.img = int8(nii.img); - case 512 - nii.img = uint16(nii.img); - case 768 - nii.img = uint32(nii.img); - case 1792 - nii.img = double(nii.img); - otherwise - error('Datatype is not supported by make_nii.'); - end - - return; % make_nii - - -%--------------------------------------------------------------------- -function hdr = make_header(dims, voxel_size, origin, datatype, ... - descrip, maxval, minval) - - hdr.hk = header_key; - hdr.dime = image_dimension(dims, voxel_size, datatype, maxval, minval); - hdr.hist = data_history(origin, descrip); - - return; % make_header - - -%--------------------------------------------------------------------- -function hk = header_key - - hk.sizeof_hdr = 348; % must be 348! - hk.data_type = ''; - hk.db_name = ''; - hk.extents = 0; - hk.session_error = 0; - hk.regular = 'r'; - hk.dim_info = 0; - - return; % header_key - - -%--------------------------------------------------------------------- -function dime = image_dimension(dims, voxel_size, datatype, maxval, minval) - - dime.dim = dims; - dime.intent_p1 = 0; - dime.intent_p2 = 0; - dime.intent_p3 = 0; - dime.intent_code = 0; - dime.datatype = datatype; - - switch dime.datatype - case 2, - dime.bitpix = 8; precision = 'uint8'; - case 4, - dime.bitpix = 16; precision = 'int16'; - case 8, - dime.bitpix = 32; precision = 'int32'; - case 16, - dime.bitpix = 32; precision = 'float32'; - case 32, - dime.bitpix = 64; precision = 'float32'; - case 64, - dime.bitpix = 64; precision = 'float64'; - case 128, - dime.bitpix = 24; precision = 'uint8'; - case 256 - dime.bitpix = 8; precision = 'int8'; - case 512 - dime.bitpix = 16; precision = 'uint16'; - case 768 - dime.bitpix = 32; precision = 'uint32'; - case 1792, - dime.bitpix = 128; precision = 'float64'; - otherwise - error('Datatype is not supported by make_nii.'); - end - - dime.slice_start = 0; - dime.pixdim = voxel_size; - dime.vox_offset = 0; - dime.scl_slope = 0; - dime.scl_inter = 0; - dime.slice_end = 0; - dime.slice_code = 0; - dime.xyzt_units = 0; - dime.cal_max = 0; - dime.cal_min = 0; - dime.slice_duration = 0; - dime.toffset = 0; - dime.glmax = maxval; - dime.glmin = minval; - - return; % image_dimension - - -%--------------------------------------------------------------------- -function hist = data_history(origin, descrip) - - hist.descrip = descrip; - hist.aux_file = 'none'; - hist.qform_code = 0; - hist.sform_code = 0; - hist.quatern_b = 0; - hist.quatern_c = 0; - hist.quatern_d = 0; - hist.qoffset_x = 0; - hist.qoffset_y = 0; - hist.qoffset_z = 0; - hist.srow_x = zeros(1,4); - hist.srow_y = zeros(1,4); - hist.srow_z = zeros(1,4); - hist.intent_name = ''; - hist.magic = ''; - hist.originator = origin; - - return; % data_history - diff --git a/DefaultData/save_nii.m b/DefaultData/save_nii.m deleted file mode 100755 index c96ee57..0000000 --- a/DefaultData/save_nii.m +++ /dev/null @@ -1,233 +0,0 @@ -% Save NIFTI dataset. Support both *.nii and *.hdr/*.img file extension. -% If file extension is not provided, *.hdr/*.img will be used as default. -% -% Usage: save_nii(nii, filename, [old_RGB]) -% -% nii.hdr - struct with NIFTI header fields (from load_nii.m or make_nii.m) -% -% nii.img - 3D (or 4D) matrix of NIFTI data. -% -% filename - NIFTI file name. -% -% old_RGB - an optional boolean variable to handle special RGB data -% sequence [R1 R2 ... G1 G2 ... B1 B2 ...] that is used only by -% AnalyzeDirect (Analyze Software). Since both NIfTI and Analyze -% file format use RGB triple [R1 G1 B1 R2 G2 B2 ...] sequentially -% for each voxel, this variable is set to FALSE by default. If you -% would like the saved image only to be opened by AnalyzeDirect -% Software, set old_RGB to TRUE (or 1). It will be set to 0, if it -% is default or empty. -% -% Tip: to change the data type, set nii.hdr.dime.datatype, -% and nii.hdr.dime.bitpix to: -% -% 0 None (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN -% 1 Binary (ubit1, bitpix=1) % DT_BINARY -% 2 Unsigned char (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8 -% 4 Signed short (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16 -% 8 Signed integer (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32 -% 16 Floating point (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32 -% 32 Complex, 2 float32 (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64 -% 64 Double precision (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64 -% 128 Red-Green-Blue (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24 -% 256 Signed char (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8 -% 512 Unsigned short (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16 -% 768 Unsigned integer (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32 -% 1024 Signed long long (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64 -% 1280 Unsigned long long (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64 -% 1536 Long double, float128 (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128 -% 1792 Complex128, 2 float64 (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 -% 2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128 -% -% Part of this file is copied and modified from: -% http://www.mathworks.com/matlabcentral/fileexchange/1878-mri-analyze-tools -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% - "old_RGB" related codes in "save_nii.m" are added by Mike Harms (2006.06.28) -% -function save_nii(nii, fileprefix, old_RGB) - - if ~exist('nii','var') | isempty(nii) | ~isfield(nii,'hdr') | ... - ~isfield(nii,'img') | ~exist('fileprefix','var') | isempty(fileprefix) - - error('Usage: save_nii(nii, filename, [old_RGB])'); - end - - if isfield(nii,'untouch') & nii.untouch == 1 - error('Usage: please use ''save_untouch_nii.m'' for the untouched structure.'); - end - - if ~exist('old_RGB','var') | isempty(old_RGB) - old_RGB = 0; - end - - filetype = 1; - - % Note: fileprefix is actually the filename you want to save - % - if findstr('.nii',fileprefix) - filetype = 2; - fileprefix = strrep(fileprefix,'.nii',''); - end - - if findstr('.hdr',fileprefix) - fileprefix = strrep(fileprefix,'.hdr',''); - end - - if findstr('.img',fileprefix) - fileprefix = strrep(fileprefix,'.img',''); - end - - write_nii(nii, filetype, fileprefix, old_RGB); - - if filetype == 1 - - % So earlier versions of SPM can also open it with correct originator - % - M=[[diag(nii.hdr.dime.pixdim(2:4)) -[nii.hdr.hist.originator(1:3).*nii.hdr.dime.pixdim(2:4)]'];[0 0 0 1]]; - save([fileprefix '.mat'], 'M'); - end - - return % save_nii - - -%----------------------------------------------------------------------------------- -function write_nii(nii, filetype, fileprefix, old_RGB) - - hdr = nii.hdr; - - if isfield(nii,'ext') & ~isempty(nii.ext) - ext = nii.ext; - [ext, esize_total] = verify_nii_ext(ext); - else - ext = []; - end - - switch double(hdr.dime.datatype), - case 1, - hdr.dime.bitpix = int16(1 ); precision = 'ubit1'; - case 2, - hdr.dime.bitpix = int16(8 ); precision = 'uint8'; - case 4, - hdr.dime.bitpix = int16(16); precision = 'int16'; - case 8, - hdr.dime.bitpix = int16(32); precision = 'int32'; - case 16, - hdr.dime.bitpix = int16(32); precision = 'float32'; - case 32, - hdr.dime.bitpix = int16(64); precision = 'float32'; - case 64, - hdr.dime.bitpix = int16(64); precision = 'float64'; - case 128, - hdr.dime.bitpix = int16(24); precision = 'uint8'; - case 256 - hdr.dime.bitpix = int16(8 ); precision = 'int8'; - case 512 - hdr.dime.bitpix = int16(16); precision = 'uint16'; - case 768 - hdr.dime.bitpix = int16(32); precision = 'uint32'; - case 1024 - hdr.dime.bitpix = int16(64); precision = 'int64'; - case 1280 - hdr.dime.bitpix = int16(64); precision = 'uint64'; - case 1792, - hdr.dime.bitpix = int16(128); precision = 'float64'; - otherwise - error('This datatype is not supported'); - end - - hdr.dime.glmax = round(double(max(nii.img(:)))); - hdr.dime.glmin = round(double(min(nii.img(:)))); - - if filetype == 2 - fid = fopen(sprintf('%s.nii',fileprefix),'w'); - - if fid < 0, - msg = sprintf('Cannot open file %s.nii.',fileprefix); - error(msg); - end - - hdr.dime.vox_offset = 352; - - if ~isempty(ext) - hdr.dime.vox_offset = hdr.dime.vox_offset + esize_total; - end - - hdr.hist.magic = 'n+1'; - save_nii_hdr(hdr, fid); - - if ~isempty(ext) - save_nii_ext(ext, fid); - end - else - fid = fopen(sprintf('%s.hdr',fileprefix),'w'); - - if fid < 0, - msg = sprintf('Cannot open file %s.hdr.',fileprefix); - error(msg); - end - - hdr.dime.vox_offset = 0; - hdr.hist.magic = 'ni1'; - save_nii_hdr(hdr, fid); - - if ~isempty(ext) - save_nii_ext(ext, fid); - end - - fclose(fid); - fid = fopen(sprintf('%s.img',fileprefix),'w'); - end - - ScanDim = double(hdr.dime.dim(5)); % t - SliceDim = double(hdr.dime.dim(4)); % z - RowDim = double(hdr.dime.dim(3)); % y - PixelDim = double(hdr.dime.dim(2)); % x - SliceSz = double(hdr.dime.pixdim(4)); - RowSz = double(hdr.dime.pixdim(3)); - PixelSz = double(hdr.dime.pixdim(2)); - - x = 1:PixelDim; - - if filetype == 2 & isempty(ext) - skip_bytes = double(hdr.dime.vox_offset) - 348; - else - skip_bytes = 0; - end - - if double(hdr.dime.datatype) == 128 - - % RGB planes are expected to be in the 4th dimension of nii.img - % - if(size(nii.img,4)~=3) - error(['The NII structure does not appear to have 3 RGB color planes in the 4th dimension']); - end - - if old_RGB - nii.img = permute(nii.img, [1 2 4 3 5 6 7 8]); - else - nii.img = permute(nii.img, [4 1 2 3 5 6 7 8]); - end - end - - % For complex float32 or complex float64, voxel values - % include [real, imag] - % - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 - real_img = real(nii.img(:))'; - nii.img = imag(nii.img(:))'; - nii.img = [real_img; nii.img]; - end - - if skip_bytes - fwrite(fid, ones(1,skip_bytes), 'uint8'); - end - - fwrite(fid, nii.img, precision); -% fwrite(fid, nii.img, precision, skip_bytes); % error using skip - fclose(fid); - - return; % write_nii - diff --git a/DefaultData/save_nii_ext.m b/DefaultData/save_nii_ext.m deleted file mode 100755 index 4788649..0000000 --- a/DefaultData/save_nii_ext.m +++ /dev/null @@ -1,38 +0,0 @@ -% Save NIFTI header extension. -% -% Usage: save_nii_ext(ext, fid) -% -% ext - struct with NIFTI header extension fields. -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function save_nii_ext(ext, fid) - - if ~exist('ext','var') | ~exist('fid','var') - error('Usage: save_nii_ext(ext, fid)'); - end - - if ~isfield(ext,'extension') | ~isfield(ext,'section') | ~isfield(ext,'num_ext') - error('Wrong header extension'); - end - - write_ext(ext, fid); - - return; % save_nii_ext - - -%--------------------------------------------------------------------- -function write_ext(ext, fid) - - fwrite(fid, ext.extension, 'uchar'); - - for i=1:ext.num_ext - fwrite(fid, ext.section(i).esize, 'int32'); - fwrite(fid, ext.section(i).ecode, 'int32'); - fwrite(fid, ext.section(i).edata, 'uchar'); - end - - return; % write_ext - diff --git a/DefaultData/save_nii_hdr.m b/DefaultData/save_nii_hdr.m deleted file mode 100755 index 6cc34bb..0000000 --- a/DefaultData/save_nii_hdr.m +++ /dev/null @@ -1,239 +0,0 @@ -% Save NIFTI dataset header. Support both *.nii and *.hdr/*.img file -% extension. -% -% Usage: save_nii_hdr(hdr, fid) -% -% hdr - struct with NIFTI header fields. -% -% fileprefix - NIFTI file name without extension. -% -% Part of this file is copied and modified from: -% http://www.mathworks.com/matlabcentral/fileexchange/1878-mri-analyze-tools -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function save_nii_hdr(hdr, fid) - - if ~exist('hdr','var') | ~exist('fid','var') - error('Usage: save_nii_hdr(hdr, fid)'); - end - - if ~isequal(hdr.hk.sizeof_hdr,348), - error('hdr.hk.sizeof_hdr must be 348.'); - end - - if hdr.hist.qform_code == 0 & hdr.hist.sform_code == 0 - hdr.hist.sform_code = 1; - hdr.hist.srow_x(1) = hdr.dime.pixdim(2); - hdr.hist.srow_x(2) = 0; - hdr.hist.srow_x(3) = 0; - hdr.hist.srow_y(1) = 0; - hdr.hist.srow_y(2) = hdr.dime.pixdim(3); - hdr.hist.srow_y(3) = 0; - hdr.hist.srow_z(1) = 0; - hdr.hist.srow_z(2) = 0; - hdr.hist.srow_z(3) = hdr.dime.pixdim(4); - hdr.hist.srow_x(4) = (1-hdr.hist.originator(1))*hdr.dime.pixdim(2); - hdr.hist.srow_y(4) = (1-hdr.hist.originator(2))*hdr.dime.pixdim(3); - hdr.hist.srow_z(4) = (1-hdr.hist.originator(3))*hdr.dime.pixdim(4); - end - - write_header(hdr, fid); - - return; % save_nii_hdr - - -%--------------------------------------------------------------------- -function write_header(hdr, fid) - - % Original header structures - % struct dsr /* dsr = hdr */ - % { - % struct header_key hk; /* 0 + 40 */ - % struct image_dimension dime; /* 40 + 108 */ - % struct data_history hist; /* 148 + 200 */ - % }; /* total= 348 bytes*/ - - header_key(fid, hdr.hk); - image_dimension(fid, hdr.dime); - data_history(fid, hdr.hist); - - % check the file size is 348 bytes - % - fbytes = ftell(fid); - - if ~isequal(fbytes,348), - msg = sprintf('Header size is not 348 bytes.'); - warning(msg); - end - - return; % write_header - - -%--------------------------------------------------------------------- -function header_key(fid, hk) - - fseek(fid,0,'bof'); - - % Original header structures - % struct header_key /* header key */ - % { /* off + size */ - % int sizeof_hdr /* 0 + 4 */ - % char data_type[10]; /* 4 + 10 */ - % char db_name[18]; /* 14 + 18 */ - % int extents; /* 32 + 4 */ - % short int session_error; /* 36 + 2 */ - % char regular; /* 38 + 1 */ - % char dim_info; % char hkey_un0; /* 39 + 1 */ - % }; /* total=40 bytes */ - - fwrite(fid, hk.sizeof_hdr(1), 'int32'); % must be 348. - - % data_type = sprintf('%-10s',hk.data_type); % ensure it is 10 chars from left - % fwrite(fid, data_type(1:10), 'uchar'); - pad = zeros(1, 10-length(hk.data_type)); - hk.data_type = [hk.data_type char(pad)]; - fwrite(fid, hk.data_type(1:10), 'uchar'); - - % db_name = sprintf('%-18s', hk.db_name); % ensure it is 18 chars from left - % fwrite(fid, db_name(1:18), 'uchar'); - pad = zeros(1, 18-length(hk.db_name)); - hk.db_name = [hk.db_name char(pad)]; - fwrite(fid, hk.db_name(1:18), 'uchar'); - - fwrite(fid, hk.extents(1), 'int32'); - fwrite(fid, hk.session_error(1), 'int16'); - fwrite(fid, hk.regular(1), 'uchar'); % might be uint8 - - % fwrite(fid, hk.hkey_un0(1), 'uchar'); - % fwrite(fid, hk.hkey_un0(1), 'uint8'); - fwrite(fid, hk.dim_info(1), 'uchar'); - - return; % header_key - - -%--------------------------------------------------------------------- -function image_dimension(fid, dime) - - % Original header structures - % struct image_dimension - % { /* off + size */ - % short int dim[8]; /* 0 + 16 */ - % float intent_p1; % char vox_units[4]; /* 16 + 4 */ - % float intent_p2; % char cal_units[8]; /* 20 + 4 */ - % float intent_p3; % char cal_units[8]; /* 24 + 4 */ - % short int intent_code; % short int unused1; /* 28 + 2 */ - % short int datatype; /* 30 + 2 */ - % short int bitpix; /* 32 + 2 */ - % short int slice_start; % short int dim_un0; /* 34 + 2 */ - % float pixdim[8]; /* 36 + 32 */ - % /* - % pixdim[] specifies the voxel dimensions: - % pixdim[1] - voxel width - % pixdim[2] - voxel height - % pixdim[3] - interslice distance - % pixdim[4] - volume timing, in msec - % ..etc - % */ - % float vox_offset; /* 68 + 4 */ - % float scl_slope; % float roi_scale; /* 72 + 4 */ - % float scl_inter; % float funused1; /* 76 + 4 */ - % short slice_end; % float funused2; /* 80 + 2 */ - % char slice_code; % float funused2; /* 82 + 1 */ - % char xyzt_units; % float funused2; /* 83 + 1 */ - % float cal_max; /* 84 + 4 */ - % float cal_min; /* 88 + 4 */ - % float slice_duration; % int compressed; /* 92 + 4 */ - % float toffset; % int verified; /* 96 + 4 */ - % int glmax; /* 100 + 4 */ - % int glmin; /* 104 + 4 */ - % }; /* total=108 bytes */ - - fwrite(fid, dime.dim(1:8), 'int16'); - fwrite(fid, dime.intent_p1(1), 'float32'); - fwrite(fid, dime.intent_p2(1), 'float32'); - fwrite(fid, dime.intent_p3(1), 'float32'); - fwrite(fid, dime.intent_code(1), 'int16'); - fwrite(fid, dime.datatype(1), 'int16'); - fwrite(fid, dime.bitpix(1), 'int16'); - fwrite(fid, dime.slice_start(1), 'int16'); - fwrite(fid, dime.pixdim(1:8), 'float32'); - fwrite(fid, dime.vox_offset(1), 'float32'); - fwrite(fid, dime.scl_slope(1), 'float32'); - fwrite(fid, dime.scl_inter(1), 'float32'); - fwrite(fid, dime.slice_end(1), 'int16'); - fwrite(fid, dime.slice_code(1), 'uchar'); - fwrite(fid, dime.xyzt_units(1), 'uchar'); - fwrite(fid, dime.cal_max(1), 'float32'); - fwrite(fid, dime.cal_min(1), 'float32'); - fwrite(fid, dime.slice_duration(1), 'float32'); - fwrite(fid, dime.toffset(1), 'float32'); - fwrite(fid, dime.glmax(1), 'int32'); - fwrite(fid, dime.glmin(1), 'int32'); - - return; % image_dimension - - -%--------------------------------------------------------------------- -function data_history(fid, hist) - - % Original header structures - %struct data_history - % { /* off + size */ - % char descrip[80]; /* 0 + 80 */ - % char aux_file[24]; /* 80 + 24 */ - % short int qform_code; /* 104 + 2 */ - % short int sform_code; /* 106 + 2 */ - % float quatern_b; /* 108 + 4 */ - % float quatern_c; /* 112 + 4 */ - % float quatern_d; /* 116 + 4 */ - % float qoffset_x; /* 120 + 4 */ - % float qoffset_y; /* 124 + 4 */ - % float qoffset_z; /* 128 + 4 */ - % float srow_x[4]; /* 132 + 16 */ - % float srow_y[4]; /* 148 + 16 */ - % float srow_z[4]; /* 164 + 16 */ - % char intent_name[16]; /* 180 + 16 */ - % char magic[4]; % int smin; /* 196 + 4 */ - % }; /* total=200 bytes */ - - % descrip = sprintf('%-80s', hist.descrip); % 80 chars from left - % fwrite(fid, descrip(1:80), 'uchar'); - pad = zeros(1, 80-length(hist.descrip)); - hist.descrip = [hist.descrip char(pad)]; - fwrite(fid, hist.descrip(1:80), 'uchar'); - - % aux_file = sprintf('%-24s', hist.aux_file); % 24 chars from left - % fwrite(fid, aux_file(1:24), 'uchar'); - pad = zeros(1, 24-length(hist.aux_file)); - hist.aux_file = [hist.aux_file char(pad)]; - fwrite(fid, hist.aux_file(1:24), 'uchar'); - - fwrite(fid, hist.qform_code, 'int16'); - fwrite(fid, hist.sform_code, 'int16'); - fwrite(fid, hist.quatern_b, 'float32'); - fwrite(fid, hist.quatern_c, 'float32'); - fwrite(fid, hist.quatern_d, 'float32'); - fwrite(fid, hist.qoffset_x, 'float32'); - fwrite(fid, hist.qoffset_y, 'float32'); - fwrite(fid, hist.qoffset_z, 'float32'); - fwrite(fid, hist.srow_x(1:4), 'float32'); - fwrite(fid, hist.srow_y(1:4), 'float32'); - fwrite(fid, hist.srow_z(1:4), 'float32'); - - % intent_name = sprintf('%-16s', hist.intent_name); % 16 chars from left - % fwrite(fid, intent_name(1:16), 'uchar'); - pad = zeros(1, 16-length(hist.intent_name)); - hist.intent_name = [hist.intent_name char(pad)]; - fwrite(fid, hist.intent_name(1:16), 'uchar'); - - % magic = sprintf('%-4s', hist.magic); % 4 chars from left - % fwrite(fid, magic(1:4), 'uchar'); - pad = zeros(1, 4-length(hist.magic)); - hist.magic = [hist.magic char(pad)]; - fwrite(fid, hist.magic(1:4), 'uchar'); - - return; % data_history - diff --git a/DefaultData/xform_nii.m b/DefaultData/xform_nii.m deleted file mode 100755 index 21d82cd..0000000 --- a/DefaultData/xform_nii.m +++ /dev/null @@ -1,521 +0,0 @@ -% internal function - -% 'xform_nii.m' is an internal function called by "load_nii.m", so -% you do not need run this program by yourself. It does simplified -% NIfTI sform/qform affine transform, and supports some of the -% affine transforms, including translation, reflection, and -% orthogonal rotation (N*90 degree). -% -% For other affine transforms, e.g. any degree rotation, shearing -% etc. you will have to use the included 'reslice_nii.m' program -% to reslice the image volume. 'reslice_nii.m' is not called by -% any other program, and you have to run 'reslice_nii.m' explicitly -% for those NIfTI files that you want to reslice them. -% -% Since 'xform_nii.m' does not involve any interpolation or any -% slice change, the original image volume is supposed to be -% untouched, although it is translated, reflected, or even -% orthogonally rotated, based on the affine matrix in the -% NIfTI header. -% -% However, the affine matrix in the header of a lot NIfTI files -% contain slightly non-orthogonal rotation. Therefore, optional -% input parameter 'tolerance' is used to allow some distortion -% in the loaded image for any non-orthogonal rotation or shearing -% of NIfTI affine matrix. If you set 'tolerance' to 0, it means -% that you do not allow any distortion. If you set 'tolerance' to -% 1, it means that you do not care any distortion. The image will -% fail to be loaded if it can not be tolerated. The tolerance will -% be set to 0.1 (10%), if it is default or empty. -% -% Because 'reslice_nii.m' has to perform 3D interpolation, it can -% be slow depending on image size and affine matrix in the header. -% -% After you perform the affine transform, the 'nii' structure -% generated from 'xform_nii.m' or new NIfTI file created from -% 'reslice_nii.m' will be in RAS orientation, i.e. X axis from -% Left to Right, Y axis from Posterior to Anterior, and Z axis -% from Inferior to Superior. -% -% NOTE: This function should be called immediately after load_nii. -% -% Usage: [ nii ] = xform_nii(nii, [tolerance], [preferredForm]) -% -% nii - NIFTI structure (returned from load_nii) -% -% tolerance (optional) - distortion allowed for non-orthogonal rotation -% or shearing in NIfTI affine matrix. It will be set to 0.1 (10%), -% if it is default or empty. -% -% preferredForm (optional) - selects which transformation from voxels -% to RAS coordinates; values are s,q,S,Q. Lower case s,q indicate -% "prefer sform or qform, but use others if preferred not present". -% Upper case indicate the program is forced to use the specificied -% tranform or fail loading. 'preferredForm' will be 's', if it is -% default or empty. - Jeff Gunter -% -% NIFTI data format can be found on: http://nifti.nimh.nih.gov -% -% - Jimmy Shen (jimmy@rotman-baycrest.on.ca) -% -function nii = xform_nii(nii, tolerance, preferredForm) - - % save a copy of the header as it was loaded. This is the - % header before any sform, qform manipulation is done. - % - nii.original.hdr = nii.hdr; - - if ~exist('tolerance','var') | isempty(tolerance) - tolerance = 0.1; - elseif(tolerance<=0) - tolerance = eps; - end - - if ~exist('preferredForm','var') | isempty(preferredForm) - preferredForm= 's'; % Jeff - end - - % if scl_slope field is nonzero, then each voxel value in the - % dataset should be scaled as: y = scl_slope * x + scl_inter - % I bring it here because hdr will be modified by change_hdr. - % - if nii.hdr.dime.scl_slope ~= 0 & ... - ismember(nii.hdr.dime.datatype, [2,4,8,16,64,256,512,768]) & ... - (nii.hdr.dime.scl_slope ~= 1 | nii.hdr.dime.scl_inter ~= 0) - - nii.img = ... - nii.hdr.dime.scl_slope * double(nii.img) + nii.hdr.dime.scl_inter; - - if nii.hdr.dime.datatype == 64 - - nii.hdr.dime.datatype = 64; - nii.hdr.dime.bitpix = 64; - else - nii.img = single(nii.img); - - nii.hdr.dime.datatype = 16; - nii.hdr.dime.bitpix = 32; - end - - nii.hdr.dime.glmax = max(double(nii.img(:))); - nii.hdr.dime.glmin = min(double(nii.img(:))); - - % set scale to non-use, because it is applied in xform_nii - % - nii.hdr.dime.scl_slope = 0; - - end - - % However, the scaling is to be ignored if datatype is DT_RGB24. - - % If datatype is a complex type, then the scaling is to be applied - % to both the real and imaginary parts. - % - if nii.hdr.dime.scl_slope ~= 0 & ... - ismember(nii.hdr.dime.datatype, [32,1792]) - - nii.img = ... - nii.hdr.dime.scl_slope * double(nii.img) + nii.hdr.dime.scl_inter; - - if nii.hdr.dime.datatype == 32 - nii.img = single(nii.img); - end - - nii.hdr.dime.glmax = max(double(nii.img(:))); - nii.hdr.dime.glmin = min(double(nii.img(:))); - - % set scale to non-use, because it is applied in xform_nii - % - nii.hdr.dime.scl_slope = 0; - - end - - % There is no need for this program to transform Analyze data - % - if nii.filetype == 0 & exist([nii.fileprefix '.mat'],'file') - load([nii.fileprefix '.mat']); % old SPM affine matrix - R=M(1:3,1:3); - T=M(1:3,4); - T=R*ones(3,1)+T; - M(1:3,4)=T; - nii.hdr.hist.qform_code=0; - nii.hdr.hist.sform_code=1; - nii.hdr.hist.srow_x=M(1,:); - nii.hdr.hist.srow_y=M(2,:); - nii.hdr.hist.srow_z=M(3,:); - elseif nii.filetype == 0 - nii.hdr.hist.rot_orient = []; - nii.hdr.hist.flip_orient = []; - return; % no sform/qform for Analyze format - end - - hdr = nii.hdr; - - [hdr,orient]=change_hdr(hdr,tolerance,preferredForm); - - % flip and/or rotate image data - % - if ~isequal(orient, [1 2 3]) - - old_dim = hdr.dime.dim([2:4]); - - % More than 1 time frame - % - if ndims(nii.img) > 3 - pattern = 1:prod(old_dim); - else - pattern = []; - end - - if ~isempty(pattern) - pattern = reshape(pattern, old_dim); - end - - % calculate for rotation after flip - % - rot_orient = mod(orient + 2, 3) + 1; - - % do flip: - % - flip_orient = orient - rot_orient; - - for i = 1:3 - if flip_orient(i) - if ~isempty(pattern) - pattern = flipdim(pattern, i); - else - nii.img = flipdim(nii.img, i); - end - end - end - - % get index of orient (rotate inversely) - % - [tmp rot_orient] = sort(rot_orient); - - new_dim = old_dim; - new_dim = new_dim(rot_orient); - hdr.dime.dim([2:4]) = new_dim; - - new_pixdim = hdr.dime.pixdim([2:4]); - new_pixdim = new_pixdim(rot_orient); - hdr.dime.pixdim([2:4]) = new_pixdim; - - % re-calculate originator - % - tmp = hdr.hist.originator([1:3]); - tmp = tmp(rot_orient); - flip_orient = flip_orient(rot_orient); - - for i = 1:3 - if flip_orient(i) & ~isequal(tmp(i), 0) - tmp(i) = new_dim(i) - tmp(i) + 1; - end - end - - hdr.hist.originator([1:3]) = tmp; - hdr.hist.rot_orient = rot_orient; - hdr.hist.flip_orient = flip_orient; - - % do rotation: - % - if ~isempty(pattern) - pattern = permute(pattern, rot_orient); - pattern = pattern(:); - - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 | ... - hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - - tmp = reshape(nii.img(:,:,:,1), [prod(new_dim) hdr.dime.dim(5:8)]); - tmp = tmp(pattern, :); - nii.img(:,:,:,1) = reshape(tmp, [new_dim hdr.dime.dim(5:8)]); - - tmp = reshape(nii.img(:,:,:,2), [prod(new_dim) hdr.dime.dim(5:8)]); - tmp = tmp(pattern, :); - nii.img(:,:,:,2) = reshape(tmp, [new_dim hdr.dime.dim(5:8)]); - - if hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - tmp = reshape(nii.img(:,:,:,3), [prod(new_dim) hdr.dime.dim(5:8)]); - tmp = tmp(pattern, :); - nii.img(:,:,:,3) = reshape(tmp, [new_dim hdr.dime.dim(5:8)]); - end - - else - nii.img = reshape(nii.img, [prod(new_dim) hdr.dime.dim(5:8)]); - nii.img = nii.img(pattern, :); - nii.img = reshape(nii.img, [new_dim hdr.dime.dim(5:8)]); - end - else - if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792 | ... - hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - - nii.img(:,:,:,1) = permute(nii.img(:,:,:,1), rot_orient); - nii.img(:,:,:,2) = permute(nii.img(:,:,:,2), rot_orient); - - if hdr.dime.datatype == 128 | hdr.dime.datatype == 511 - nii.img(:,:,:,3) = permute(nii.img(:,:,:,3), rot_orient); - end - else - nii.img = permute(nii.img, rot_orient); - end - end - else - hdr.hist.rot_orient = []; - hdr.hist.flip_orient = []; - end - - nii.hdr = hdr; - - return; % xform_nii - - -%----------------------------------------------------------------------- -function [hdr, orient] = change_hdr(hdr, tolerance, preferredForm) - - orient = [1 2 3]; - affine_transform = 1; - - % NIFTI can have both sform and qform transform. This program - % will check sform_code prior to qform_code by default. - % - % If user specifys "preferredForm", user can then choose the - % priority. - Jeff - % - useForm=[]; % Jeff - - if isequal(preferredForm,'S') - if isequal(hdr.hist.sform_code,0) - error('User requires sform, sform not set in header'); - else - useForm='s'; - end - end % Jeff - - if isequal(preferredForm,'Q') - if isequal(hdr.hist.qform_code,0) - error('User requires qform, qform not set in header'); - else - useForm='q'; - end - end % Jeff - - if isequal(preferredForm,'s') - if hdr.hist.sform_code > 0 - useForm='s'; - elseif hdr.hist.qform_code > 0 - useForm='q'; - end - end % Jeff - - if isequal(preferredForm,'q') - if hdr.hist.qform_code > 0 - useForm='q'; - elseif hdr.hist.sform_code > 0 - useForm='s'; - end - end % Jeff - - if isequal(useForm,'s') - R = [hdr.hist.srow_x(1:3) - hdr.hist.srow_y(1:3) - hdr.hist.srow_z(1:3)]; - - T = [hdr.hist.srow_x(4) - hdr.hist.srow_y(4) - hdr.hist.srow_z(4)]; - - if det(R) == 0 | ~isequal(R(find(R)), sum(R)') - hdr.hist.old_affine = [ [R;[0 0 0]] [T;1] ]; - R_sort = sort(abs(R(:))); - R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0; - hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ]; - - if det(R) == 0 | ~isequal(R(find(R)), sum(R)') - msg = [char(10) char(10) ' Non-orthogonal rotation or shearing ']; - msg = [msg 'found inside the affine matrix' char(10)]; - msg = [msg ' in this NIfTI file. You have 3 options:' char(10) char(10)]; - msg = [msg ' 1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)]; - msg = [msg ' file. I strongly recommand this, because it will not cause' char(10)]; - msg = [msg ' negative effect, as long as you remember not to do slice' char(10)]; - msg = [msg ' time correction after using ''reslice_nii.m''.' char(10) char(10)]; - msg = [msg ' 2. Using included ''load_untouch_nii.m'' program to load image' char(10)]; - msg = [msg ' without applying any affine geometric transformation or' char(10)]; - msg = [msg ' voxel intensity scaling. This is only for people who want' char(10)]; - msg = [msg ' to do some image processing regardless of image orientation' char(10)]; - msg = [msg ' and to save data back with the same NIfTI header.' char(10) char(10)]; - msg = [msg ' 3. Increasing the tolerance to allow more distortion in loaded' char(10)]; - msg = [msg ' image, but I don''t suggest this.' char(10) char(10)]; - msg = [msg ' To get help, please type:' char(10) char(10) ' help reslice_nii.m' char(10)]; - msg = [msg ' help load_untouch_nii.m' char(10) ' help load_nii.m']; - error(msg); - end - end - - elseif isequal(useForm,'q') - b = hdr.hist.quatern_b; - c = hdr.hist.quatern_c; - d = hdr.hist.quatern_d; - - if 1.0-(b*b+c*c+d*d) < 0 - if abs(1.0-(b*b+c*c+d*d)) < 1e-5 - a = 0; - else - error('Incorrect quaternion values in this NIFTI data.'); - end - else - a = sqrt(1.0-(b*b+c*c+d*d)); - end - - qfac = hdr.dime.pixdim(1); - if qfac==0, qfac = 1; end - i = hdr.dime.pixdim(2); - j = hdr.dime.pixdim(3); - k = qfac * hdr.dime.pixdim(4); - - R = [a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c - 2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b - 2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b]; - - T = [hdr.hist.qoffset_x - hdr.hist.qoffset_y - hdr.hist.qoffset_z]; - - % qforms are expected to generate rotation matrices R which are - % det(R) = 1; we'll make sure that happens. - % - % now we make the same checks as were done above for sform data - % BUT we do it on a transform that is in terms of voxels not mm; - % after we figure out the angles and squash them to closest - % rectilinear direction. After that, the voxel sizes are then - % added. - % - % This part is modified by Jeff Gunter. - % - if det(R) == 0 | ~isequal(R(find(R)), sum(R)') - - % det(R) == 0 is not a common trigger for this --- - % R(find(R)) is a list of non-zero elements in R; if that - % is straight (not oblique) then it should be the same as - % columnwise summation. Could just as well have checked the - % lengths of R(find(R)) and sum(R)' (which should be 3) - % - hdr.hist.old_affine = [ [R * diag([i j k]);[0 0 0]] [T;1] ]; - R_sort = sort(abs(R(:))); - R( find( abs(R) < tolerance*min(R_sort(end-2:end)) ) ) = 0; - R = R * diag([i j k]); - hdr.hist.new_affine = [ [R;[0 0 0]] [T;1] ]; - - if det(R) == 0 | ~isequal(R(find(R)), sum(R)') - msg = [char(10) char(10) ' Non-orthogonal rotation or shearing ']; - msg = [msg 'found inside the affine matrix' char(10)]; - msg = [msg ' in this NIfTI file. You have 3 options:' char(10) char(10)]; - msg = [msg ' 1. Using included ''reslice_nii.m'' program to reslice the NIfTI' char(10)]; - msg = [msg ' file. I strongly recommand this, because it will not cause' char(10)]; - msg = [msg ' negative effect, as long as you remember not to do slice' char(10)]; - msg = [msg ' time correction after using ''reslice_nii.m''.' char(10) char(10)]; - msg = [msg ' 2. Using included ''load_untouch_nii.m'' program to load image' char(10)]; - msg = [msg ' without applying any affine geometric transformation or' char(10)]; - msg = [msg ' voxel intensity scaling. This is only for people who want' char(10)]; - msg = [msg ' to do some image processing regardless of image orientation' char(10)]; - msg = [msg ' and to save data back with the same NIfTI header.' char(10) char(10)]; - msg = [msg ' 3. Increasing the tolerance to allow more distortion in loaded' char(10)]; - msg = [msg ' image, but I don''t suggest this.' char(10) char(10)]; - msg = [msg ' To get help, please type:' char(10) char(10) ' help reslice_nii.m' char(10)]; - msg = [msg ' help load_untouch_nii.m' char(10) ' help load_nii.m']; - error(msg); - end - - else - R = R * diag([i j k]); - end % 1st det(R) - - else - affine_transform = 0; % no sform or qform transform - end - - if affine_transform == 1 - voxel_size = abs(sum(R,1)); - inv_R = inv(R); - originator = inv_R*(-T)+1; - orient = get_orient(inv_R); - - % modify pixdim and originator - % - hdr.dime.pixdim(2:4) = voxel_size; - hdr.hist.originator(1:3) = originator; - - % set sform or qform to non-use, because they have been - % applied in xform_nii - % - hdr.hist.qform_code = 0; - hdr.hist.sform_code = 0; - end - - % apply space_unit to pixdim if not 1 (mm) - % - space_unit = get_units(hdr); - - if space_unit ~= 1 - hdr.dime.pixdim(2:4) = hdr.dime.pixdim(2:4) * space_unit; - - % set space_unit of xyzt_units to millimeter, because - % voxel_size has been re-scaled - % - hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,1,0)); - hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,2,1)); - hdr.dime.xyzt_units = char(bitset(hdr.dime.xyzt_units,3,0)); - end - - hdr.dime.pixdim = abs(hdr.dime.pixdim); - - return; % change_hdr - - -%----------------------------------------------------------------------- -function orient = get_orient(R) - - orient = []; - - for i = 1:3 - switch find(R(i,:)) * sign(sum(R(i,:))) - case 1 - orient = [orient 1]; % Left to Right - case 2 - orient = [orient 2]; % Posterior to Anterior - case 3 - orient = [orient 3]; % Inferior to Superior - case -1 - orient = [orient 4]; % Right to Left - case -2 - orient = [orient 5]; % Anterior to Posterior - case -3 - orient = [orient 6]; % Superior to Inferior - end - end - - return; % get_orient - - -%----------------------------------------------------------------------- -function [space_unit, time_unit] = get_units(hdr) - - switch bitand(hdr.dime.xyzt_units, 7) % mask with 0x07 - case 1 - space_unit = 1e+3; % meter, m - case 3 - space_unit = 1e-3; % micrometer, um - otherwise - space_unit = 1; % millimeter, mm - end - - switch bitand(hdr.dime.xyzt_units, 56) % mask with 0x38 - case 16 - time_unit = 1e-3; % millisecond, ms - case 24 - time_unit = 1e-6; % microsecond, us - otherwise - time_unit = 1; % second, s - end - - return; % get_units - diff --git a/Plotting/Create_CAP_colorbar.m b/Plotting/Create_CAP_colorbar.m deleted file mode 100755 index be85c38..0000000 --- a/Plotting/Create_CAP_colorbar.m +++ /dev/null @@ -1,56 +0,0 @@ -%% Creates a nice looking colorbar for the CAP display -function [Ah,h] = Create_CAP_colorbar(absmin,absmax,absstep,colT,lab,Ah,Ori,CB1,CB2,n_steps) - - H_range = [absmin absmax]; % The colormap is symmetric around zero - - % Set the Min/Max T-values for alpha coding - A_range = [0 1]; - - % Set the labels for the colorbar - hue_label = lab; - - colrange = linspace(absmin,absmax,256); - - switch Ori - case 'Horizontal' - - y = linspace(A_range(1), A_range(2), 256); - % x represents the range in alpha (abs(t-stats)) - x = linspace(H_range(1), H_range(2), 256); - % y represents the range in hue (beta weight difference) - [X,Y] = meshgrid(x,y); % Transform into a 2D matrix - - h=imagesc(x,y,X,'Parent',Ah); - axis(Ah,'xy'); % Plot the colorbar - set(Ah, 'Xcolor', 'k', 'Ycolor', 'k','YTickLabel','','YTick',[],'XTick',absmin:absstep:absmax,'FontSize',8); - set(Ah, 'XAxisLocation', 'bottom'); - xlabel(Ah,hue_label,'FontSize',8); - - A = ones(size(X)); - A(abs(X) < colT) = 0; - A = reshape(A,256,256); - - case 'Vertical' - - x = linspace(A_range(1), A_range(2), 256); - % x represents the range in alpha (abs(t-stats)) - y = linspace(H_range(1), H_range(2), 256); - % y represents the range in hue (beta weight difference) - [X,Y] = meshgrid(x,y); % Transform into a 2D matrix - - h=imagesc(x,y,Y,'Parent',Ah); - axis(Ah,'xy'); % Plot the colorbar - set(Ah, 'Xcolor', 'k', 'Ycolor', 'k','XTickLabel','','XTick',[],'YTick',absmin:absstep:absmax,'FontSize',8); - set(Ah, 'YAxisLocation', 'right'); - ylabel(Ah,hue_label,'FontSize',8); - - A = ones(size(Y)); - A(abs(Y) < colT) = 0; - A = reshape(A,256,256); - end - - tmp_cmap = cbrewer(CB1,CB2,n_steps); - colormap(Ah,flipud(tmp_cmap)); - - set(h,'AlphaData',A); -end \ No newline at end of file diff --git a/Plotting/MakeViolin.m b/Plotting/MakeViolin.m deleted file mode 100755 index d7adf60..0000000 --- a/Plotting/MakeViolin.m +++ /dev/null @@ -1,55 +0,0 @@ -%% Makes a violin plot with overlapped boxplot, tuning colors -% Y and O are vectors containing the data to plot for the two conditions -% Color has light colors for background (first cell) and dark colors for -% average (second cell), for maximum 4 populations -function [box,h_viol,ah] = MakeViolin(Y,ah,Lab,YLabel,Color,n_pop,n_states) - - % Range of the plot - Max = max(max((Y))); - Min = min(min((Y))); - Max = Max + 0.15*max(abs(Min),Max); - Min = Min - 0.15*max(abs(Min),Max); - - % Plots the distribution - ylim(ah,[Min,Max]); - - % Colors for the background - Col_final = num2cell(Color{1},2); - Col_final = Col_final(1:n_pop); - Col_final = repmat(Col_final,n_states,1); - - % Colors for the foreground - Col_final2 = num2cell(Color{2},2); - Col_final2 = Col_final2(1:n_pop); - Col_final2 = repmat(Col_final2,n_states,1); - - Lab_final = {}; - - for i = 1:n_states - Lab_final = [Lab_final, repmat({Lab{i}},1,n_pop)]; - end - - h_viol = distributionPlot(ah,Y','showMM',0,'color',Col_final,'yLabel',YLabel,'xNames',Lab_final); - hold(ah,'on'); - box = boxplot(Y','Parent',ah,'Labels',Lab_final); - - h_box = findobj(box,'Tag','Box'); - set(h_box,'color','k','LineWidth',2); - - h_median = findobj(box,'Tag','Median'); - h_outliers = findobj(box,'Tag','Outliers'); - - for i = 1:n_pop - for j = 1:n_states - - idx_oi = i+(j-1)*n_pop; - - set(h_median(idx_oi),'color',Col_final2{idx_oi},'LineWidth',2); - set(h_outliers(idx_oi),'Marker','o','MarkerFaceColor',Col_final2{n_pop*n_states-idx_oi+1},... - 'MarkerEdgeColor',Col_final2{idx_oi},'MarkerSize',3); - - end - end - - set(ah,'Box','off'); -end \ No newline at end of file diff --git a/Plotting/cbrewer/cbrewer.m b/Plotting/cbrewer/cbrewer.m deleted file mode 100644 index 26be891..0000000 --- a/Plotting/cbrewer/cbrewer.m +++ /dev/null @@ -1,128 +0,0 @@ -function [colormap]=cbrewer(ctype, cname, ncol, interp_method) -% -% CBREWER - This function produces a colorbrewer table (rgb data) for a -% given type, name and number of colors of the colorbrewer tables. -% For more information on 'colorbrewer', please visit -% http://colorbrewer2.org/ -% -% The tables were generated from an MS-Excel file provided on the website -% http://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_updates.html -% -% -% [colormap]=cbrewer(ctype, cname, ncol, interp_method) -% -% INPUT: -% - ctype: type of color table 'seq' (sequential), 'div' (diverging), 'qual' (qualitative) -% - cname: name of colortable. It changes depending on ctype. -% - ncol: number of color in the table. It changes according to ctype and -% cname -% - interp_method: interpolation method (see interp1.m). Default is "cubic" ) -% -% A note on the number of colors: Based on the original data, there is -% only a certain number of colors available for each type and name of -% colortable. When 'ncol' is larger then the maximum number of colors -% originally given, an interpolation routine is called (interp1) to produce -% the "extended" colormaps. -% -% Example: To produce a colortable CT of ncol X 3 entries (RGB) of -% sequential type and named 'Blues' with 8 colors: -% CT=cbrewer('seq', 'Blues', 8); -% To use this colortable as colormap, simply call: -% colormap(CT) -% -% To see the various colormaps available according to their types and -% names, simply call: cbrewer() -% -% This product includes color specifications and designs developed by -% Cynthia Brewer (http://colorbrewer.org/). -% -% Author: Charles Robert -% email: tannoudji@hotmail.com -% Date: 06.12.2011 -% ------------------------------ -% 18.09.2015 Minor fixes, fixed a bug where the 'spectral' color table did not appear in the preview - - -% load colorbrewer data -load('colorbrewer.mat') -% initialise the colormap is there are any problems -colormap=[]; -if (~exist('interp_method', 'var')) - interp_method='cubic'; -end - -% If no arguments -if (~exist('ctype', 'var') | ~exist('cname', 'var') | ~exist('ncol', 'var')) - disp(' ') - disp('[colormap] = cbrewer(ctype, cname, ncol [, interp_method])') - disp(' ') - disp('INPUT:') - disp(' - ctype: type of color table *seq* (sequential), *div* (divergent), *qual* (qualitative)') - disp(' - cname: name of colortable. It changes depending on ctype.') - disp(' - ncol: number of color in the table. It changes according to ctype and cname') - disp(' - interp_method: interpolation method (see interp1.m). Default is "cubic" )') - - disp(' ') - disp('Sequential tables:') - z={'Blues','BuGn','BuPu','GnBu','Greens','Greys','Oranges','OrRd','PuBu','PuBuGn','PuRd',... - 'Purples','RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd', 'Spectral'}; - disp(z') - - disp('Divergent tables:') - z={'BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn'}; - disp(z') - - disp(' ') - disp('Qualitative tables:') - %getfield(colorbrewer, 'qual') - z={'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3'}; - disp(z') - - plot_brewer_cmap - return -end - -% Verify that the input is appropriate -ctype_names={'div', 'seq', 'qual'}; -if (~ismember(ctype,ctype_names)) - disp('ctype must be either: *div*, *seq* or *qual*') - colormap=[]; - return -end - -if (~isfield(colorbrewer.(ctype),cname)) - disp(['The name of the colortable of type *' ctype '* must be one of the following:']) - getfield(colorbrewer, ctype) - colormap=[]; - return -end - -if (ncol>length(colorbrewer.(ctype).(cname))) -% disp(' ') -% disp('----------------------------------------------------------------------') -% disp(['The maximum number of colors for table *' cname '* is ' num2str(length(colorbrewer.(ctype).(cname)))]) -% disp(['The new colormap will be extrapolated from these ' num2str(length(colorbrewer.(ctype).(cname))) ' values']) -% disp('----------------------------------------------------------------------') -% disp(' ') - cbrew_init=colorbrewer.(ctype).(cname){length(colorbrewer.(ctype).(cname))}; - colormap=interpolate_cbrewer(cbrew_init, interp_method, ncol); - colormap=colormap./255; - return -end - -if (isempty(colorbrewer.(ctype).(cname){ncol})) - - while(isempty(colorbrewer.(ctype).(cname){ncol})) - ncol=ncol+1; - end - disp(' ') - disp('----------------------------------------------------------------------') - disp(['The minimum number of colors for table *' cname '* is ' num2str(ncol)]) - disp('This minimum value shall be defined as ncol instead') - disp('----------------------------------------------------------------------') - disp(' ') -end - -colormap=(colorbrewer.(ctype).(cname){ncol})./255; - -end \ No newline at end of file diff --git a/Plotting/cbrewer/cbrewer_preview.jpg b/Plotting/cbrewer/cbrewer_preview.jpg deleted file mode 100644 index bd2830a..0000000 Binary files a/Plotting/cbrewer/cbrewer_preview.jpg and /dev/null differ diff --git a/Plotting/cbrewer/change_jet.m b/Plotting/cbrewer/change_jet.m deleted file mode 100644 index b8d4ecb..0000000 --- a/Plotting/cbrewer/change_jet.m +++ /dev/null @@ -1,64 +0,0 @@ -% This script help produce a new 'jet'-like colormap based on other RGB reference colors - -% ------- I WAS ASKED --------------- -% "is there a chance that you could add a diverging map going from blue to green to red as in jet, -% but using the red and blue from your RdBu map and the third darkest green from your RdYlGn map?"" -% -% ANSWER: -% You should construct the new colormap based on the existing RGB values of 'jet' -% but projecting these RGB values on your new RGB basis. -% ----------------------------------- - -% load colormaps -jet=colormap('jet'); -RdBu=cbrewer('div', 'RdBu', 11); -RdYlGn=cbrewer('div', 'RdYlGn', 11); - -% Define the new R, G, B references (p stands for prime) -Rp=RdBu(1,:); -Bp=RdBu(end, :); -Gp=RdYlGn(end-2, :); -RGBp=[Rp;Gp;Bp]; - -% construct the new colormap based on the existing RGB values of jet -% Project the RGB values on your new basis -newjet = jet*RGBp; - -% store data in a strcuture, easier to handle -cmap.jet=jet; -cmap.newjet=newjet; -cnames={'jet', 'newjet'}; - -% plot the RGB values -fh=figure(); -colors={'r', 'g', 'b'}; -for iname=1:length(cnames) - subplot(length(cnames),1,iname) - dat=cmap.(cnames{end-iname+1}); - for icol=1:size(dat,2) - plot(dat(:,icol), 'color', colors{icol}, 'linewidth', 2);hold on; - end % icol - title([' "' cnames{end-iname+1} '" in RGB plot']) -end - -% plot the colormaps -fh=figure(); -for iname=1:length(cnames) - F=cmap.(cnames{iname}); - ncol=length(F); - fg=1./ncol; % geometrical factor - X=fg.*[0 0 1 1]; - Y=0.1.*[1 0 0 1]+(2*iname-1)*0.1; - - for icol=1:ncol - X2=X+fg.*(icol-1); - fill(X2,Y,F(icol, :), 'linestyle', 'none') - hold all - end % icol - text(-0.1, mean(Y), cnames{iname}, 'HorizontalAlignment', 'right', 'FontWeight', 'bold', 'FontSize', 10, 'FontName' , 'AvantGarde') - xlim([-0.4, 1]) - axis off - set(gcf, 'color', [1 1 1]) - ylim([0.1 1.05.*max(Y)]); - end % iname - diff --git a/Plotting/cbrewer/colorbrewer.mat b/Plotting/cbrewer/colorbrewer.mat deleted file mode 100644 index ec59ef4..0000000 Binary files a/Plotting/cbrewer/colorbrewer.mat and /dev/null differ diff --git a/Plotting/cbrewer/interpolate_cbrewer.m b/Plotting/cbrewer/interpolate_cbrewer.m deleted file mode 100644 index e8b5e21..0000000 --- a/Plotting/cbrewer/interpolate_cbrewer.m +++ /dev/null @@ -1,36 +0,0 @@ -function [interp_cmap]=interpolate_cbrewer(cbrew_init, interp_method, ncolors) -% -% INTERPOLATE_CBREWER - interpolate a colorbrewer map to ncolors levels -% -% INPUT: -% - cbrew_init: the initial colormap with format N*3 -% - interp_method: interpolation method, which can be the following: -% 'nearest' - nearest neighbor interpolation -% 'linear' - bilinear interpolation -% 'spline' - spline interpolation -% 'cubic' - bicubic interpolation as long as the data is -% uniformly spaced, otherwise the same as 'spline' -% - ncolors=desired number of colors -% -% Author: Charles Robert -% email: tannoudji@hotmail.com -% Date: 14.10.2011 - - -% just to make sure, in case someone puts in a decimal -ncolors=round(ncolors); - -% How many data points of the colormap available -nmax=size(cbrew_init,1); - -% create the associated X axis (using round to get rid of decimals) -a=(ncolors-1)./(nmax-1); -X=round([0 a:a:(ncolors-1)]); -X2=0:ncolors-1; - -z=interp1(X,cbrew_init(:,1),X2,interp_method); -z2=interp1(X,cbrew_init(:,2),X2,interp_method); -z3=interp1(X,cbrew_init(:,3),X2, interp_method); -interp_cmap=round([z' z2' z3']); - -end \ No newline at end of file diff --git a/Plotting/cbrewer/plot_brewer_cmap.m b/Plotting/cbrewer/plot_brewer_cmap.m deleted file mode 100644 index a5cab9e..0000000 --- a/Plotting/cbrewer/plot_brewer_cmap.m +++ /dev/null @@ -1,50 +0,0 @@ -% Plots and identifies the various colorbrewer tables available. -% Is called by cbrewer.m when no arguments are given. -% -% Author: Charles Robert -% email: tannoudji@hotmail.com -% Date: 14.10.2011 - - - -load('colorbrewer.mat') - -ctypes={'div', 'seq', 'qual'}; -ctypes_title={'Diverging', 'Sequential', 'Qualitative'}; -cnames{1,:}={'BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral'}; -cnames{2,:}={'Blues','BuGn','BuPu','GnBu','Greens','Greys','Oranges','OrRd','PuBu','PuBuGn','PuRd',... - 'Purples','RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'}; -cnames{3,:}={'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3'}; - -figure('position', [314 327 807 420]) -for itype=1:3 - - %fh(itype)=figure(); - subplot(1,3,itype) - - for iname=1:length(cnames{itype,:}) - - ncol=length(colorbrewer.(ctypes{itype}).(cnames{itype}{iname})); - fg=1./ncol; % geometrical factor - - X=fg.*[0 0 1 1]; - Y=0.1.*[1 0 0 1]+(2*iname-1)*0.1; - F=cbrewer(ctypes{itype}, cnames{itype}{iname}, ncol); - - for icol=1:ncol - X2=X+fg.*(icol-1); - fill(X2,Y,F(icol, :), 'linestyle', 'none') - text(-0.1, mean(Y), cnames{itype}{iname}, 'HorizontalAlignment', 'right', 'FontWeight', 'bold', 'FontSize', 10, 'FontName' , 'AvantGarde') - xlim([-0.4, 1]) - hold all - end % icol - %set(gca, 'box', 'off') - title(ctypes_title{itype}, 'FontWeight', 'bold', 'FontSize', 16, 'FontName' , 'AvantGarde') - axis off - set(gcf, 'color', [1 1 1]) - end % iname - ylim([0.1 1.05.*max(Y)]); -end %itype - -set(gcf, 'MenuBar', 'none') -set(gcf, 'Name', 'ColorBrewer Color maps') \ No newline at end of file diff --git a/Plotting/distributionPlot.m b/Plotting/distributionPlot.m deleted file mode 100755 index 352cc69..0000000 --- a/Plotting/distributionPlot.m +++ /dev/null @@ -1,902 +0,0 @@ -function handles = distributionPlot(varargin) -%DISTRIBUTIONPLOT creates violin plots for convenient visualization of multiple distributions -% -% SYNOPSIS: handles = distributionPlot(data,propertyName,propertyValue,...) -% handles = distributionPlot(ah,...) -% -% INPUT data : m-by-nData array of values, or vector of grouped data (use -% the 'groups' property to specify the grouping variable), or -% cell array of length nData. -% The cell array can either contain vectors with values, or -% m-by-2 arrays with [bins,counts] if you want to determine the -% histograms by yourself (m can be different between cell -% elements). Note that arrays inside cells with any -% other shape than m-by-2 are reshaped to vector an a warning is -% thrown (DISTRIBUTIONPLOT:AUTORESHAPE). -% -% DISTRIBUTIONPLOT accepts the following propertyName/propertyValue -% pairs (all are optional): -% -% distWidth : width of distributions; ideally between 0 and 1. -% 1 means that adjacent distributions might touch. Default: 0.9 -% variableWidth : If true, the width of the distribution changes, -% reflecting the shape of the histogram of the data. If false, -% the distribution is only encoded by color levels. Default: true -% color : uniform coloring of histograms. Supply either a color -% string ('r'), or a truecolor vector ([1 0 0]). Use a -% cell array of length nData to specify one color per -% distribution. Default: 'k' -% If variableWidth is set to false, a colormap is generated that -% goes from white to the chose color (or from black, if -% invert==true). -% If both 'color', and 'colormap' are specified, 'colormap' takes -% precedence. -% colormap : colormap used to describe the distribution (first row -% corresponds to bins with least data, last row corresponds to -% bins with most data (invert the grayscale colormap to have -% black indicate the most data). -% Supply a cell array of length nData to color distributions -% individually. Note that using multiple colormaps means that -% the colorbar doesn't contain much useful information. -% Default: [] -% Colormap will index into the figure colormap, which will be -% modified by distributionPlot. This is done to allow editing the -% distributions in e.g. Adobe Illustrator. -% If both 'color', and 'colormap' are specified, 'colormap' takes -% precedence. -% globalNorm : normalization for bin width (x-direction) -% 0 : every histogram is normalized individually so that the -% maximum bin width is equal to distWidth. This is best -% suited to comparing distribution shapes. Default. -% 1 : histograms are normalized such that equal bin width -% reports equal numbers of counts per bin. -% 2 : histograms are normalized so that the relative areas -% covered by the histograms reflect the relative total number -% of data points. -% 3 : histograms areas are normalized so that relative densities -% are the same across histograms. Thus, if -% data = {rand(100,1),rand(500,1)}, -% then -% distributionPlot(data,'globalNorm',2,'histOpt',0,'divFactor',10) -% shows the left histogram 5x as wide as the right, while -% distributionPlot(data,'globalNorm',3,'histOpt',0,'divFactor',10) -% displays both histograms equally wide, since each bin -% contains ~10% of the data. -% Options 1 and 2 produce similar results if the bins are spaced -% equally for the distributions. Options 0 and 3 produce similar -% results if the data are drawn from the same distributions. -% Note that colormaps currently always report the number of data -% points per bin; 'globalNorm' only applies to the distribution -% shape. -% -% groups : grouping variable for grouped data. Grouping will be -% resolved by calling grp2idx, and unless xNames have -% been supplied, group names determine the x-labels. -% If the grouping variable is numeric, group labels also -% determine x-values, unless the parameter xValues has -% been specified. -% histOpt : histogram type to plot -% 0 : use hist command (no smoothing, fixed number of -% bins) -% 1 : smoothened histogram using ksdensity with -% Normal kernel. Default. -% 1.1: smoothened histogram using ksdensity where the -% kernel is robustly estimated via histogram.m. -% Normal kernel. -% 2 : histogram command (no smoothing, automatic -% determination of thickness (y-direction) of bins) -% divFactor : Parameter dependent on histOpt. If... -% histOpt == 0: divFactor = # of bins. Default: 25. -% Alternatively, pass a vector which will be -% interpreted as bin centers. -% histOpt == 1: divFactor decides by how much the default -% kernel-width is multiplied in order to avoid an -% overly smooth histogram. Default: 1/2 -% histOpt == 2: divFactor decides by how much the -% automatic bin width is multiplied in order to have -% more (<1) or less (>1) detail. Default: 1 -% addSpread : if 1, data points are plotted with plotSpread. -% distWidth is ideally set to 0.95 -% This option is not available if the data is supplied as -% histograms. -% Please download plotSpread.m separately from the File -% Exchange using the link in the remarks -% showMM : if 1, mean and median are shown as red crosses and -% green squares, respectively. This is the default -% 2: only mean -% 3: only median -% 4: mean +/- standard error of the mean (no median) -% 5: mean +/- standard deviation (no median) -% 6: draw lines at the 25,50,75 percentiles (no mean) -% 0: plot neither mean nor median -% xValues: x-coordinate where the data should be plotted. -% If xValues are given, "distWidth" is scaled by the median -% difference between adjacent (sorted) x-values. Note that -% this may lead to overlapping distributions. Default: -% 1:nData -% xNames : cell array of length nData containing x-tick names -% (instead of the default '1,2,3') -% xMode : if 'auto', x-ticks are spaced automatically. If 'manual', -% there is a tick for each distribution. If xNames is -% provided as input, xMode is forced to 'manual'. Default: -% 'manual'. -% NOTE: SPECIFYING XNAMES OR XVALUES OR XMODE WILL ERASE PREVIOUS -% LABELS IF PLOTTING INTO EXISTING AXES -% yLabel : string with label for y-axis. Default : '' -% If empty and data is histograms, ylabel is set to 'counts' -% invert : if 1, axes color is changed to black, and colormap is -% inverted. -% histOri: Orientation of histogram. Either 'center', 'left', or -% 'right'. With 'left' or 'right', the left or right half of -% the standard violin plot is shown. Has no effect if -% variableWidth is false. Default: center -% xyOri : orientation of axes. Either 'normal' (=default), or -% 'flipped'. If 'flipped', the x-and y-axes are switched, so -% that violin plots are horizontal. Consequently, -% axes-specific properties, such as 'yLabel' are applied to -% the other axis. -% widthDiv : 1-by-2 array with [numberOfDivisions,currentDivision] -% widthDiv allows cutting the stripe dedicated to a single -% distribution into multible bands, which can be filled with -% sequential calls to distributionPlot. This is one way -% to compare two (or more) sequences of distributions. See -% example below. -% ah : axes handle to plot the distributions. Default: gca -% -% OUTPUT handles : 1-by-4 cell array with patch-handles for the -% distributions, plot handles for mean/median, the -% axes handle, and the plotSpread-points handle -% -% -% EXAMPLES -% %--Distributions contain more information than boxplot can capture -% r = rand(1000,1); -% rn = randn(1000,1)*0.38+0.5; -% rn2 = [randn(500,1)*0.1+0.27;randn(500,1)*0.1+0.73]; -% rn2=min(rn2,1);rn2=max(rn2,0); -% figure -% ah(1)=subplot(3,4,1:2); -% boxplot([r,rn,rn2]) -% ah(2)=subplot(3,4,3:4); -% distributionPlot([r,rn,rn2],'histOpt',2); % histOpt=2 works better for uniform distributions than the default -% set(ah,'ylim',[-1 2]) -% -% %--- additional options -% -% data = [randn(100,1);randn(50,1)+4;randn(25,1)+8]; -% subplot(3,4,5) -% -% %--- defaults -% distributionPlot(data); -% subplot(3,4,6) -% -% %--- show density via custom colormap only, show mean/std, -% distributionPlot(data,'colormap',copper,'showMM',5,'variableWidth',false) -% subplot(3,4,7:8) -% -% %--- auto-binwidth depends on # of datapoints; for small n, plotting the data is useful -% % note that this option requires the additional installation -% % of plotSpread from the File Exchange (link below) -% distributionPlot({data(1:5:end),repmat(data,2,1)},'addSpread',true,'showMM',false,'histOpt',2) -% -% %--- show quantiles -% subplot(3,4,9),distributionPlot(randn(100,1),'showMM',6) -% -% %--- horizontal orientation -% subplot(3,4,10:11), -% distributionPlot({chi2rnd(3,1000,1),chi2rnd(5,1000,1)},'xyOri','flipped','histOri','right','showMM',0), -% xlim([-3 13]) -% -% %--- compare distributions side-by-side (see also example below) -% % plotting into specified axes will throw a warning that you can -% % turn off using " warning off DISTRIBUTIONPLOT:ERASINGLABELS " -% ah = subplot(3,4,12); -% subplot(3,4,12),distributionPlot(chi2rnd(3,1000,1),'histOri','right','color','r','widthDiv',[2 2],'showMM',0) -% subplot(3,4,12),distributionPlot(chi2rnd(5,1000,1),'histOri','left','color','b','widthDiv',[2 1],'showMM',0) -% -% %--Use globalNorm to generate meaningful colorbar -% data = {randn(100,1),randn(500,1)}; -% figure -% distributionPlot(data,'globalNorm',true,'colormap',1-gray(64),'histOpt',0,'divFactor',[-5:0.5:5]) -% colorbar -% -% %--Use widthDiv to compare two series of distributions -% data1 = randn(500,5); -% data2 = bsxfun(@plus,randn(500,5),0:0.1:0.4); -% figure -% distributionPlot(data1,'widthDiv',[2 1],'histOri','left','color','b','showMM',4) -% distributionPlot(gca,data2,'widthDiv',[2 2],'histOri','right','color','k','showMM',4) -% -% %--Christmas trees! -% x=meshgrid(1:10,1:10); -% xx = tril(x); -% xx = xx(xx>0); -% figure -% hh=distributionPlot({xx,xx,xx},'color','g','addSpread',1,'histOpt',2,'showMM',0); -% set(hh{4}{1},'color','r','marker','o') -% END -% -% REMARKS To show distributions as clouds of points (~beeswarm plot), -% and/or to use the option "addSpread", please download the -% additional function plotSpread.m from the File Exchange -% http://www.mathworks.com/matlabcentral/fileexchange/37105-plot-spread-points-beeswarm-plot -% -% I used to run ksdensity with the Epanechnikov kernel. However, -% for integer data, the shape of the kernel can produce peaks -% between the integers, which is not ideal (use histOpt=2 for -% integer valued data). -% -% A previous iteration of distributionPlot used the input -% specifications below. They still work to ensure backward -% compatibility, but are no longer supported or updated. -% handles = distributionPlot(data,distWidth,showMM,xNames,histOpt,divFactor,invert,addSpread,globalNorm) -% where distWidth of 1 means that the maxima -% of two adjacent distributions might touch. Negative numbers -% indicate that the distributions should have constant width, i.e -% the density is only expressed through greylevels. -% Values between 1 and 2 are like values between 0 and 1, except -% that densities are not expressed via graylevels. Default: 1.9 -% -% -% SEE ALSO histogram, ksdensity, plotSpread, boxplot, grp2idx -% - -% created with MATLAB ver.: 7.6.0.324 (R2008a) on Windows_NT -% -% created by: Jonas Dorn; jonas.dorn@gmail.com -% DATE: 08-Jul-2008 -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%==================================== -%% TEST INPUT -%==================================== - -% set defaults -def.xNames = []; -def.showMM = 1; -def.distWidth = 0.9; -def.histOpt = 1; -def.divFactor = [25,2,1]; -def.invert = false; -def.colormap = []; -def.color = 'k'; -def.addSpread = false; -def.globalNorm = false; -def.variableWidth = true; -def.groups = []; -def.yLabel = ''; -def.xValues = ''; -def.xMode = 'manual'; -def.histOri = 'center'; -def.xyOri = 'normal'; -def.widthDiv = [1 1]; -isHistogram = false; %# this parameter is not set by input - - -if nargin == 0 || isempty(varargin{1}) - error('not enough input arguments') -end - -% check for axes handle -if ~iscell(varargin{1}) && isscalar(varargin{1}) == 1 && ... - ishandle(varargin{1}) && strcmp(get(varargin{1},'Type'),'axes') - ah = varargin{1}; - data = varargin{2}; - varargin(1:2) = []; - newAx = false; - - -else - ah = gca; - data = varargin{1}; - varargin(1) = []; - newAx = true; -end - -% check for current axes limits. Set NaN if the axes have no children -% yet - we need that in case we're building a complicated set of -% distributions -if ~isempty(get(ah,'children')) - xAxLim = xlim; - yAxLim = ylim; -else - [xAxLim,yAxLim] = deal([NaN NaN]); -end - -fh = get(ah,'Parent'); - -% check data. If not cell, convert -if ~iscell(data) - [nPoints,nData] = size(data); - data = mat2cell(data,nPoints,ones(nData,1)); -else - % get nData - data = data(:); - nData = length(data); - % make sure all are vectors - badCol = ~cellfun(@isvector,data) & ~cellfun(@isempty,data); - if any(badCol) - nCols = cellfun(@(x)(size(x,2)),data(badCol)); - if all(nCols==2) - % bins,counts - isHistogram = true; - else - warning('DISTRIBUTIONPLOT:AUTORESHAPE',... - 'Elements %s of the cell array are not vectors. They will be reshaped automatically',... - num2str(find(badCol)')); - data(badCol) = cellfun(@(x)(x(:)),data(badCol),'UniformOutput',false); - end - end -end - -parserObj = inputParser; -parserObj.FunctionName = 'distributionPlot'; -stdWidth = 1; % scaling parameter for variableWidth with uneven x-values -% check whether we're dealing with pN/pV or straight arguments -if ~isempty(varargin) && ~ischar(varargin{1}) && ~isstruct(varargin{1}) - % use old format - % distWidth,showMM,xNames,histOpt,divFactor,invert,addSpread,globalNorm - def.distWidth = 1.9; - parserObj.addOptional('distWidth',def.distWidth); - parserObj.addOptional('showMM',def.showMM); - parserObj.addOptional('xNames',def.xNames); - parserObj.addOptional('histOpt',def.histOpt); - parserObj.addOptional('divFactor',def.divFactor); - parserObj.addOptional('invert',def.invert); - parserObj.addOptional('addSpread',def.addSpread); - parserObj.addOptional('globalNorm',def.globalNorm); - parserObj.addOptional('groups',def.groups); - parserObj.addOptional('yLabel',def.yLabel); - parserObj.addOptional('color',def.color); - - - parserObj.parse(varargin{:}); - opt = parserObj.Results; - % fill in defaults that are not supported in the old version of the - % code - opt.colormap = []; - opt.variableWidth = true; - opt.histOri = 'center'; - opt.xValues = []; - opt.xMode = 'auto'; - opt.xyOri = 'normal'; - opt.widthDiv = [1 1]; - - % overwrite empties with defaults - inputParser considers empty to be a - % valid input. - fnList = fieldnames(opt); - for fn = fnList' - if isempty(opt.(fn{1})) - opt.(fn{1}) = def.(fn{1}); - end - end - - - % fix a few parameters - if opt.distWidth > 1 - opt.distWidth = opt.distWidth - 1; - else - opt.colormap = 1-gray(128); - end - if opt.distWidth < 0 - opt.variableWidth = false; - opt.distWidth = abs(opt.distWidth); - end - - if ~isempty(opt.xNames) - opt.xMode = 'manual'; - end - - -else - defNames = fieldnames(def); - for dn = defNames(:)' - parserObj.addParamValue(dn{1},def.(dn{1})); - end - - - parserObj.parse(varargin{:}); - opt = parserObj.Results; - - % if groups: deal with data - if ~isempty(opt.groups) - [idx,labels,vals] = grp2idx(opt.groups); - % convert data to cell array - data = accumarray(idx,data{1},[],@(x){x}); - nData = length(data); - % if not otherwise provided, use group labels for xnames - if isempty(opt.xNames) - opt.xNames = labels; - if ~iscell(opt.xNames) - opt.xNames = num2cell(opt.xNames); - end - end - if isnumeric(vals) && isempty(opt.xValues) - opt.xValues = vals; - end - - end - - if ~ischar(opt.xyOri) || ~any(ismember(opt.xyOri,{'normal','flipped'})) - error('option xyOri must be either ''normal'' or ''flipped'' (is ''%s'')',opt.xyOri); - end - - - - -end -% common checks - -% default x-values: 1:n -if isempty(opt.xValues) - opt.xValues = 1:nData; -elseif length(opt.xValues) ~= nData - error('please supply as many x-data values as there are data entries') -elseif length(opt.xValues) > 1 % only check for scale if more than 1 value - % scale width - stdWidth = median(diff(sort(opt.xValues))); - opt.distWidth = opt.distWidth * stdWidth; -end - -if ~isscalar(opt.divFactor) && length(opt.divFactor) == 3 && all(opt.divFactor==def.divFactor) - opt.divFactor = opt.divFactor(floor(opt.histOpt)+1); -end -if isHistogram - opt.histOpt = 99; - if isempty(opt.yLabel) - opt.yLabel = 'counts'; - end -end - - - -% check colors/colormaps: do we need to expand colormap? -if ~iscell(opt.colormap) - opt.colormap = {opt.colormap}; -end -if ~iscell(opt.color) - opt.color = {opt.color}; -end -for iColor = 1:length(opt.color) - if ischar(opt.color{iColor}) - opt.color{iColor} = colorCode2rgb(opt.color{iColor}); - end -end - -% expand - if only single colormap specified, we expand only once -if ~opt.variableWidth - missingColormaps = find(cellfun(@isempty,opt.colormap)); - for iMissing = missingColormaps(:)' - - endColor = opt.color{max(iMissing,length(opt.color))}; - % normally, we go from white to color - cmap = zeros(128,3); - for rgb = 1:3 - cmap(:,rgb) = linspace(1,endColor(rgb),128); - end - opt.colormap{iMissing} = cmap; - - end -end - -% if we have colormaps, we need to create a master which we add to the -% figure. Invert if necessary, and expand the cell array to nData -colormapLength = cellfun(@(x)size(x,1),opt.colormap); -if any(colormapLength>0) - - colormap = cat(1,opt.colormap{:}); - if opt.invert - colormap = 1-colormap; - end - set(fh,'Colormap',colormap) - if length(opt.colormap) == 1 - opt.colormap = repmat(opt.colormap,nData,1); - colormapLength = repmat(colormapLength,nData,1); - colormapOffset = zeros(nData,1); - singleMap = true; - else - colormapOffset = [0;cumsum(colormapLength(1:end-1))]; - singleMap = false; - end - -else - - colormapLength = zeros(nData,1); - if length(opt.color) == 1 - opt.color = repmat(opt.color,nData,1); - end - if opt.invert - opt.color = cellfun(@(x)1-x,opt.color,'uniformOutput',false); - end -end - - -% set hold on -holdState = get(ah,'NextPlot'); -set(ah,'NextPlot','add'); - -% if new axes: invert -if newAx && opt.invert - set(ah,'Color','k') -end - -%=================================== - - - -%=================================== -%% PLOT DISTRIBUTIONS -%=================================== - -% assign output -hh = NaN(nData,1); -[m,md,sem,sd] = deal(nan(nData,1)); -if opt.showMM == 6 - md = nan(nData,3,3); % md/q1/q3, third dim is y/xmin/xmax -end - -% get base x-array -% widthDiv is a 1-by-2 array with -% #ofDivs, whichDiv -% The full width (distWidth) is split into -% #ofDivs; whichDiv says which "stripe" is active -xWidth = opt.distWidth/opt.widthDiv(1); -xMin = -opt.distWidth/2; -xLow = xMin + xWidth * (opt.widthDiv(2)-1); -xBase = [-xWidth;xWidth;xWidth;-xWidth]/2; -xOffset = xLow + xWidth/2; - -% b/c of global norm: loop twice -plotData = cell(nData,2); - -% loop through data. Prepare patch input, then draw patch into gca -for iData = 1:nData - currentData = data{iData}; - % only plot if there is some finite data - if ~isempty(currentData(:)) && any(isfinite(currentData(:))) - - switch floor(opt.histOpt) - case 0 - % use hist - [xHist,yHist] = hist(currentData,opt.divFactor); - - case 1 - % use ksdensity - - if opt.histOpt == 1.1 - % use histogram to estimate kernel - [dummy,x] = histogram(currentData); %#ok - if length(x) == 1 - % only one value. Make fixed distribution - dx = 0.1; - yHist = x; - xHist = sum(isfinite(currentData)); - else - dx = x(2) - x(1); - - % make sure we sample frequently enough - x = min(x)-dx:dx/3:max(x)+dx; - [xHist,yHist] = ksdensity(currentData,x,'kernel','normal','width',dx/(1.5*opt.divFactor)); - end - else - - % x,y are switched relative to normal histogram - [xHist,yHist,u] = ksdensity(currentData,'kernel','normal'); - % take smaller kernel to avoid over-smoothing - if opt.divFactor ~= 1 - [xHist,yHist] = ksdensity(currentData,'kernel','normal','width',u/opt.divFactor); - end - end - - % modify histogram such that the sum of bins (not the - % integral under the curve!) equals the total number of - % observations, in order to be comparable to hist - xHist = xHist/sum(xHist)*sum(isfinite(currentData)); - - case 2 - % use histogram - bar heights are counts as in hist - [xHist,yHist] = histogram(currentData,opt.divFactor,0); - case 99 - % bins,counts already supplied - xHist = currentData(:,2)'; - yHist = currentData(:,1)'; - end - plotData{iData,1} = xHist; - plotData{iData,2} = yHist; - end -end - -goodData = find(~cellfun(@isempty,plotData(:,1))); -% get norm -switch opt.globalNorm - case 3 - % #3 normalizes relative densities - xNorm(goodData) = cellfun(@(x)min(diff(x)),plotData(goodData,2)); - xNorm(goodData) = xNorm(goodData) .* cellfun(@sum,plotData(goodData,1))'; - maxNorm(goodData) = cellfun(@max,plotData(goodData,1)); - xNorm(goodData) = xNorm(goodData)*max(maxNorm(goodData)./xNorm(goodData)); - - case 2 - % #2 should normalize so that the integral of the - % different histograms (i.e. area covered) scale with the - % respective sum of counts across all bins. Requires evenly spaced - % histograms at the moment - xNorm(goodData) = cellfun(@(x)min(diff(x)),plotData(goodData,2)); - maxNorm(goodData) = cellfun(@max,plotData(goodData,1)); - xNorm(goodData) = xNorm(goodData)*max(maxNorm(goodData)./xNorm(goodData)); - case 1 - xNorm(goodData) = max(cat(2,plotData{:,1})); - case 0 - xNorm(goodData) = cellfun(@max,plotData(goodData,1)); -end - - -for iData = goodData' - - % find current data again - currentData = data{iData}; - - xHist = plotData{iData,1}; - yHist = plotData{iData,2}; - - % find y-step - dy = min(diff(yHist)); - if isempty(dy) - dy = 0.1; - end - - % create x,y arrays - nPoints = length(xHist); - xArray = repmat(xBase,1,nPoints); - yArray = repmat([-0.5;-0.5;0.5;0.5],1,nPoints); - - - % x is iData +/- almost 0.5, multiplied with the height of the - % histogram - if opt.variableWidth - - - tmp = xArray.*repmat(xHist,4,1)./xNorm(iData); - - switch opt.histOri - case 'center' - % we can simply use xArray - xArray = tmp; - case 'right' - % shift everything to the left - delta = tmp(1,:) - xArray(1,:); - xArray = bsxfun(@minus,tmp,delta); - case 'left' - % shift everything to the right - delta = tmp(1,:) - xArray(1,:); - xArray = bsxfun(@plus,tmp,delta); - end - - xArray = xArray + opt.xValues(iData); - - else - xArray = xArray + iData; - end - - % add offset (in case we have multiple widthDiv) - xArray = xArray + xOffset; - - - % yData is simply the bin locations - yArray = repmat(yHist,4,1) + dy*yArray; - - % add patch - vertices = [xArray(:),yArray(:)]; - faces = reshape(1:numel(yArray),4,[])'; - - if colormapLength(iData) == 0 - colorOpt = {'FaceColor',opt.color{iData}}; - else - % calculate index into colormap - if singleMap - % use scaled mapping so that colorbar is meaningful - if opt.globalNorm > 0 - colorOpt = {'FaceVertexCData',xHist','CDataMapping','scaled','FaceColor','flat'}; - else - colorOpt = {'FaceVertexCData',xHist'/xNorm(iData),'CDataMapping','scaled','FaceColor','flat'}; - end - - else - idx = round((xHist/xNorm(iData))*(colormapLength(iData)-1))+1; - colorOpt = {'FaceVertexCData',idx'+colormapOffset(iData),'CDataMapping','direct','FaceColor','flat'}; - end - end - - - switch opt.xyOri - case 'normal' - hh(iData)= patch('Vertices',vertices,'Faces',faces,'Parent',ah,colorOpt{:},'EdgeColor','none'); - case 'flipped' - hh(iData)= patch('Vertices',vertices(:,[2,1]),'Faces',faces,'Parent',ah,colorOpt{:},'EdgeColor','none'); - end - - if opt.showMM > 0 - if isHistogram - [m(iData),sem(iData)] = weightedStats(currentData(:,1),currentData(:,2),'w'); - sd(iData) = sem(iData) * sqrt(sum(currentData(:,2))); - % weighted median: where we're at middle weight - % may need some tweaking - goodCurrentData = sortrows(currentData(all(isfinite(currentData),2),:),1); - weightList = cumsum(goodCurrentData(:,2)); - weightList = weightList / weightList(end); - md(iData) = goodCurrentData(find(weightList>0.5,1,'first'),1); - else - m(iData) = nanmean(currentData); - md(iData) = nanmedian(currentData); - sd(iData) = nanstd(currentData); - sem(iData) = sd(iData)/sqrt(sum(isfinite(currentData))); - end - - if opt.showMM == 6 - % read quantiles - "y"-value, plus x-start-stop - % re-use md array which allows using a loop below instead of - % lots of copy-paste - % md array is md/q1/q3, with third dimension y/xmin/xmax - - md(iData,2,1) = prctile(currentData,25); - md(iData,3,1) = prctile(currentData,75); - - for qq = 1:3 - % find corresponding y-bin - yLoc = repmat(... - any(yArray>md(iData,qq,1),1) & any(yArray<=md(iData,qq,1),1),... - [4 1]); - % look up corresponding x-values. Note that there is a bit - % of a risk that the line will be exactly between two very - % different bins - but if we make the line longer, it will - % be ugly almost all the time - md(iData,qq,2) = min( xArray( yLoc ) ); - md(iData,qq,3) = max( xArray( yLoc ) ); - end - - end - end -end % loop - -sh = []; -if opt.addSpread - if isHistogram - disp('Option addSpread is unavailable if data is supplied as histograms. Call plotSpread separately') - else - % add spread - try - sh = plotSpread(ah,data,'xValues',opt.xValues,'xyOri',opt.xyOri); - set(sh{1},'color',[0,128,255]/255); - catch me - if strcmp(me.identifier,'MATLAB:UndefinedFunction') - error('plotSpread not found. Please download it from the Matlab File Exchange') - else - rethrow(me) - end - end - end -end - -mh = [];mdh=[]; -if opt.showMM - % plot mean, median. Mean is filled red circle, median is green square - % I don't know of a very clever way to flip xy and keep everything - % readable, thus it'll be copy-paste - switch opt.xyOri - case 'normal' - if any(opt.showMM==[1,2]) - mh = plot(ah,opt.xValues+xOffset,m,'+r','Color','r','MarkerSize',12); - end - if any(opt.showMM==[1,3]) - mdh = plot(ah,opt.xValues+xOffset,md,'sg','MarkerSize',12); - end - if opt.showMM == 4 - mh = plot(ah,opt.xValues+xOffset,m,'+r','Color','r','MarkerSize',12); - mdh = myErrorbar(ah,opt.xValues+xOffset,m,sem); - end - if opt.showMM == 5 - mh = plot(ah,opt.xValues+xOffset,m,'+r','Color','r','MarkerSize',12); - mdh = myErrorbar(ah,opt.xValues+xOffset,m,sd); - end - if opt.showMM == 6 - mdh(1,:) = plot(ah,squeeze(md(:,1,2:3))',repmat(md(:,1,1)',2,1),'color','r','lineWidth',2);%,'lineStyle','--'); - mdh(2,:) = plot(ah,squeeze(md(:,2,2:3))',repmat(md(:,2,1)',2,1),'color','r','lineWidth',1);%,'lineStyle','--'); - mdh(3,:) = plot(ah,squeeze(md(:,3,2:3))',repmat(md(:,3,1)',2,1),'color','r','lineWidth',1);%,'lineStyle','--'); - end - case 'flipped' - if any(opt.showMM==[1,2]) - mh = plot(ah,m,opt.xValues+xOffset,'+r','Color','r','MarkerSize',12); - end - if any(opt.showMM==[1,3]) - mdh = plot(ah,md,opt.xValues+xOffset,'sg','MarkerSize',12); - end - if opt.showMM == 4 - mh = plot(ah,m,opt.xValues+xOffset,'+r','Color','r','MarkerSize',12); - mdh = myErrorbar(ah,m,opt.xValues+xOffset,[sem,NaN(size(sem))]); - end - if opt.showMM == 5 - mh = plot(ah,m,opt.xValues+xOffset,'+r','Color','r','MarkerSize',12); - mdh = myErrorbar(ah,m,opt.xValues+xOffset,[sd,NaN(size(sd))]); - end - if opt.showMM == 6 - mdh(1,:) = plot(ah,repmat(md(:,1,1)',2,1),squeeze(md(:,1,2:3))','color','r','lineWidth',2);%,'lineStyle','--'); - mdh(2,:) = plot(ah,repmat(md(:,2,1)',2,1),squeeze(md(:,2,2:3))','color','r','lineWidth',1);%,'lineStyle','--'); - mdh(3,:) = plot(ah,repmat(md(:,3,1)',2,1),squeeze(md(:,3,2:3))','color','r','lineWidth',1);%,'lineStyle','--'); - end - end -end - -% find extents of x-axis (or y-axis, if flipped) -minX = min(opt.xValues)-stdWidth; -maxX = max(opt.xValues)+stdWidth; - -if ~isnan(xAxLim(1)) - % we have previous limits - switch opt.xyOri - case 'normal' - minX = min(minX,xAxLim(1)); - maxX = max(maxX,xAxLim(2)); - case 'flipped' - minX = min(minX,yAxLim(1)); - maxX = max(maxX,yAxLim(2)); - end -end - - -% if ~empty, use xNames -switch opt.xyOri - case 'normal' - switch opt.xMode - case 'manual' - if newAx == false - warning('DISTRIBUTIONPLOT:ERASINGLABELS','Plotting into an existing axes and specifying labels will erase previous labels') - end - set(ah,'XTick',opt.xValues); - if ~isempty(opt.xNames) - set(ah,'XTickLabel',opt.xNames) - end - case 'auto' - % no need to do anything - end - if ~isempty(opt.yLabel) - ylabel(ah,opt.yLabel); - end - % have plot start/end properly - xlim(ah,[minX,maxX]) - case 'flipped' - switch opt.xMode - case 'manual' - if newAx == false - warning('DISTRIBUTIONPLOT:ERASINGLABELS','Plotting into an existing axes and specifying labels will erase previous labels') - end - set(ah,'YTick',opt.xValues); - if ~isempty(opt.xNames) - set(ah,'YTickLabel',opt.xNames) - end - case 'auto' - % no need to do anything - end - if ~isempty(opt.yLabel) - xlabel(ah,opt.yLabel); - end - % have plot start/end properly - ylim(ah,[minX,maxX]) -end - - -%========================== - - -%========================== -%% CLEANUP & ASSIGN OUTPUT -%========================== - -if nargout > 0 - handles{1} = hh; - handles{2} = [mh;mdh]; - handles{3} = ah; - handles{4} = sh; -end - -set(ah,'NextPlot',holdState); \ No newline at end of file diff --git a/Plotting/plot_slice.m b/Plotting/plot_slice.m deleted file mode 100755 index cb4f2c8..0000000 --- a/Plotting/plot_slice.m +++ /dev/null @@ -1,88 +0,0 @@ -%% This function plots the CAPs obtained for a given case -% Inputs: -% - Cp: a matrix of size n_clusters x n_voxels with the CAPs (or patterns) -% to plot -% - T: the threshold below which voxels will not be colored -% - maxC: the maximal value at which the color display will saturate -% - mask: a very long vector of logicals symbolizing the regions of the -% brain that are actually to be considered (in-brain voxels typically) -% - brain_final: a 3D matrix used to plot the greyscale brain template on which -% to overlay activity patterns -% - ai: the nii data related to the considered seed, including information -% on the scale differences between Cp indexes ('distance between voxels of -% the matrix') and actual MNI space -% - Dimension: the type of slice to plot ('X', 'Y' or 'Z') -% - MNI: the MNI coordinate of the slice to plot -% - Handle: the handle of the graph to update -function [Handle] = plot_slice(Cp,T,maxC,mask,brain_final,ai,Dimension,MNI,Handle) - - % Computes the matrix index matching the MNI coordinates of interest. - Map = inv(ai.mat); - - switch Dimension - case 'X' - ctr = round(Map(1,1)*MNI+Map(1,4)); - case 'Y' - ctr = round(Map(2,2)*MNI+Map(2,4)); - case 'Z' - ctr = round(Map(3,3)*MNI+Map(3,4)); - end - - % temp contains the volume values (within mask), and is a 3D volume after - % those lines - temp = nan(size(mask)); - temp(mask) = Cp; - temp(isnan(temp)) = 0; - temp = reshape(temp,ai.dim); - - % ho contains the structural underlay slice to plot at right slice, - % while tmpp contains the values to plot on top - switch Dimension - case {'X'} - tmpp = squeeze(temp(ctr,:,:)); - ho = squeeze(brain_final(ctr,:,:)); - case {'Y'} - tmpp = squeeze(temp(:,ctr,:)); - ho = squeeze(brain_final(:,ctr,:)); - case {'Z'} - tmpp = squeeze(temp(:,:,ctr)); - ho = squeeze(brain_final(:,:,ctr)); - end - - % I is an image with values from 0 to 1 (because the original - % image had no negative value) - I = double(ho)'/max(double(ho(:))); - I(I==0) = 1; - - % Creates an 'image with three values per pixel' - Irgb = cat(3,I,I,I); - - % Actual plotting - imagesc(Irgb,'Parent',Handle); - hold(Handle,'on'); - - % Plots the slice of interest on top of the brain template - h=imagesc(tmpp','Parent',Handle); - set(Handle,'YDir','normal'); - - % At this stage, ddd contains a set of colors, with white if the values - % are too low. We ask the axes of interest to be using this colormap - % colormap(Handle,ddd); - tmp_cm = cbrewer('div','RdBu',1000); - colormap(Handle,flipud(tmp_cm)); - - % Defines that the topmost and bottommost elements of the - % colormap will map maxC and -maxC respectively - caxis(Handle,[-1 1]*maxC); - - % Opacity: sets data points below the value of interest as - % transparent (they are white, but transparent); note that we do this - % specifically for the h imagesc (the one to plot on top) - A = ones(size(tmpp)); - A(abs(tmpp)0.7)=Inf; -[a,b]=munkres(A); -%} -% Example 4: an example of partial assignment -%{ -A = [1 3 Inf; Inf Inf 5; Inf Inf 0.5]; -[a,b]=munkres(A) -%} -% a = [1 0 3] -% b = 1.5 -% Reference: -% "Munkres' Assignment Algorithm, Modified for Rectangular Matrices", -% http://csclab.murraystate.edu/bob.pilgrim/445/munkres.html - -% version 2.3 by Yi Cao at Cranfield University on 11th September 2011 - -assignment = zeros(1,size(costMat,1)); -cost = 0; - -validMat = costMat == costMat & costMat < Inf; -bigM = 10^(ceil(log10(sum(costMat(validMat))))+1); -costMat(~validMat) = bigM; - -% costMat(costMat~=costMat)=Inf; -% validMat = costMat0) - break - end - coverColumn = false(1,n); - coverColumn(starZ(starZ>0))=true; - coverRow = false(n,1); - primeZ = zeros(n,1); - [rIdx, cIdx] = find(dMat(~coverRow,~coverColumn)==bsxfun(@plus,minR(~coverRow),minC(~coverColumn))); - while 1 - %************************************************************************** - % STEP 4: Find a noncovered zero and prime it. If there is no starred - % zero in the row containing this primed zero, Go to Step 5. - % Otherwise, cover this row and uncover the column containing - % the starred zero. Continue in this manner until there are no - % uncovered zeros left. Save the smallest uncovered value and - % Go to Step 6. - %************************************************************************** - cR = find(~coverRow); - cC = find(~coverColumn); - rIdx = cR(rIdx); - cIdx = cC(cIdx); - Step = 6; - while ~isempty(cIdx) - uZr = rIdx(1); - uZc = cIdx(1); - primeZ(uZr) = uZc; - stz = starZ(uZr); - if ~stz - Step = 5; - break; - end - coverRow(uZr) = true; - coverColumn(stz) = false; - z = rIdx==uZr; - rIdx(z) = []; - cIdx(z) = []; - cR = find(~coverRow); - z = dMat(~coverRow,stz) == minR(~coverRow) + minC(stz); - rIdx = [rIdx(:);cR(z)]; - cIdx = [cIdx(:);stz(ones(sum(z),1))]; - end - if Step == 6 - % ************************************************************************* - % STEP 6: Add the minimum uncovered value to every element of each covered - % row, and subtract it from every element of each uncovered column. - % Return to Step 4 without altering any stars, primes, or covered lines. - %************************************************************************** - [minval,rIdx,cIdx]=outerplus(dMat(~coverRow,~coverColumn),minR(~coverRow),minC(~coverColumn)); - minC(~coverColumn) = minC(~coverColumn) + minval; - minR(coverRow) = minR(coverRow) - minval; - else - break - end - end - %************************************************************************** - % STEP 5: - % Construct a series of alternating primed and starred zeros as - % follows: - % Let Z0 represent the uncovered primed zero found in Step 4. - % Let Z1 denote the starred zero in the column of Z0 (if any). - % Let Z2 denote the primed zero in the row of Z1 (there will always - % be one). Continue until the series terminates at a primed zero - % that has no starred zero in its column. Unstar each starred - % zero of the series, star each primed zero of the series, erase - % all primes and uncover every line in the matrix. Return to Step 3. - %************************************************************************** - rowZ1 = find(starZ==uZc); - starZ(uZr)=uZc; - while rowZ1>0 - starZ(rowZ1)=0; - uZc = primeZ(rowZ1); - uZr = rowZ1; - rowZ1 = find(starZ==uZc); - starZ(uZr)=uZc; - end -end - -% Cost of assignment -rowIdx = find(validRow); -colIdx = find(validCol); -starZ = starZ(1:nRows); -vIdx = starZ <= nCols; -assignment(rowIdx(vIdx)) = colIdx(starZ(vIdx)); -pass = assignment(assignment>0); -pass(~diag(validMat(assignment>0,pass))) = 0; -assignment(assignment>0) = pass; -cost = trace(costMat(assignment>0,assignment(assignment>0))); - -function [minval,rIdx,cIdx]=outerplus(M,x,y) -ny=size(M,2); -minval=inf; -for c=1:ny - M(:,c)=M(:,c)-(x+y(c)); - minval = min(minval,min(M(:,c))); -end -[rIdx,cIdx]=find(M==minval);