Spherical searchlight
this example implements a spherical searchlight using cosmo_spherical_neighborhood and performs crossvalidation with a nearest neigh classifier
Note: for running searchlights it is recommended to use cosmo_searchlight and cosmo_spherical_neighborhood
- For CoSMoMVPA's copyright information and license terms, #
- see the COPYING file distributed with CoSMoMVPA. #
Contents
Set up parameters
config=cosmo_config(); data_path=fullfile(config.tutorial_data_path,'ak6','s01'); output_path=fullfile(config.output_data_path); fn=fullfile(data_path,'glm_T_stats_perrun.nii'); maskfn=fullfile(data_path,'brain_mask.nii'); radius=3; targets=repmat(1:6,1,10); chunks=floor(((1:60)-1)/6)+1; classifier=@cosmo_classify_nn; classifier_opt=struct();
load data and set sample attributes
ds=cosmo_fmri_dataset(fn, 'mask', maskfn, ... 'targets', targets, ... 'chunks', chunks); fprintf('Input dataset:\n'); cosmo_disp(ds);
Input dataset: .a .vol .mat [ -3 0 0 121 0 3 0 -114 0 0 3 -11.1 0 0 0 1 ] .xform 'scanner_anat' .dim [ 80 80 43 ] .fdim .labels { 'i' 'j' 'k' } .values { [ 1 2 3 ... 78 79 80 ]@1x80 [ 1 2 3 ... 78 79 80 ]@1x80 [ 1 2 3 ... 41 42 43 ]@1x43 } .sa .targets [ 1 2 3 : 4 5 6 ]@60x1 .chunks [ 1 1 1 : 10 10 10 ]@60x1 .samples [ 0.933 0.000495 2.1 ... 0.681 0.626 0.421 -0.772 0.117 1.73 ... 0.723 0.892 1.7 0.621 1.52 -0.25 ... -0.341 -0.832 -0.546 : : : : : : -2.37 -1.92 -0.879 ... 0.784 0.67 0.522 -0.261 0.351 -0.0767 ... 2.81 2.27 -0.947 -1.29 -0.964 -0.966 ... 0.827 0.833 0.991 ]@60x43822 .fa .i [ 35 36 44 ... 46 47 47 ]@1x43822 .j [ 17 17 17 ... 35 35 36 ]@1x43822 .k [ 1 1 1 ... 39 39 39 ]@1x43822
define centers of searchlight
nfeatures=size(ds.samples,2); center_ids=1:nfeatures;
use voxel selection function
nbrhood=cosmo_spherical_neighborhood(ds, 'radius',radius); center2neighbors=nbrhood.neighbors; ncenters=numel(center2neighbors); % should be equal to 'nfeatures'
+00:00:02 [####################] -00:00:00 mean size 111.5
set up cross validation
(here we use cosmo_oddeven_partitioner; cosmo_nfold_partitioner would be another possiblity, with the advantage of using a larger training set, but the disadvantage that it takes longer to run)
partitions=cosmo_oddeven_partitioner(ds.sa.chunks);
Allocate space for output
ncenters=numel(center_ids); accs=zeros(1,ncenters);
Run the searchlight
go over all features: in each iteration, slice the dataset to get the desired features using center2neighbors, then use cosmo_crossvalidate to get classification accuracies (it's its second output argument), and store the classiifcation accuracies.
Note: it is generally easier (and faster) to use cosmo_searchlight and cosmo_crossvalidation_measure; this example here is for illustrative purposes mainly
% use cosmo_show_progress to show a pretty progress bar prev_msg=''; clock_start=clock(); show_progress_every=1000; for k=1:ncenters % >@@> center_id=center_ids(k); sphere_feature_ids=center2neighbors{center_id}; sphere_ds=cosmo_slice(ds, sphere_feature_ids, 2); % run cross validation [pred_cv,acc]=cosmo_crossvalidate(sphere_ds, classifier, ... partitions, classifier_opt); % for now, just store the accuracy (not the predictions) accs(center_id)=acc; % <@@< % show progress every 1000 steps, and at the beginning and end. if k==1 || mod(k,show_progress_every)==0 || k==nfeatures mean_so_far=mean(accs(1:k)); msg=sprintf('accuracy %.3f (%d features visited)', mean_so_far, k); prev_msg=cosmo_show_progress(clock_start,k/ncenters,msg,prev_msg); end end
+00:03:27 [####################] -00:00:00 accuracy 0.202 (43822 features visited)
store the output
this uses the neighborhood from spherical voxel selection, after removing the fields neighbors and origin
res_map=nbrhood; res_map=rmfield(res_map,{'neighbors','origin'}); res_map.samples=accs; % little sanity check cosmo_check_dataset(ds); fprintf('Output dataset:\n'); cosmo_disp(res_map); output_fn=fullfile(output_path, 'spherical_neighborhood_searchlight.nii'); cosmo_map2fmri(res_map, output_fn); fprintf('Output written to %s\n', output_fn);
Output dataset: .a .vol .mat [ -3 0 0 121 0 3 0 -114 0 0 3 -11.1 0 0 0 1 ] .xform 'scanner_anat' .dim [ 80 80 43 ] .fdim .labels { 'i' 'j' 'k' } .values { [ 1 2 3 ... 78 79 80 ]@1x80 [ 1 2 3 ... 78 79 80 ]@1x80 [ 1 2 3 ... 41 42 43 ]@1x43 } .fa .nvoxels [ 42 46 45 ... 41 41 38 ]@1x43822 .radius [ 3 3 3 ... 3 3 3 ]@1x43822 .center_ids [ 1 2 3 ... 4.38e+04 4.38e+04 4.38e+04 ]@1x43822 .i [ 35 36 44 ... 46 47 47 ]@1x43822 .j [ 17 17 17 ... 35 35 36 ]@1x43822 .k [ 1 1 1 ... 39 39 39 ]@1x43822 .samples [ 0.2 0.0833 0.35 ... 0.267 0.183 0.117 ]@1x43822 Output written to /Users/nick/outputs/spherical_neighborhood_searchlight.nii
Plot a few slices
cosmo_plot_slices(res_map);