attachment:cbu_meeg_spm5_pipeline_13_4_09.m of SpmDemo - Meg Wiki
location: attachment:cbu_meeg_spm5_pipeline_13_4_09.m of SpmDemo

Attachment 'cbu_meeg_spm5_pipeline_13_4_09.m'

Download

   1 % Batch script (linear pipeline) for MEG analysis in SPM5   
   2 % Rik Henson MRC CBU Sep 08
   3 %
   4 % Note that would benefit from modularisation (eg for stop/start
   5 % running), but wanted all steps in one file to ease exposition
   6 %
   7 % First start SPM with (at the CBU) "spm 5 eeg" from Linux prompt
   8 
   9 clear
  10 
  11 wd = '/imaging/rh01/Methods/CBUMEGDemo/Group';   % !!!REPLACE WITH YOUR DIRECTORY!!!
  12 cd(wd)
  13 
  14 %addpath /imaging/local/spm/spm5/cbu_updates/    
  15 addpath /imaging/rh01/dev_trees/spm5_cbu_updates/    
  16 % Or update direct from SVN http://imaging.mrc-cbu.cam.ac.uk/svn/spm5_cbu_updates/devel/
  17 addpath /imaging/local/meg_misc/    
  18 % Or update direct from SVN http://imaging.mrc-cbu.cam.ac.uk/svn/meg_misc/devel/
  19 
  20 %%%%%%%%%% Different types of sensor
  21 sennam{1}   = 'mags'; sennam{2} = 'grds'; sennam{3} = 'eeg';
  22 Nsen     = length(sennam);
  23 eegflag  = [0 0 1];         % Binary flag for which sensor is EEG
  24 
  25 % Num channels per sensor type (if differs across subjects, can re-specify below)
  26 Nchan(1) = 102;    Nchan(2) = 204;   Nchan(3) = 70;
  27 
  28 % Any user-thresholds for rejection for each of above (Inf=none)
  29 thr(1)   = Inf;    thr(2)   = Inf;   thr(3)   = 120;
  30 EOGthr   = 120;   % EOG threshold (EOG is duplicated in each file)
  31 
  32 %%%%%%%%%% Experiment-specific parameters
  33 expwin      = [-100 400];                    % Epoch window (in ms)
  34 expcodes    = [1:8];                         % Codes in FIF file to extract
  35 offset      = [ones(1,length(expcodes))*34]; % t=0 offset (eg visual delay)
  36 newcodes    = [1 1 1 1 2 2 2 2];             % Any new (recoding) of above
  37 expcons     = [1 0; 0 1; 1 -1; 1/2 1/2];     % Contrasts (on NEW codes)
  38 Ncons       = size(expcons,1); 
  39 		 
  40 %%%%%%%%%% Raw FIF files on network 
  41 % (cell of cells for each session of each sub (only one session here))
  42 % Eg if instead two sessions per subject:
  43 %    Fifdata = { { '/megdata/cbu/lfp/meg08_0014/080117/block1_raw.fif';
  44 %                  '/megdata/cbu/lfp/meg08_0014/080117/block2_raw.fif'} };
  45 fifdata = {
  46            {'/megdata/cbu/lfp/meg08_0014/080117/block4_raw.fif'};
  47            {'/megdata/cbu/lfp/meg08_0015/080118/block4_raw.fif'};
  48            {'/megdata/cbu/lfp/meg08_0016/080118/block4_raw.fif'};
  49            {'/megdata/cbu/lfp/meg08_0038/080131/block4_raw.fif'};
  50            {'/megdata/cbu/lfp/meg08_0064/080212/block4_raw.fif'};
  51            {'/megdata/cbu/lfp/meg08_0111/080303/block4_raw.fif'};
  52            {'/megdata/cbu/lfp/meg08_0112/080303/block4_raw.fif'};
  53            {'/megdata/cbu/lfp/meg08_0113/080303/block4_raw.fif'};
  54            {'/megdata/cbu/lfp/meg08_0127/080310/block4_raw.fif'};
  55 	     }
  56 
  57 
  58 %%%%%%%%%% Raw DICOM files on network (one per subject)
  59 mridata = {
  60            '/mridata/cbu/CBU080769_CBU080769/20080916_095501/Series_002_CBU_MPRAGE';
  61            '/mridata/cbu/CBU071255_CBU071255/20071218_150851/Series_002_CBU_MPRAGE';
  62            '/mridata/cbu/CBU071151_CBU071151/20071116_140044/Series_002_CBU_MPRAGE';
  63            '/mridata/cbu/CBU071229_CBU071229/20071211_112249/Series_002_CBU_MPRAGE';
  64            '/mridata/cbu/CBU080034_RIS13667/20080111_102845/Series_002_CBU_MPRAGE';
  65            '/mridata/cbu/CBU080292_CBU080292/20080418_161843/Series_002_CBU_MPRAGE';
  66            '/mridata/cbu/CBU080358_CBU080358/20080506_151233/Series_003_CBU_MPRAGE';
  67            '/mridata/cbu/CBU080413_CBU080413/20080522_124313/Series_002_CBU_MPRAGE';
  68            '/mridata/cbu/CBU080802_CBU080802/20080930_090538/Series_002_CBU_MPRAGE';
  69 	  };
  70 
  71 
  72 %%%%%%%%%% Bad channel names noticed by Operator or post hoc (eeg/meg,sub,ses)
  73 badchans{1,1,1} = [1143];
  74 badchans{1,2,1} = [1143 0913 1013 0313 0933 2222 0642 1232 1913];
  75 badchans{1,3,1} = [1143];
  76 badchans{1,4,1} = [1143 2223 0432];
  77 badchans{1,5,1} = [1143];
  78 badchans{1,6,1} = [1143];
  79 badchans{1,7,1} = [1143 2223];
  80 badchans{1,8,1} = [1143 1412];
  81 badchans{1,9,1} = [1143 2223];
  82 
  83 %%%%%%%%%% Bad EEG channels noticed by Operator or post hoc (in terms of NAME)
  84 badchans{2,1,1} = [48 50 73];                 % Poor contact
  85 badchans{2,2,1} = [7 13 16 24 46 48 57];      % Drifting
  86 badchans{2,3,1} = [48];                       % Drifting
  87 badchans{2,4,1} = [48];                       % Drifting
  88 badchans{2,5,1} = [15 40 49];                 % Poor contact
  89 badchans{2,6,1} = [48];                       % Drifting
  90 badchans{2,7,1} = [48 72];                    % No deflection (odd N170 topo)?
  91 badchans{2,8,1} = [65 48];                    % odd in final topo of N170?
  92 badchans{2,9,1} = [20 31 45];                 % 45 poor contact; 20+31 highfreq noise
  93 
  94 % (Just happens that any EEG Channels 61 onwards are numbered 65 onwards in our lab!)
  95 for sub=1:size(badchans,2)
  96   for ses=1:size(badchans,3)
  97    f = find(badchans{2,sub,ses}>60);
  98    badchans{2,sub,ses}(f) = badchans{2,sub,ses}(f)-4;
  99   end
 100 end
 101 
 102 %%%%%%%%%%% subject-specific parameters
 103 %dosubs   = [1:9];      % Subjects to run, eg for subset: dosubs = [5:8]; 
 104 dosubs   = [1:8];       % Exclude sub9 because MRI segmentation requires manual re-
 105                         % positioning first (can try yourself; see MRI section below!)
 106                         % (in fact for many, eg sub5 too, normalisation is much
 107                         % better after manual repositioning)
 108 Nsub     = length(dosubs);
 109 
 110 % Below assumes that two EOG channels (VEOG and HEOG), which will be
 111 % appended at end of every data-file. Note that this script does not yet
 112 % handle concurrent ECG (see Jason Taylor for how to do this)
 113 for s = 1:Nsub
 114  subnum = dosubs(s);
 115  for m = 1:Nsen;
 116    Nsubchan(s,m) = Nchan(m);  % In case different number of channels (eg EEG) for some subjects
 117   chan_thr{s,m} = [ones(1,Nsubchan(s,m))*thr(m) EOGthr EOGthr]; 
 118  end
 119 end
 120 
 121 VitECapsules = ones(1,max(dosubs));  % Whether MRIs have Vitamin E capsule (all here)
 122 
 123 %%%%%%%%%%% control flags (1=do step; 0=omit step)
 124 %maxfiltflag = 1; maxmvcompflag = 1; maxtransflag = 1; 
 125 maxfiltflag = 0; maxmvcompflag = 1; maxtransflag = 1; 
 126 usemaxmvcompflag = 0; usemaxtransflag = 1; 
 127 chancheckflag = 0; respmflag = 0; reprocessflag = 0; 
 128 %getmriflag = 1;
 129 getmriflag = 0;
 130 write2Dflag = [1 0 1]; write3Dflag = 1;
 131 fuseinvertflag = 1;        % Whether want to simultaneously invert (fuse) modalities (sennam)
 132                        % (Henson et al, submitted)
 133 grpinvertflag = 1;     % Whether invert using group priors (after individual inversions)
 134                        % (Litvak & Friston, 2008, Neuroimage)
 135 fmriinvertflag = 1;    % Whether want to use fMRI priors on inversion
 136                        % (Flandin et al, submitted)
 137 		       
 138 %%%%%%%%%% General parameters
 139 % Maxfilter
 140 downsample_maxf   = '-ds 4';           % maxfilter downsampling factor (eg 4 to save space)
 141                                        % though beware of effect of downsampling on triggers
 142 				       % (http://imaging.mrc-cbu.cam.ac.uk/meg/CbuSpmParameters)
 143 %downsample_maxf  = '';                % (if none)
 144 format_maxf       = '-format float';   % maxfilter data format (native = float32)
 145 %format_maxf      = '-format short';   % (if to save space)
 146 trans_offset_maxf = [0 -13 +6];        % New centre for trans default
 147                                        % (see our maxfilter WIKI)
 148 
 149 % SPM
 150 downsample_spm    = 100;                % spm new sample rate (Hz; should be at
 151                                         % least twice filt_cut_spm below)
 152 filt_cut_spm      = 40;                 % Lowpass filter cutoff for SPM (Hz)
 153 dformat_spm       = 'int16';            % data format for spm (eg to save space)
 154 sensor_smooth_spm = [5 5 10];           % Smoothing in SensorSpace-Time [mm mm ms];
 155 source_smooth_spm = [10 10 10];         % Smoothing in Source space [mm mm mm]
 156 
 157 %%%%%%%%%%% Initialisation
 158 subsphere = [];
 159 allsssbad = cell(Nsub,1);
 160 nbadchan = cell(Nsen,Nsub);
 161 nrejects = cell(Nsen,Nsub);
 162 nevents  = cell(Nsen,Nsub);
 163 
 164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 165 %%%%%%%%%%% Preprocess MEG/EEG data
 166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 167 
 168 for sub = 1:Nsub
 169  
 170  subnum    = dosubs(sub);
 171  Nses(sub) = size(fifdata{subnum},1);
 172 
 173  cd(wd)
 174  swd = sprintf('sub%d',subnum);
 175  try cd(swd); catch eval(sprintf('!mkdir %s',swd)); cd(swd); end
 176   
 177  for ses = 1:Nses(sub)
 178 
 179    allsssbad{sub} = cell(1,Nses(sub));
 180    
 181    fnm_stem = sprintf('sub%d_ses%d',subnum,ses);
 182 
 183    if maxfiltflag
 184 
 185 %%%%% Use autobad to detect bad channels from first 20s, and select from output
 186      rawfile  = fifdata{subnum}{ses};
 187      sssfile  = sprintf('%s_sss.fif',fnm_stem)
 188      logfile  = sprintf('%s_autobad.log',fnm_stem)
 189      headptsfile  = sprintf('%s_headpoints.txt',fnm_stem)
 190 
 191      if exist(sssfile), delete(sssfile), end
 192      if exist(logfile), delete(logfile), end
 193      [Centre,Radius]  = meg_fit_sphere(rawfile,pwd,headptsfile);
 194      disp(sprintf('Subject %d (%d): Session %d: Sphere centre [%d %d %d] and radius %d mm',subnum,sub,ses,Centre(1),Centre(2),Centre(3),Radius))
 195      subsphere(sub,:) = [Centre Radius];
 196 
 197      disp('Checking first 20s for bad channels...')
 198      eval(sprintf('!/neuro/bin/util/maxfilter -f %s -o %s -ctc /neuro/databases/ctc/ct_sparse.fif -cal /neuro/databases/sss/sss_cal.dat -frame head -origin %d %d %d -autobad 20 -skip 21 9999999 -v | tee %s',rawfile,sssfile,Centre(1),Centre(2),Centre(3),logfile))
 199      
 200      badfile = sprintf('%s_badchan.txt',fnm_stem)
 201      if exist(badfile), delete(badfile), end
 202      eval(sprintf('!cat %s | sed -n ''/Static/p'' | cut -f 5- -d '' '' > %s',logfile,badfile));
 203      sssbadchans{sub}{ses} = unique([textread(badfile,'%d')' badchans{1,subnum,ses}]);
 204      for bc=1:length(sssbadchans{sub}{ses}); allsssbad{sub}{ses} = [allsssbad{sub}{ses} sprintf(' %04d',sssbadchans{sub}{ses}(bc))]; end
 205 
 206 %%%%% Now mark bad channels and run ST 
 207      logfile = sprintf('%s_ssst.log',fnm_stem)
 208      if exist(sssfile), delete(sssfile), end    % Don't need previous file from autobad
 209      sssfile  = sprintf('%s_ssst.fif',fnm_stem)
 210      if exist(logfile), delete(logfile), end
 211      posfile = sprintf('%s_mvpos.txt',fnm_stem)
 212 
 213      disp(['Now maxfiltering with bad channels (and tSSS): ' allsssbad{sub}{ses}])
 214      eval(sprintf('!/neuro/bin/util/maxfilter -f %s -o %s -ctc /neuro/databases/ctc/ct_sparse.fif -cal /neuro/databases/sss/sss_cal.dat -frame head -origin %d %d %d %s -autobad off -bad %s -st 4 -headpos -hpistep 1000 -hpisubt amp -hp %s %s -v | tee %s',rawfile,sssfile,Centre(1),Centre(2),Centre(3),format_maxf,allsssbad{sub}{ses},posfile,downsample_maxf,logfile))
 215 
 216      S.logfile = logfile;
 217      [max_d(sub),max_r(sub)] = meg_plot_maxfilter_move(S);
 218 % Do check the movement parameters - particularly goodness of fit -
 219 % because movement compensation below will be invalidated if poor fit
 220 % (also, the 'inter' MaxFilter option is used below in case the HPI 
 221 % temporarily fails (which it does for sub5), but if your subject's 
 222 % HPI failed  permanently from the start, you might not know this otherwise,
 223 % because 'inter' would handle it fine!).
 224      
 225      infile = sssfile;
 226      
 227 %%%%% Now mark bad channels and run MVCOMP
 228      if maxmvcompflag
 229 
 230       sss2file = sprintf('%s_mvcomp.fif',fnm_stem)
 231       logfile = sprintf('%s_mvcomp.log',fnm_stem)
 232       if exist(sss2file), delete(sss2file), end
 233       if exist(logfile), delete(logfile), end
 234 
 235       disp(['Now compensating movement... (every 1000ms)'])
 236       eval(sprintf('!/neuro/bin/util/maxfilter -f %s -o %s -ctc /neuro/databases/ctc/ct_sparse.fif -cal /neuro/databases/sss/sss_cal.dat -frame head -origin %d %d %d %s -autobad off -bad %s -st 4 -movecomp inter -hpistep 200 -hpisubt amp %s -v | tee %s',rawfile,sss2file,Centre(1),Centre(2),Centre(3),format_maxf,allsssbad{sub}{ses},downsample_maxf,logfile))
 237 %      eval(sprintf('!/neuro/bin/util/maxfilter -f %s -o %s -ctc /neuro/databases/ctc/ct_sparse.fif -cal /neuro/databases/sss/sss_cal.dat -frame head -origin %d %d %d %s -autobad off -bad %s -st 4 -movecomp -hpistep 1000 -hpisubt amp %s -v | tee %s',rawfile,sss2file,Centre(1),Centre(2),Centre(3),format_maxf,allsssbad{sub}{ses},downsample_maxf,logfile))
 238 
 239       infile = sss2file;
 240      end
 241      
 242 %%%%% Now Trans Default (if requested)
 243      if maxtransflag
 244       trans_origin = Centre(1:3) + trans_offset_maxf;
 245       logfile = sprintf('%s_trans.log',fnm_stem)
 246       sss3file = sprintf('%s_trans.fif',fnm_stem)
 247       if exist(sss3file), delete(sss3file), end
 248       if exist(logfile), delete(logfile), end
 249 
 250       disp(['Now trans-ing to DEFAULT ' num2str(round(trans_origin))])
 251       eval(sprintf('!/neuro/bin/util/maxfilter -f %s -o %s -ctc /neuro/databases/ctc/ct_sparse.fif -cal /neuro/databases/sss/sss_cal.dat -autobad off -trans default -frame head -origin %d %d %d %s -v -force | tee %s',infile,sss3file,trans_origin(1),trans_origin(2),trans_origin(3),format_maxf,logfile))
 252      end
 253     end
 254 
 255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 256 %%%%% Olaf's channel checking (have not used for a while; should put in SVN!)
 257     if chancheckflag 
 258      addpath /imaging/olaf/MEG/artefact_scan_tool/
 259      global fiffs tasks values criteria sensors datapara figs;
 260      ini_check4artefacts; % Initialisation of variables
 261      epochlength = 5;    
 262      amplitude_threshold_mag = 5000;  
 263      amplitude_threshold_gra = 10000;         
 264      out_dir = fullfile(wd,'ChanCheck');
 265      addfiff(infile,fnm_stem);
 266      addtask('maxminamp');   % maximum minus minimum amplitude within epoch
 267      addtask('maxmingrad');  % maximum signal gradient (amplitude difference between successive data points in time) with epoch
 268      addtask('threshold');   % number of epochs with max-min amplitudes above specified threshold
 269      addtask('crosscorr');   % intercorrelation matrix for magnetometers and gradiometers separately
 270      addtask('trendamp');    % linear trend in max-min differences across all epochs
 271      addtask('trendgrad');   % linear trend in maximum signal gradients across all epochs
 272      check4artefacts;    % That's where it all happens... lean back and enjoy!
 273     end
 274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 275 
 276 %%%%% Read into SPM (writes separate files for MEG and EEG)
 277 
 278     clear S
 279     if usemaxtransflag
 280       S.Fdata = sprintf('%s_trans.fif',fnm_stem);
 281       if maxmvcompflag
 282        S.HPIfile = sprintf('%s_mvcomp.fif',fnm_stem);   % If trans'ed (hpi lost)
 283       else
 284        S.HPIfile = sprintf('%s_sss.fif',fnm_stem);      % If trans'ed (hpi lost)
 285       end
 286     elseif usemaxmvcompflag
 287       S.Fdata = sprintf('%s_mvcomp.fif',fnm_stem);
 288       S.HPIfile = [];
 289     else
 290       S.Fdata = sprintf('%s_sss.fif',fnm_stem);      
 291       S.HPIfile = [];
 292     end
 293 %    meg_plot_fifpoints(S);                              % If want to check points
 294     S.Fchannels = 'FIF306_setup.mat';
 295     S.veogchan  = [62 63]; S.veog_unipolar = 0;
 296     S.heogchan  = [61 64]; S.heog_unipolar = 0;
 297     S.trig_chan = 'STI101';
 298     S.twin      = [0 Inf];
 299     S.eeg_ref   = 'average';
 300     S.trig_type = 'positive_from_zero';
 301 %    S.Dtype     = 'float32';                             % make int16 if files too big
 302     S.Fchannels_eeg = fullfile(spm('dir'),'EEGtemplates', sprintf('cbu_meg_%deeg_montage_old.mat',Nsubchan(sub,find(eegflag)))); % use default montage (which simply explains how to display in 2D), prior to new CBU caps in mid-2008
 303 %    S.Fchannels_eeg =  fullfile(wd,swd,sprintf('eeg_montage_sub%02d.mat',subnum)); % use subject-specific (care labels may not be standard)
 304     
 305     if respmflag
 306       D = spm_eeg_rdata_FIF(S);
 307       basefile = D.fname(1:(end-4));
 308     else
 309       basefile = S.Fdata(1:(end-4));
 310     end
 311 
 312 %%%%% Downsample, then split Mags and Grads (file too big otherwise)
 313 
 314     if reprocessflag
 315       clear S; S.D = sprintf('%s-eeg.mat',basefile); disp(S.D)
 316       S.Radc_new = downsample_spm;
 317       D = spm_eeg_downsample(S);
 318 
 319       clear S; S.D = basefile;
 320       S.Radc_new = downsample_spm;
 321       D = spm_eeg_downsample(S);
 322       basefile = D.fname(1:(end-4));
 323 
 324       clear S; S.D = D.fname;
 325       D = spm_eeg_splitFIF(S);
 326     end
 327     
 328 %%%%% If want to view rawdata (with Danny's tool):
 329 %     meg_viewdata(D.fname);
 330      
 331 %%%%% Preprocess each sensor type
 332 
 333      for sen = 1:Nsen
 334  
 335        if reprocessflag
 336 	clear S
 337         S.D = sprintf('%s-%s.mat',basefile,sennam{sen}); disp(S.D)
 338 	S.filter.type = 'butterworth';
 339 	S.filter.band = 'low';	S.filter.PHz = filt_cut_spm;
 340 %	S.filter.band = 'stop'; S.filter.PHz = [49 51];
 341         S.Dtype       = dformat_spm;
 342 	D = spm_eeg_filter(S);
 343 
 344 %%%%%% !!!Insert ICA here if want to remove EOG/ECG artifacts!!!
 345 %%%%%% (See Jason Taylor; assume filtered, downsampled data appropriate)
 346 	
 347 	clear S; S.D = D.fname;
 348  	S.events.start    = expwin(1);
 349  	S.events.stop     = expwin(2);
 350  	S.events.types    = expcodes;
 351  	S.events.Inewlist = 0;
 352  	S.events.resynch  = offset;
 353 	D = spm_eeg_epochs(S);
 354 	
 355 	% re-classify event-codes
 356 	for e = 1:length(expcodes);
 357 	    fi = find(D.events.code==expcodes(e));
 358 	    if ~isempty(fi)
 359 		D.events.code(fi) = newcodes(e);
 360 	    end
 361 	end
 362 	D.events.types  = unique(D.events.code);
 363 	D.events.Ntypes = length(D.events.types);
 364 	save(D.fname,'D')
 365 	clear S; S.D = D.fname;
 366 
 367       else
 368         S.D = sprintf('e_fd%s-%s.mat',basefile,sennam{sen}); disp(S.D)
 369 	D = spm_eeg_ldata(S.D);
 370       end
 371       
 372 %%%%% Threshold channels (eg EOG)
 373 
 374       nc = D.Nchannels;
 375       S.thresholds.External_list   = 0;
 376       S.thresholds.Check_Threshold = 1;
 377       S.thresholds.threshold       = chan_thr{sub,sen};
 378       S.BadThr                     = 0.2;  
 379       S.artefact.weighted          = 0;
 380       if eegflag(sen)==0
 381 %           S.channels.Bad = unique([D.channels.Bad strcmpi(D.channels.name....sssbadchans{sub}{ses}]);     	% If dont trust MaxFilter channel reconstruction
 382       else
 383             S.channels.Bad = unique([D.channels.Bad badchans{2,subnum,ses}]);  
 384       end
 385       D = spm_eeg_artefact(S);
 386       
 387       nbadchan{sen,sub} = [nbadchan{sen,sub} length(D.channels.Bad)];	
 388       nrejects{sen,sub} = [nrejects{sen,sub} length(find(D.events.reject))];
 389 
 390 %%%%% Re-reference EEG if removed channels
 391       if eegflag(sen) & ~isempty(D.channels.Bad)
 392 	   D = spm_eeg_ldata(D.fname);
 393            meg_reavg_ref(D);
 394 	   save(D.fname,'D')
 395       end
 396       sesnam{sen,ses} = D.fname;
 397       
 398 %%%%% Uncomment if want to average and contrast each session separately 
 399 %%%%% (as well as after merging below)
 400 %
 401 %      clear S; S.D = D.fname;
 402 %      D = spm_eeg_average(S);
 403 %
 404 %      clear S; S.D = D.fname;
 405 %      S.c         = expcons;
 406 %      S.WeightAve = 1;
 407 %      D = spm_eeg_weight_epochs(S);
 408 %      nevents{sen,sub} = D.events.repl;
 409       
 410     end  % end of sen loop
 411   end  % end of ses loop
 412     
 413 %%%%% Merge sessions, average, contrast 
 414 
 415   for sen = 1:Nsen
 416 
 417     if Nses(sub)>1
 418       if ~usetransflag
 419         disp(['Concatenating sessions... (NB: merged files will not have correct channel Loc/Orient info unless trans-ed to first or to default!!)']);
 420       end
 421       clear S; S.D = strvcat(sesnam{sen,:});
 422       S.recode = cell(1,Nses(sub));
 423       D = spm_eeg_merge(S);
 424       clear S; S.D = D.fname;
 425     else
 426       clear S; S.D = sesnam{sen,1};
 427     end
 428     preavgnam{sen,sub} = fullfile(D.path,S.D);  
 429 
 430     Nsubchan(sub,sen) = length(D.channels.eeg) - length(D.channels.Bad);
 431 
 432     D = spm_eeg_average(S);
 433 
 434     clear S; S.D = D.fname;
 435     S.c = expcons;
 436     S.WeightAve = 0;
 437     D = spm_eeg_weight_epochs(S);
 438     
 439     nevents{sen,sub}  = D.events.repl;
 440     avgnam{sen,sub} = fullfile(D.path,D.fname);
 441   end
 442 end
 443 
 444 cd(wd)
 445 
 446 for sen = 1:Nsen
 447  disp(sprintf('%s...',sennam{sen}))
 448  for sub = 1:Nsub
 449    subnum = dosubs(sub);
 450    disp(sprintf('\tSub %d (%d)...',subnum,sub))
 451    disp(sprintf('\t\tNevents (per condition): %s',mat2str(nevents{sen,sub})))
 452    disp(sprintf('\t\tRejects (per session): %s',mat2str(nrejects{sen,sub})))
 453    disp(sprintf('\t\tBadchans (per session): %s',mat2str(nbadchan{sen,sub})))
 454  end
 455 end
 456 
 457 %%%% Create RMS of Grads (mainly for Sensor-Time image files)
 458 
 459 for sen = 1:Nsen
 460   if strcmp(sennam{sen},'grds')
 461      for sub = 1:Nsub
 462        cd(wd); swd = sprintf('sub%d',dosubs(sub)); cd(swd)
 463        clear S; S.D = avgnam{sen,sub};
 464        S.do_write = 1;
 465        D = meg_grds2grms(S); % RMS of grads; just for sensor-level analyses 
 466        avgnam{Nsen+1,sub} = fullfile(D.path,D.fname);
 467        nevents{Nsen+1,sub}  = nevents{sen,sub};
 468      end
 469      Nsen=Nsen+1; sennam{Nsen} = 'grms';
 470      write2Dflag(Nsen) = 1;
 471   end
 472 end
 473 
 474 %%%% Write out Sensor-Time image files for each subject
 475 
 476 for sen = find(write2Dflag)
 477   for sub = 1:Nsub
 478          cd(wd); swd = sprintf('sub%d',dosubs(sub)); cd(swd)
 479 	 disp(avgnam{sen,sub})
 480          [pth,nam,ext] = fileparts(avgnam{sen,sub});
 481          clear S; S.Fname = [nam ext]; 
 482 	 S.interpolate_bad = 0;
 483          S.n = 32;
 484          S.pixsize = 3;
 485          S.trialtypes = [1:Ncons];
 486          P = spm_eeg_convertmat2ana3D(S);
 487 	 if any(sensor_smooth_spm)   
 488 	  if length(sensor_smooth_spm)==1; sensor_smooth_spm = ones(1,3)*sensor_smooth_spm; end
 489 	  for con = 1:size(P,1);
 490 	   [pth,nam,ext] = fileparts(P(con,:));
 491 	   Pout          = fullfile(pth,['s' nam ext]);
 492            spm_smooth(spm_vol(P(con,:)),Pout,sensor_smooth_spm);
 493 	   Pin = strvcat(P(con,:),Pout);
 494 	   spm_imcalc_ui(Pin,Pout,'((i1+eps).*i2)./(i1+eps)',{[],[],'float32',0});   %Reinsert NaNs
 495  	   SensorTimeImgs{sen}{sub}(con,:) = fullfile(wd,swd,Pout);
 496 	  end
 497 	 else
 498 	  for con = 1:size(P,1);
 499  	   SensorTimeImgs{sen}{sub}(con,:) = fullfile(wd,swd,P(con,:));
 500 	  end
 501 	 end
 502   end
 503 end
 504 
 505 %%%% Create Grand Mean across subjects (inc RMS (grms))
 506 cd(wd)
 507 for sen = 1:Nsen
 508  clear S; S.P = strvcat(avgnam{sen,:});
 509  S.Pout = sprintf('G%d-%s.mat',Nsub,sennam{sen})
 510  D = spm_eeg_grandmean(S);
 511 end
 512 
 513 eval(sprintf('save preproc%d.mat subsphere nrejects nbadchan nevents allsssbad dosubs preavgnam avgnam',length(dosubs)))
 514 
 515 disp('!!!NOW USE SPM-Display-M/EEG button to examine results, eg G8-*.mat files !!!')
 516 
 517 %return   % uncommment if want script to finish here
 518 
 519 
 520 % Once displaying one of the modalities, you can hold shift and select both 
 521 % conditions 1+2, and click on a posterior right channel to see the M170
 522 % difference between faces (1) and scrambled faces (2). You can also select
 523 % condition 3, which is the differential ERF/ERP between faces and scrambled,
 524 % then press "topography", enter -100ms for initial time, then press and hold
 525 % the time slider to see topography of difference at every time point (displayed
 526 % in Matlab window) - random noise until ~100ms, when strong differences emerge
 527 
 528 
 529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 530 %%%%%%%%%%%%%%%%% 2D sensor x 1D Time SPMs 
 531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 532 
 533 stdir = fullfile(wd,'SensorTimeSPMs');
 534 try cd(stdir); catch eval(sprintf('!mkdir %s',stdir)); end
 535 
 536 clear grpsubs grpcons imgfiles
 537 grpsubs{1} = [1:Nsub];
 538 % If want to split subjects, eg into two groups, eg:
 539 % grpsubs{1} = [1:4]; grpsubs{2} = [5:Nsub];
 540 grpcons{1} = [1:2];  % Include each condition for mags
 541 grpcons{3} = [1:2];  % Include each condition for eeg
 542 grpcons{4} = [1:2];  % Diff of RMS (be careful if diff number of trials for diff conditions)
 543 %grpcons{4} = [3];    % Or RMS of diff (not equivalent to above)
 544 
 545 Ngrp = length(grpsubs);
 546 for sen = find(write2Dflag)
 547  outdir = fullfile(stdir,sennam{sen})
 548  for grp = 1:Ngrp
 549   for sub = 1:length(grpsubs{grp});
 550    subnum = grpsubs{grp}(sub);
 551    imgfiles{grp}{sub} = SensorTimeImgs{sen}{subnum}(grpcons{sen},:);
 552   end
 553  end
 554  meg_batch_anova(imgfiles,outdir);
 555 end
 556 
 557 disp('!!!NOW press Results button in SPM!!!')
 558 
 559 %return
 560 
 561 % You need to know a bit about the SPM Results interface, but press the Results 
 562 % button (make sure SPM is in "EEG" mode) (or better still, use the "ns" toolbox
 563 % under "Toolbox" button - see WIKI page below) and select the SPM.mat file for 
 564 % one of the modalities, select the default effects of interest F-contrast
 565 % (because we don't care about polarity, at least for Mags and EEG), choose
 566 % 0.001 uncorrected. Then press "Volume" to get table of stats (ignore brain image). 
 567 % You should see, at least in Mags and EEG, frontal and posterior clusters 
 568 % (simply of different polarity) maximal around 170ms. Not much survives whole-
 569 % image correction because only 8 subjects, so few df's ie low power and RFT 
 570 % conservative) - though effects around 170ms do for corrected extent-level 
 571 % for Mags and EEG (using "ns" toolbox); GRMS results are poor though. 
 572 % Correction for height would also be significant if you used SVC because
 573 % of an a priori timewindow of interest around 170ms (again see WIKI page below).
 574 %
 575 % For more info on interpreting these SPMs, see
 576 %                   http://imaging.mrc-cbu.cam.ac.uk/meg/SensorSpm
 577 %
 578 % Also, for an example use with EEG data, see Henson et al (2008), Neuroimage.
 579 %
 580 % Note that you can do SVC for a priori timewindows of interest (see end of above WIKI)
 581 % But one use of this SPMs is to define timewindows of interest (in the absence of 
 582 % a priori ones) for the subsequent source localisation below...
 583 %
 584 % (Note that these SPMs can also handle different numbers and locations of channels
 585 % across subjects, provided their locations are digitised in same space, because the 
 586 % data are interpolated to same grid. For MEG data, particularly gradiometers, the
 587 % results benefit from using 'trans -default' above, to realign across different
 588 % headpositions for different subjects - see Smith et al (in press), HBM Abstract.
 589 
 590 
 591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 592 %%%%%%%%%%%%%%%%% Get MRIS
 593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 594 
 595 for sub=1:Nsub 
 596    subnum = dosubs(sub);
 597    swd = sprintf('sub%d',subnum);
 598    mwd{subnum} = fullfile(wd,swd,'MRI');
 599    try cd(mwd{subnum}); catch eval(sprintf('!mkdir %s',mwd{subnum})); cd(mwd{subnum}); end
 600 
 601    if getmriflag
 602      hdr = spm_select('FPList',mridata{subnum},'^*.dcm');
 603      hdr = spm_dicom_headers(hdr);
 604      
 605      patsex{subnum} = hdr{1}.PatientsSex;
 606      patage{subnum} = hdr{1}.PatientsAge;   % NB At time of scanning, not time of MEG!
 607      
 608      spm_dicom_convert(hdr,'all','flat','nii');
 609 
 610      mrifile{sub} = spm_select('FPList',mwd{subnum},'^s.*-0[0-9].nii$');
 611      % (filter setting just to ensure picks up raw structural - assuming CBU onvention)
 612      mrifile{sub} = strtrim(mrifile{sub}(1,:));   % Take first if multiple previous
 613 
 614      disp('!!!GOOD IDEA TO MANUALLY REPOSITION STRUCTURAL VIA DISPLAY BUTTON!!!')
 615 %     pause
 616      
 617      if VitECapsules(subnum)
 618       meg_headmask(mrifile{sub},'display');         % Remove any VitE capsules
 619       disp('!!!Check difference image!!!');
 620 %      pause     
 621       eval(sprintf('!mv %s_masked.nii %s',mrifile{sub}(1:end-4),mrifile{sub}))
 622      end
 623      patage
 624      patsex
 625    
 626    else
 627      mrifile{sub} = spm_select('FPList',mwd{subnum},'^s.*-0[0-9].nii$');
 628      mrifile{sub} = strtrim(mrifile{sub}(1,:));   % Take first if multiple previous     
 629      wmrifile{sub} = spm_select('FPList',mwd{subnum},'^wms.*-0[0-9].nii$');
 630      wmrifile{sub} = strtrim(wmrifile{sub}(1,:));   % Take first if multiple previous     
 631    end
 632 end
 633 spm_check_registration(strvcat(mrifile));             % Only feasible for <~20 images
 634 try, spm_check_registration(strvcat(wmrifile)); end   % (sub5 bit too warped at back)
 635 
 636 disp('!!!NOW DISPLAY MRI IMAGE in SPM AND DETERMINE FIDUCIALS!!!')
 637 
 638 %%%%%%%%%% Coordinates of fiducials from above MRIs (nasion, left, right)
 639 % Below are from using MRI as is (without manually reorienting) - very approximate
 640 smri_fids{1}  = [ 3 111  22; -78 18 -31; 77 11 -33];
 641 smri_fids{2}  = [ 6 107 -28; -69 26 -41; 68 14 -45];
 642 smri_fids{3}  = [-2 124 -23; -78 22 -52; 70 21 -58];
 643 smri_fids{4}  = [ 3 109 -8;  -72 18 -41; 72 18 -47];
 644 smri_fids{5}  = [-15 103 -33; -79 3 -38; 62 13 -46];
 645 smri_fids{6}  = [-4 109 -20; -71 15 -32; 63 11 -35];
 646 smri_fids{7}  = [-1 93  -5;  -72 14 -44; 70 10 -44];
 647 smri_fids{8}  = [ 1 99  -22; -73  8 -27; 69 10 -42];
 648 smri_fids{9}  = [-3 125 -24; -76 22 -55; 69 22 -58];
 649 % Below are after my manual reorienting (just for your reference)
 650 %smri_fids{1}  = [ 0.7 80.0 -31.2;   -76.9 -14.3 -45.9;   79.9 -19.2 -41.0];
 651 %smri_fids{2}  = [ 1.3 78.7 -30.9;   -71.8  -2.5 -58.0;   71.5   1.8 -58.0];  
 652 %smri_fids{3}  = [ 1.7 88.8 -24.6;   -74.0  -1.4 -66.1;   71.7  -2.8 -66.1];
 653 %smri_fids{4}  = [-1.6 78.9 -22.4;   -74.8 -13.3 -57.7;   71.6  -7.2 -54.6];
 654 %smri_fids{5} = {TBA};
 655 %smri_fids{6}  = [-2.4 79.1 -27.1;   -72.1  -9.8 -44.6;   64.3  -9.8 -51.9];
 656 %smri_fids{7}  = [-2.3 73.2  -7.0;   -71.8  -2.0 -46.9;   70.2  -4.9 -49.8]; 
 657 %smri_fids{8}  = [ 0.0 78.1 -30.3;   -71.3  -1.5 -48.5;   72.8   6.0 -51.5]; 
 658 %smri_fids{9}  = [ 0.0 88.9 -31.1;   -76.8 -15.5 -56.6;   78.0 -12.7 -55.0];
 659 
 660 
 661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 662 %%%%%%%%%%%%%%%%% Localise on Mesh
 663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 664 
 665 addpath /imaging/local/Brainstorm/Toolbox
 666 
 667 clear sennam;
 668 sennam{1}   = 'mags'; sennam{2} = 'grds'; sennam{3} = 'eeg';
 669 Nsen     = length(sennam);
 670 		      
 671 % !!! There are several options for source localisation, eg choice of
 672 % forward model (eg Spheres or BEMs), and choice of inversion method (eg
 673 % MSP, COH, MNM). Below illustrates just two possible inversions (each 
 674 % inversion is indexed by "val"), the second of which has been commented 
 675 % out because BEMs take a VERY LONG time (and don't work well for EEG yet). 
 676 % Of course many more options can be tried (and compared using the model-evidence,
 677 % recorded in mod_evd below, provided that you don't also change the
 678 % data, eg epoch inverted). 
 679 %
 680 % For more information about forward models, see 
 681 %    http://imaging.mrc-cbu.cam.ac.uk/meg/SpmForwardModels
 682 % For more information about inversion parameters, see 
 683 %    Friston et al (2008) Neuroimage 
 684 %    (PDF available here http://imaging.mrc-cbu.cam.ac.uk/meg/SpmAnalysis)
 685 
 686 %%%%%%%%%%%%%%%%%%%%
 687 val = 1;  % Spherical forward model using canonical cortical mesh but individual head meshes
 688 comment{val} = 'Concentric Spheres';
 689 cortex{val}  = 'Can';   % Canonical (inverse-normalised template) cortical mesh
 690 CtxSize(val) = 8196;    % One of 5124, 8196 or 20484 dipoles in canonical cortical mesh
 691 iskull{val}  = 'Ind';   % Individual (SPM-created) inner skull mesh
 692 oskull{val}  = '';      % (Outer skull irrelevant for spherical models)
 693 scalp{val}   = 'Ind';   % Individual (SPM-created) scalp mesh
 694 formod{val}  = 'Sph';   % Concentric spheres
 695 surfit(val,:)= [2 2 2]; % Use 2nd surface to fit sphere (here, innerskull) for all sensor-types
 696 
 697 invcons{val} = [1 2];   % Conditions to invert
 698 invtype{val} = 'GS';    % Type of inversion (This is MSP, with a Greedy Search (GS))
 699 invtwin{val} = expwin;  % Invert whole epoch
 700 
 701 %%%%% Options for subsequent time-freq contrast
 702 contwin{val}{1} = [140 190];  % Time window for contrast
 703 contwin{val}{2} = [];         % Frequency window for contrast ([]=all freqs) 
 704 conengy{val}    = 'evoked';   % or 'induced', but spm_eeg_invert_fuse doesnt handle yet
 705 
 706 %%%%%%%%%%%%%%%%%%%%
 707 val = 2;  % As val=1 except IID (ie standard minimum norm) used to invert
 708 comment{val} = 'Concentric Spheres';
 709 cortex{val}  = 'Can';   % Canonical (inverse-normalised template) cortical mesh
 710 CtxSize(val) = 8196;    % One of 5124, 8196 or 20484 dipoles in canonical cortical mesh
 711 iskull{val}  = 'Ind';   % Individual (SPM-created) inner skull mesh
 712 oskull{val}  = '';      % (Outer skull irrelevant for spherical models)
 713 scalp{val}   = 'Ind';   % Individual (SPM-created) scalp mesh
 714 formod{val}  = 'Sph';   % Concentric spheres
 715 surfit(val,:)= [2 2 2]; % Use 2nd surface to fit sphere (here, innerskull) for all data-types
 716 
 717 invcons{val} = [1 2];   % Conditions to invert
 718 invtype{val} = 'IID';   % Type of inversion
 719 invtwin{val} = expwin;  % Invert whole epoch
 720 
 721 %%%%% Options for subsequent time-freq contrast
 722 contwin{val}{1} = [140 190];  % Time window for contrast
 723 contwin{val}{2} = [];         % Frequency window for contrast ([]=all freqs) 
 724 conengy{val}    = 'evoked';   % or 'induced', but spm_eeg_invert_fuse doesnt handle yet
 725 
 726 %%%%%%%%%%%%%%%%%%%%
 727 %val = 2;  % BEM using canonical meshes (Warning: BEMs take a long time to compute!)
 728 %
 729 %comment{val} = 'Boundary Element Model';
 730 %cortex{val}  = 'Can';    % Canonical (inverse-normalised template) cortical mesh
 731 %CtxSize(val) = 8196;     % One of 5124, 8196 or 20484 dipoles in canonical cortical mesh
 732 %iskull{val}  = 'Can';    % Canonical (inverse-normalised template) inner skull mesh
 733 %oskull{val}  = 'Can';    % Canonical (inverse-normalised template) outer skull mesh
 734 %scalp{val}   = 'Can';    % Canonical (inverse-normalised template) scalp mesh
 735 %formod{val}  = 'BEM';    % Boundary Element Model
 736 %surfit(val,:)= [2 2 4];  % Surfaces for BEM: up to 2nd for MEG (iskull) and 4th for EEG (+oskull+scalp)
 737 %invcons{val} = [1 2];    % Conditions to invert
 738 %invtype{val} = 'GS';     % Type of inversion (This is MSP, with a Greedy Search (GS))
 739 %invtwin{val} = expwin;   % Invert whole epoch
 740 
 741 %%%%% Options for subsequent time-freq contrast
 742 %contwin{val}{1} = [140 190];  % Time window for contrast
 743 %contwin{val}{2} = [];         % Frequency window for contrast ([]=all freqs) 
 744 %conengy{val}    = 'evoked';   % or 'induced', but spm_eeg_invert_fuse doesnt handle yet
 745 
 746 % Other options you can consider are "overlapping spheres" for the
 747 % forward model (see spm_eeg_inv_BSTfwdsol.m), minimumum norm (IID) for
 748 % the inversion, etc. See Henson et al (2009), Neuroimage, for more options.
 749 
 750 Nval = length(comment);
 751 mod_evd=[];
 752 
 753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 754 
 755 % If want to pass prior estimates of sensor-level error (noise), eg
 756 % estimates from empty-room data in case of MEG, such as below...
 757 %tmp = load('/imaging/rh01/Methods/MEG_Group/MeanCn.mat')
 758 % !!!Care: Cn only relevant to SSSt and 40Hz lowpass (see Henson et al, submitted)!!!
 759 
 760 for sub = 1:Nsub
 761 
 762  cd(wd)
 763  subnum = dosubs(sub);
 764  swd = sprintf('sub%d',subnum);
 765  cd(swd)
 766  
 767 % If want to pass prior estimates of sensor-level error (noise)...
 768 % !!!Care - sensor order in sennam must match order in Cn, ie Cn{1}=mags, Cn{2}=grads!!!
 769 % Ce{1} = {speye(Nsubchan(sub,1)) tmp.Cn{1}};   % Mags
 770 % Ce{2} = {speye(Nsubchan(sub,2)) tmp.Cn{2}};   % Grds
 771 % Ce{3} = {speye(Nsubchan(sub,3))};             % EEG (no noise estimates yet)
 772 %
 773 % Otherwise, do not pass anything, corresponding to just IID ('white') noise only:
 774  Ce = cell(1,Nsen);
 775    
 776  for val = 1:Nval
 777    
 778   for sen = 1:Nsen
 779 
 780    clear S;  
 781    S.D = char(preavgnam{sen,sub});
 782 % This is using all trials to estimate sources, ie total (induced+evoked) power.
 783 % This gives more sample points in total, and the pure evoked part can always be 
 784 % extracted when estimating time-freq contrasts afterwards (see below). If you want
 785 % to localise purely evoked power, then use instead:
 786 %   S.D = char(avgnam{sen,sub});
 787 % Also may prefer "mvcomp" rather than "trans" data, if don't trust "trans default"
 788 
 789    D = spm_eeg_ldata(S.D); disp(S.D)
 790 
 791 %If want to clear previous localisations (safer?)
 792    if val==1
 793      if isfield(D,'inv');  D = rmfield(D,'inv'); save(D.fname,'D'); end
 794      if isfield(D,'con');  D = rmfield(D,'con'); save(D.fname,'D'); end
 795    end
 796    
 797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Initialise
 798 
 799    disp(comment{val})
 800    D.val = val; D.fname
 801    D.inv{val}.method = 'imaging';
 802    load('defaults_eeg_inv.mat')
 803    D.inv{val} = invdefts.imag;
 804    D.inv{val}.date = mat2str(fix(clock));
 805    D.inv{val}.comment = comment{val};
 806 
 807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MRI
 808 
 809 %%%%%%%%%%%%%%%%%%% Meshing 1: Normalising native MRI
 810 
 811    D.inv{val}.mesh.sMRI = mrifile{sub};   % In case many from previous
 812 
 813    [pth,nam,ext] = spm_fileparts(D.inv{val}.mesh.sMRI);
 814    mri_stem = nam;
 815    wmrifile{sub} = fullfile(pth,['wm' nam ext]);
 816    if ~exist(wmrifile{sub})
 817     D = spm_eeg_inv_spatnorm(D);	
 818    else
 819     def_name      = [nam '_sn_1.mat'];
 820     isndef_name   = [nam '_inv_sn_1.mat'];
 821     D.inv{val}.mesh.def    = fullfile(pth,def_name);
 822     D.inv{val}.mesh.invdef = fullfile(pth,isndef_name);
 823     D.inv{val}.mesh.nobias = fullfile(pth,['m' nam ext]);
 824     D.inv{val}.mesh.wmMRI  = fullfile(pth,['wm' nam ext]);
 825    end
 826 
 827 %%%%%%%%%%%%%%%%%%% Meshing 2: Creating binary images for scalp (and inner skull)
 828 
 829    D.inv{val}.mesh.msk_scalp = spm_select('List',mwd{subnum},'^*scalp\.nii$');
 830  
 831    if isempty(D.inv{val}.mesh.msk_scalp)
 832     D = spm_eeg_inv_getmasks(D);	
 833    else	% assume other masks exist too!
 834     D.inv{val}.mesh.msk_scalp   = fullfile(mwd{subnum},D.inv{val}.mesh.msk_scalp);
 835     D.inv{val}.mesh.msk_iskull  = spm_select('FPList',mwd{subnum},'^*iskull\.nii$');
 836     D.inv{val}.mesh.msk_cortex  = spm_select('FPList',mwd{subnum},'^*cortex\.nii$');
 837     D.inv{val}.mesh.msk_flags   = struct('img_norm',0,'ne',1,'ng',2,'thr_im',[.5 .05]);
 838    end
 839    spm_check_registration(char(D.inv{val}.mesh.msk_scalp,D.inv{val}.mesh.msk_iskull,D.inv{val}.mesh.msk_cortex,D.inv{val}.mesh.sMRI));
 840 
 841 %%%%%%%%%%%%%%%%%%% Meshing 2: Creating meshes
 842 
 843    D.inv{val}.mesh.template  = 0;
 844    D.inv{val}.mesh.canonical = 1;
 845    D.inv{val}.mesh.Msize = CtxSize(val);
 846   
 847   % Prompt for canonical or user-specified cortical meshs (SPM does not currently
 848   % produce individual ones, because automatic meshing of cortex is difficult!)
 849  
 850    if strcmp(cortex{val},'Can')
 851     Tmesh = load(fullfile(spm('dir'),'EEGtemplates',sprintf('mni_mesh_cortex_%d.mat',CtxSize(val))));
 852     D.inv{val}.mesh.tess_mni.vert    = Tmesh.vert;
 853     D.inv{val}.mesh.tess_mni.face    = uint16(Tmesh.face);
 854     Tmesh.vert = spm_get_orig_coord(Tmesh.vert,D.inv{val}.mesh.def);
 855     D.inv{val}.mesh.tess_ctx.vert    = Tmesh.vert;
 856     D.inv{val}.mesh.tess_ctx.face    = uint16(Tmesh.face);
 857    elseif strcmp(cortex{val},'Load')
 858     Tmesh = spm_select(1,'mat','Select cortex mat file containing vert and face',[],pwd,'.*mat');
 859     D.inv{val}.mesh.tess_ctx.vert    = Tmesh.vert;
 860     D.inv{val}.mesh.tess_ctx.face    = uint16(Tmesh.face);
 861     Tmesh.vert = spm_get_orig_coord(Tmesh.vert,D.inv{val}.mesh.invdef);
 862     D.inv{val}.mesh.tess_mni.vert    = Tmesh.vert;
 863     D.inv{val}.mesh.tess_mni.face    = uint16(Tmesh.face);
 864    else
 865     error('No cortical mesh specified????')
 866    end
 867 
 868    iskull_mesh_name = fullfile('MRI',[mri_stem '_iskull_mesh.mat']);
 869    scalp_mesh_name = fullfile('MRI',[mri_stem '_scalp_mesh.mat']);
 870     
 871   % Prompt for canonical, individual (from SPM) or user-specified inner skull
 872   % (Use canonical if worried about canonical cortex piercing innner skull)
 873 
 874    if strcmp(iskull{val},'Can')
 875     Tmesh = load(fullfile(spm('dir'),'EEGtemplates','mni_mesh_iskull_2562.mat'));
 876     Tmesh.vert = spm_get_orig_coord(Tmesh.vert,D.inv{val}.mesh.def);
 877     D.inv{val}.mesh.tess_iskull.vert = Tmesh.vert;
 878     D.inv{val}.mesh.tess_iskull.face = uint16(Tmesh.face);
 879    elseif strcmp(iskull{val},'Ind')
 880     if ~exist(iskull_mesh_name)
 881      D = spm_eeg_inv_getmeshes(D,1);
 882      vert = D.inv{val}.mesh.tess_iskull.vert;
 883      face = D.inv{val}.mesh.tess_iskull.face;
 884      save(iskull_mesh_name,'vert','face');
 885     else
 886      Tmesh = load(iskull_mesh_name);
 887      D.inv{val}.mesh.tess_iskull.vert = Tmesh.vert;
 888      D.inv{val}.mesh.tess_iskull.face = uint16(Tmesh.face);
 889     end
 890    elseif strcmp(iskull{val},'Load')
 891      Tmesh = spm_select(1,'mat','Select iskull mat file containing vert and face',[],pwd,'.*mat');
 892      D.inv{val}.mesh.tess_iskull.vert = Tmesh.vert;
 893      D.inv{val}.mesh.tess_iskull.face = uint16(Tmesh.face);
 894    else
 895      warning('No inner skull mesh specified')
 896    end
 897 
 898   % Prompt for canonical or user-specified outer skull (SPM does not currently
 899   % produce individual ones, because segmenting outer skull from scalp difficult)
 900   % (Note that outer skull only really necessary for EEG BEMs)
 901 
 902    if strcmp(oskull{val},'Can')
 903     Tmesh = load(fullfile(spm('dir'),'EEGtemplates','mni_mesh_oskull_2562.mat'));
 904     Tmesh.vert = spm_get_orig_coord(Tmesh.vert,D.inv{val}.mesh.def);
 905     D.inv{val}.mesh.tess_oskull.vert = Tmesh.vert;
 906     D.inv{val}.mesh.tess_oskull.face = uint16(Tmesh.face);
 907    elseif strcmp(oskull{val},'Load')
 908      Tmesh = spm_select(1,'mat','Selectoskull  mat file containing vert and face',[],pwd,'.*mat');
 909      D.inv{val}.mesh.tess_oskull.vert = Tmesh.vert;
 910      D.inv{val}.mesh.tess_oskull.face = uint16(Tmesh.face);
 911    else
 912      warning('No outer skull mesh specified')
 913    end
 914 
 915   % Prompt for canonical, individual (from SPM) or user-specified scalp
 916   % (Use canonical if worried about canonical cortex or inner skull piercing scalp)
 917 
 918    if strcmp(scalp{val},'Can')
 919     Tmesh = load(fullfile(spm('dir'),'EEGtemplates','mni_mesh_scalp_2562.mat'));
 920     Tmesh.vert = spm_get_orig_coord(Tmesh.vert,D.inv{val}.mesh.def);
 921     D.inv{val}.mesh.tess_scalp.vert = Tmesh.vert;
 922     D.inv{val}.mesh.tess_scalp.face = uint16(Tmesh.face);
 923    elseif strcmp(scalp{val},'Ind')
 924     if ~exist(scalp_mesh_name)
 925      D = spm_eeg_inv_getmeshes(D,2);
 926      vert = D.inv{val}.mesh.tess_scalp.vert;
 927      face = D.inv{val}.mesh.tess_scalp.face;
 928      save(scalp_mesh_name,'vert','face');
 929     else
 930      Tmesh = load(scalp_mesh_name);
 931      D.inv{val}.mesh.tess_scalp.vert = Tmesh.vert;
 932      D.inv{val}.mesh.tess_scalp.face = uint16(Tmesh.face);
 933     end
 934    elseif strcmp(scalp{val},'Load')
 935      Tmesh = spm_select(1,'mat','Select scalp mat file containing vert and face',[],pwd,'.*mat');
 936      D.inv{val}.mesh.tess_scalp.vert = Tmesh.vert;
 937      D.inv{val}.mesh.tess_scalp.face = uint16(Tmesh.face);
 938    else
 939      warning('No scalp mesh specified')
 940    end
 941 
 942   % Always individual scalp for datareg
 943   
 944    if ~exist(scalp_mesh_name)
 945      S = spm_eeg_inv_getmeshes(D,2);   % lastarg==1 returns iskull (not scalp)
 946      vert = S.inv{val}.mesh.tess_scalp.vert;
 947      face = S.inv{val}.mesh.tess_scalp.face;
 948      save(scalp_mesh_name,'vert','face');
 949      D.inv{val}.mesh.tess_scalp_datareg.vert  = vert;
 950      D.inv{val}.mesh.tess_scalp_datareg.face  = uint16(face);  
 951    else
 952      Tmesh = load(scalp_mesh_name);
 953      D.inv{val}.mesh.tess_scalp_datareg.vert  = Tmesh.vert;
 954      D.inv{val}.mesh.tess_scalp_datareg.face  = uint16(Tmesh.face);  
 955    end
 956   
 957    spm_eeg_inv_checkmeshes(D);
 958    save(D.fname,'D');
 959 
 960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DataReg
 961 
 962    if isempty(D.inv{val}.datareg.fid_coreg) 
 963     
 964     D.inv{val}.datareg.sensors    = D.channels.Loc';
 965     D.inv{val}.datareg.fid_eeg    = D.channels.fid_eeg;
 966     D.inv{val}.datareg.headshape  = D.channels.headshape;
 967     if ~eegflag(sen)
 968      D.inv{val}.datareg.megorient = D.channels.Orient';
 969     end
 970     D.inv{val}.datareg.scalpvert  = D.inv{val}.mesh.tess_scalp_datareg.vert;
 971     D.inv{val}.datareg.fid_mri    = smri_fids{subnum};
 972     D = spm_eeg_inv_datareg(D);
 973     fid_err(sub) = sqrt(mean(mean((D.inv{val}.datareg.fid_coreg - D.inv{val}.datareg.fid_mri).^2)))
 974    end
 975   
 976    spm_eeg_inv_checkdatareg(D);
 977    save(D.fname,'D');
 978    clear S; S.D=D.fname; 
 979 %   meg_pretty_datareg(S);        % Prettier rendering of head and sensors
 980 
 981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Forward Model
 982 
 983    rotate3d off
 984    D.inv{val}.method = 'Imaging';
 985    if ~eegflag(sen)
 986     if strcmp(formod{val},'Sph'), meth = 'meg_sphere';
 987     elseif strcmp(formod{val},'BEM'), meth = 'meg_bem'; 
 988     elseif strcmp(formod{val},'OS'), meth = 'meg_os'; 
 989     else, error('Unknown forward model!'); end
 990    else
 991     if strcmp(formod{val},'Sph'), meth = 'eeg_3sphereBerg';
 992     elseif strcmp(formod{val},'BEM'), meth = 'eeg_bem'; 
 993     elseif strcmp(formod{val},'OS'), meth = 'eeg_os'; 
 994     else, error('Unknown forward model!'); end
 995    end
 996    D.inv{val}.forward.method =  meth;
 997    D.inv{val}.forward.surface2fit = surfit(val,sen);
 998 %   D.inv{val}.forward.NVertMax = 1000;   % If want to save some time!
 999    gain_name = fullfile(mwd{subnum},[mri_stem '_SPMgainmatrix_' upper(sennam{sen}) ...
1000  		    '_' formod{val} '_' num2str(surfit(val,sen)) '.mat'])
1001    gxyz_name = fullfile(mwd{subnum},[mri_stem '_SPMgainmatxyz_' upper(sennam{sen}) ...
1002 		    '_' formod{val} '_' num2str(surfit(val,sen)) '.mat'])
1003   
1004 %  delete(gain_name);   % if want to be safe 
1005    if ~exist(gain_name) %| ~exist(gxyz_name)
1006     [D,OPTIONS] = spm_eeg_inv_BSTfwdsol(D);
1007     eval(sprintf('!mv %s %s',D.inv{val}.forward.gainmat,gain_name))
1008     eval(sprintf('!mv %s %s',D.inv{val}.forward.gainxyz,gxyz_name))
1009    end
1010 
1011    D.inv{val}.forward.gainmat = gain_name;
1012    D.inv{val}.forward.gainxyz = gxyz_name;
1013    save(D.fname,'D');
1014 
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Invert each modality separately
1016 
1017    D.inv{val}.inverse = [];
1018    D.inv{val}.inverse.trials = invcons{val};
1019    D.inv{val}.inverse.type   = invtype{val};
1020    D.inv{val}.inverse.woi    = invtwin{val};
1021    D.inv{val}.inverse.lpf    = 0;   % Confusing, but hpf refers to cutoff
1022    D.inv{val}.inverse.hpf    = 40;  % of lowpass (and lpf to cutoff of highpass)
1023 % Some extra parameters that you could play with...(but defaults seem ok!)
1024 %   D.inv{val}.inverse.smooth = 0.8;
1025 %   D.inv{val}.inverse.Np = 256;
1026 %   D.inv{val}.inverse.Han = 0;
1027    D.inv{val}.inverse.Qe = Ce{sen};
1028 
1029    D = spm_eeg_invert(D);
1030 %   D = spm_eeg_invert_fuse(D);   % If want to compare exactly with fused below
1031    save(D.fname,'D');
1032    mod_evd(sub,val,sen) = D.inv{val}.inverse.F1(end);
1033    
1034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1035 
1036    D.inv{val}.contrast.woi  = contwin{val}{1};
1037    D.inv{val}.contrast.fboi = contwin{val}{2};
1038    D.inv{val}.contrast.type = conengy{val};
1039    D.val = val;
1040    D = spm_eeg_inv_results(D); 
1041    spm_eeg_inv_results_display(D); 
1042 
1043    if write3Dflag
1044     D.inv{val}.contrast.smooth = source_smooth_spm;
1045     D.inv{val}.contrast.rms = 1;
1046 %    D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1047     D = spm_eeg_inv_Mesh2Voxels(D);
1048     SourceImgs{sen}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1049    end  
1050 
1051 %  If want to save on filesize
1052 %   if val>2
1053 %    canvert = D.inv{val-1}.mesh.tess_mni.vert;
1054 %    canface = D.inv{val-1}.mesh.tess_mni.face;
1055 %    D.inv{val-1}.mesh = [];
1056 %    D.inv{val-1}.mesh.tess_mni.vert = canvert;
1057 %    D.inv{val-1}.mesh.tess_mni.face = canface;
1058 %    D.inv{val-1}.datareg = [];
1059 %    clear canvert canface
1060 %   end 
1061  
1062    disp(sprintf('Sub=%d, %s, val=%d: %s',sub,sennam{sen},val,D.inv{val}.comment))
1063    save(D.fname,'D');
1064    
1065   end % end sen
1066 
1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068 % Fusion
1069 
1070   if fuseinvertflag
1071    DD = {};
1072    for sen=1:Nsen
1073      DD{sen} = spm_eeg_ldata(preavgnam{sen,sub});
1074      DD{sen}.val = val;
1075    end
1076    DD{1}.inv{val}.inverse.Nm = [];   % Reset any parameters from last inversion
1077    DD{1}.inv{val}.inverse.Nr = [];   % Reset any parameters from last inversion
1078    DD{1}.inv{val}.inverse.QP = [];   % Reset any parameters from last inversion
1079 
1080    DD{1}.inv{val}.inverse.OutExt = '_fused';
1081    D = spm_eeg_invert_fuse(DD);  
1082    mod_evd(sub,val,Nsen+1) = D.inv{val}.inverse.F1(end);
1083 
1084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1085 
1086    D.inv{val}.contrast.woi  = contwin{val}{1};
1087    D.inv{val}.contrast.fboi = contwin{val}{2};
1088    D.inv{val}.contrast.type = conengy{val};
1089    D.val = val;
1090    D = spm_eeg_inv_results(D); 
1091    spm_eeg_inv_results_display(D); 
1092 
1093    if write3Dflag
1094     D.inv{val}.contrast.smooth = source_smooth_spm;
1095     D.inv{val}.contrast.rms = 1;
1096 %    D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1097     D = spm_eeg_inv_Mesh2Voxels(D);
1098     SourceImgs{Nsen+1}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1099    end
1100 
1101    sennam{Nsen+1} = 'fused';
1102    preavgnam{Nsen+1,sub} = fullfile(D.path,D.fname);
1103   end
1104   
1105  end % end val
1106  
1107 end % end subs
1108 
1109 % Review model-evidences (note cannot compare fused to individual modality
1110 % inversions, since data differs)
1111 for sub = 1:Nsub
1112    subnum = dosubs(sub);
1113    disp(sprintf('\tSub %d (%d)...',subnum,sub))
1114    disp(sprintf('\t\tFiducial error (RMS mm): %3.2f',fid_err(sub)))
1115    for val=1:Nval
1116      disp(sprintf('\t\tModel-evidences (a.u.): %s',mat2str(round(squeeze(mod_evd(sub,val,:))))))
1117    end
1118 end
1119 
1120 % Fid errors may be quite large (~8mm) for some subjects, simply because
1121 % I did not bother to mark them carefully on the MRI. Note that the
1122 % actual coregistration is determined primarily by the digitised headshape;
1123 % the fiducials are only really used to check the quality of registration.
1124 
1125 %spm_check_registration(strvcat(wmrifile))   % double-check normaliation worked
1126 
1127 disp('!!!Review single-subject localisations if you wish!!!')
1128 
1129 % At this point, you can review a single-subject's localisation by
1130 % pressing the "3D source reconstruction" button, and then loading one
1131 % of the mmca* files (for one modality, or the "*_fused.mat" for the
1132 % fusion of the modalities). You can then press the "mip" button to see
1133 % the overall reconstruction, or the "display" button under "window" to
1134 % see the power in the time-freq contrast (for the selected
1135 % condition). You can also display a movie and change the start-stop
1136 % times, etc. Don't press the other buttons for inversion, fusion, group
1137 % inversion etc because they will be covered below...
1138 
1139 %%%%%%%%%%%%%%%%% Or a quick look at mean over subjects...
1140 
1141 clear S; S.con = [1 -1]; S.boi{1} = [140 190]; S.boi{2} = []; % boi{2}=[] is all freqs
1142 S.fig = 2;
1143 for val=1:Nval
1144  S.val = val; 
1145  for sen=1:(Nsen+fuseinvertflag)
1146   S.fig = S.fig+1;
1147   S.P = strvcat(preavgnam{sen,:});
1148   meg_inv_display_con(S);
1149  end
1150 end
1151 lastfig = S.fig;
1152 
1153 % You should see bilateral fusiform and anterior inferior temporal
1154 % cortex, plus some more posterior occipitotemporal stuff on the right,
1155 % in most of the modalities, particularly the fused result
1156   
1157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1158 %%%%%%%%%%%%%%%%% 3D  SPMs 
1159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1160 
1161 stdir = fullfile(wd,'SourceSPMs');
1162 try cd(stdir); catch eval(sprintf('!mkdir %s',stdir)); end
1163 
1164 clear grpsubs imgfiles grpcons
1165 grpsubs{1} = [1:Nsub];
1166 % If want to split subjects, eg into two groups, eg:
1167 % grpsubs{1} = [1:4]; grpsubs{2} = [5:Nsub];
1168 
1169 grpcons = [1:2];
1170 Ngrp = length(grpsubs);
1171 for val=1:Nval
1172  valdir = fullfile(stdir,sprintf('Inv%d',val));
1173  try cd(valdir); catch eval(sprintf('!mkdir %s',valdir)); end
1174  for sen = 1:(Nsen+fuseinvertflag)
1175   outdir = fullfile(valdir,sennam{sen})
1176   for grp = 1:Ngrp
1177    for sub = 1:length(grpsubs{grp});
1178     subnum = grpsubs{grp}(sub);
1179     imgfiles{grp}{sub} = SourceImgs{sen}{val}{subnum}(grpcons,:);
1180    end
1181   end
1182   meg_batch_anova(imgfiles,outdir,'/imaging/local/spm/spm5/EEGtemplates/mni_mesh_cortex_8196.nii');
1183  end
1184 end
1185 cd(stdir)
1186 disp('!!!Review the group 3D stats if you wish!!!')
1187 
1188 %return
1189 
1190 % Again you need to know a bit about the SPM Results interface, but press
1191 % Results and select an SPM.mat file for one of the modalities and enter
1192 % a new T-contrast [1 -1] to find voxels in which greater source
1193 % amplitude for faces than scrambled faces, choose 0.01 uncorrected (not
1194 % much survives whole-image correction because only 8 subjects, so few
1195 % df's ie low power and RFT conservative) and then press "Volume" to get
1196 % table of stats. It will be very rough (speckled) because of the low
1197 % dfs, but you should see a cloud around right  fusiform for example for 
1198 % the fused stats. These statistical maps look better with more subjects, 
1199 % or when using SNPM or PPM's (see Henson et al, 2007, Neuroimage and
1200 % Taylor & Henson, in prep, for more information).
1201 
1202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203 %%%%%%%%%%%%%%%%% 3D  PPMs 
1204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205 
1206 % This uses SPMs above to calculate Posterior Probability Maps (PPMs),
1207 % which do not have any mutliple comparison issues (eg no need for RFT)
1208 % However, it will take a long time...
1209 
1210 for val=1:Nval
1211  valdir = fullfile(stdir,sprintf('Inv%d',val));
1212  cd(valdir); 
1213  for sen = 1:(Nsen+fuseinvertflag)
1214   outdir = fullfile(valdir,sennam{sen})
1215   cd(outdir)
1216   load('SPM.mat');
1217   spm_spm_Bayes(SPM);
1218  end
1219 end
1220 disp('!!!Review the group 3D PPMs if you wish!!!')
1221 
1222 % Again you need to know a bit about the PPM Results interface, but press
1223 % Results and select an SPM.mat file for one of the modalities and enter
1224 % a new T-contrast [1 -1], but this time, select "Bayesian" rather than
1225 % "classical" when prompted. Then change the default effect size threshold 
1226 % to 0, and probability threshold to 0.99. This will show voxels with a
1227 % >99% probability of the increase for faces relative to scrambled being
1228 % greater than zero.
1229 
1230 
1231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1232 % Group inversion
1233 
1234 grp_mod_evd=[];
1235 if grpinvertflag
1236  for sen=1:Nsen 
1237   clear DD  
1238   for sub=1:Nsub
1239    DD{sub} = spm_eeg_ldata(preavgnam{sen,sub});
1240   end
1241   for val=1:Nval   % NB: Group inversion makes no difference for IID (val=2 here)
1242    for sub=1:Nsub
1243     DD{sub}.val = val;
1244     DD{sub}.inv{val}.comment    = [DD{sub}.inv{val}.comment 'Group'];
1245     DD{sub}.inv{val}.inverse.Nm = [];   % Reset any parameters from last inversion
1246     DD{sub}.inv{val}.inverse.Nr = [];   % Reset any parameters from last inversion
1247    end
1248    
1249    DD = spm_eeg_invert(DD);
1250 
1251    % Save outputs
1252    for sub=1:Nsub
1253     D       = DD{sub};
1254     D.fname = [D.fname(1:(end-4)) '_grp.mat'];
1255     grppreavgnam{sen,sub} = fullfile(D.path, D.fname);
1256     save(fullfile(D.path, D.fname), 'D');
1257     grp_mod_evd(sub,val,sen) = D.inv{val}.inverse.F1(end);
1258 
1259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1260 
1261     D.inv{val}.contrast.woi  = contwin{val}{1};
1262     D.inv{val}.contrast.fboi = contwin{val}{2};
1263     D.inv{val}.contrast.type = conengy{val};
1264     D.val = val;
1265     D = spm_eeg_inv_results(D); 
1266     spm_eeg_inv_results_display(D); 
1267 
1268     if write3Dflag
1269      D.inv{val}.contrast.smooth = source_smooth_spm;
1270      D.inv{val}.contrast.rms = 1;
1271 %     D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1272      D = spm_eeg_inv_Mesh2Voxels(D);
1273      GrpSourceImgs{sen}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1274     end 
1275     save(fullfile(D.path, D.fname), 'D');
1276    end % end val
1277   end % end sub
1278  end % end sen
1279  
1280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281 % Fuse any Group inversion
1282  if fuseinvertflag
1283   for sub=1:Nsub
1284    clear DD;
1285    for sen=1:Nsen
1286      DD{sen} = spm_eeg_ldata(grppreavgnam{sen,sub});
1287    end
1288 
1289    for val=1:Nval   % NB: Group inversion makes no difference for IID (val=2 here)
1290     for sen=1:Nsen
1291      DD{sen}.val = val;
1292      DD{sen}.inv{val}.inverse.Nm = [];   % Reset any parameters from last inversion
1293      DD{sen}.inv{val}.inverse.Nr = [];   % Reset any parameters from last inversion
1294     % DD{sen}.inv{val}.inverse.QP = [];  % (Important not to reset the source priors QP from the grp inversion above)
1295      DD{sen}.inv{val}.inverse.OutExt = '_fused';
1296     end
1297     
1298     D = spm_eeg_invert_fuse(DD);  
1299     grp_mod_evd(sub,val,Nsen+1) = D.inv{val}.inverse.F1(end);
1300   
1301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1302 
1303     D.inv{val}.contrast.woi  = contwin{val}{1};
1304     D.inv{val}.contrast.fboi = contwin{val}{2};
1305     D.inv{val}.contrast.type = conengy{val};
1306     D.val = val;
1307     D = spm_eeg_inv_results(D); 
1308     spm_eeg_inv_results_display(D); 
1309 
1310     if write3Dflag
1311      D.inv{val}.contrast.smooth = source_smooth_spm;
1312      D.inv{val}.contrast.rms = 1;
1313 %     D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1314      D = spm_eeg_inv_Mesh2Voxels(D);
1315      GrpSourceImgs{Nsen+1}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1316     end
1317     save(fullfile(D.path, D.fname), 'D');
1318    end  % end val
1319    
1320    sennam{Nsen+1} = 'fused';
1321    grppreavgnam{Nsen+1,sub} = fullfile(D.path,D.fname);
1322   end   % end sub
1323  end
1324 end
1325 
1326 % Review model-evidences (note cannot compare fused to individual modality
1327 % inversions, since data differs)
1328 for sub = 1:Nsub
1329    subnum = dosubs(sub);
1330    disp(sprintf('\tSub %d (%d)...',subnum,sub))
1331    for val=1:Nval
1332      disp(sprintf('\t\tModel-evidences (a.u.): %s',mat2str(round(squeeze(grp_mod_evd(sub,val,:))))))
1333    end
1334 end
1335 
1336 %%%%%%%%%%%%%%%%% Quick look at mean over subjects...
1337 
1338 clear S; S.con = [1 -1]; S.boi{1} = [140 190]; S.boi{2} = []; % boi{2}=[] is all freqs
1339 S.fig = lastfig;
1340 for val=1:Nval   % NB: Group inversion makes no difference for IID (val=2 here)
1341  S.val = val;
1342  for sen=1:(Nsen+fuseinvertflag)
1343   S.fig = S.fig+1;
1344   S.P = strvcat(grppreavgnam{sen,:});
1345   meg_inv_display_con(S);
1346   drawnow
1347  end
1348 end
1349 lastfig = S.fig;
1350 
1351 % The group fused results look a bit more focal than before, even though
1352 % gradiometer result look a bit less likely. Note that this is just the
1353 % mean over subjects, so a better test is statistics over subjects below...
1354 
1355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1356 %%%%%%%%%%%%%%%%% 3D  SPMs 
1357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 
1359 stdir = fullfile(wd,'GrpSourceSPMs');
1360 try cd(stdir); catch eval(sprintf('!mkdir %s',stdir)); end
1361 
1362 clear grpsubs imgfiles grpcons
1363 grpsubs{1} = [1:Nsub];
1364 % If want to split subjects, eg into two groups, eg:
1365 % grpsubs{1} = [1:4]; grpsubs{2} = [5:Nsub];
1366 grpcons = [1:2];
1367 Ngrp = length(grpsubs);
1368 for val=1:Nval   % NB: Group inversion makes no difference for IID (val=2 here)
1369  valdir = fullfile(stdir,sprintf('Inv%d',val));
1370  try cd(valdir); catch eval(sprintf('!mkdir %s',valdir)); end
1371  for sen = 1:(Nsen+fuseinvertflag)
1372   outdir = fullfile(valdir,sennam{sen})
1373   for grp = 1:Ngrp
1374    for sub = 1:length(grpsubs{grp});
1375     subnum = grpsubs{grp}(sub);
1376     imgfiles{grp}{sub} = GrpSourceImgs{sen}{val}{subnum}(grpcons,:);
1377    end
1378   end
1379   meg_batch_anova(imgfiles,outdir,'/imaging/local/spm/spm5/EEGtemplates/mni_mesh_cortex_8196.nii');
1380  end
1381 end
1382 cd(stdir)
1383 disp('!!!Review the group 3D stats if you wish!!!')
1384 
1385 %return
1386 
1387 % Again you need to know a bit about the SPM Results interface, but press
1388 % Results and select an SPM.mat file for one of the modalities and enter
1389 % a new T-contrast [1 -1] to find voxels in which greater source
1390 % amplitude for faces than scrambled faces, choose 0.001 uncorrected (not
1391 % much survives whole-image correction because only 8 subjects, so few
1392 % df's ie low power and RFT conservative) and then press "Volume" to get
1393 % table of stats. It will be very rough (speckled) because of the low
1394 % dfs. The results for mags, for example, seem better (eg more
1395 % suprathreshold voxels) for this group inversion than previously (above),
1396 % though it is less clear that the fused results are better following
1397 % group inversion of each modality alone (this is an area of current
1398 % investigation). You can decide not to use group inversion (or fusion)
1399 % of course. Again, all these statistical maps look better with more subjects, 
1400 % or when using SNPM or PPM's (see Henson et al, 2007, Neuroimage and
1401 % Taylor & Henson, in prep, for more information).
1402 
1403 
1404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405 %%%%%%%%%%%%%%%%% 3D  PPMs 
1406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407 
1408 % This uses SPMs above to calculate Posterior Probability Maps (PPMs),
1409 % which do not have any mutliple comparison issues (eg no need for RFT)
1410 % However, it will take a long time...
1411 
1412 for val=1:Nval   % NB: Group inversion makes no difference for IID (val=2 here)
1413  valdir = fullfile(stdir,sprintf('Inv%d',val));
1414  cd(valdir); 
1415  for sen = 1:(Nsen+fuseinvertflag)
1416   outdir = fullfile(valdir,sennam{sen})
1417   cd(outdir)
1418   load('SPM.mat');
1419   spm_spm_Bayes(SPM);
1420  end
1421 end
1422 disp('!!!Review the group 3D PPMs if you wish!!!')
1423 
1424 % Again you need to know a bit about the PPM Results interface, but press
1425 % Results and select an SPM.mat file for one of the modalities and enter
1426 % a new T-contrast [1 -1], but this time, select "Bayesian" rather than
1427 % "classical" when prompted. Then change the default effect size threshold 
1428 % to 0, and probability threshold to 0.99. This will show voxels with a
1429 % >99% probability of the increase for faces relative to scrambled being
1430 % greater than zero.
1431 
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 % adding fMRI priors (only really helps IID (MNM) inversions; little effect on MSP)
1434 
1435 fmri_grp_mod_evd=[];
1436 if fmriinvertflag
1437 
1438 % Create fMRI priors from an SPM image....
1439 % Here we assume a group prior in MNI space, but priors could be
1440 % defined separately for each subject based on their own fMRI data
1441 
1442  clear S
1443  S.D = grppreavgnam{1,sub};    % Take first subject/modality; doesnt really matter
1444  S.fmri = '/imaging/rh01/Methods/fMRIPriors/fMRI_ANOVA_flip0/UFvsS_05_cor_15.img';
1445  S.gm = '/imaging/local/spm/spm5/canonical/c1single_subj_T1.nii';
1446  S.space = 1;  % SPM and GM images are in MNI space
1447  S.hthr = 0.5;  S.ethr = 0;
1448  S.ncomp = Inf; S.smooth = 0.2;
1449  S.pflag = 1;
1450 
1451  D0 = spm_eeg_inv_fmripriors(S);
1452  fMRI = D0.inv{D0.val}.fmri.priors;   % Priors (cell of vectors)
1453   
1454  for sen=1:Nsen 
1455   clear DD
1456   for sub=1:Nsub
1457    DD{sub} = spm_eeg_ldata(preavgnam{sen,sub});
1458   end
1459   for val=1:Nval
1460    for sub=1:Nsub 
1461     DD{sub}.inv{val}.comment    = [DD{sub}.inv{val}.comment 'Group+fMRI priors'];
1462     DD{sub}.inv{val}.inverse.Nm = [];   % Reset any parameters from last inversion
1463     DD{sub}.inv{val}.inverse.Nr = [];   % Reset any parameters from last inversion
1464     DD{sub}.val = val;
1465     DD{sub}.inv{val}.inverse.pQ = fMRI;
1466    end
1467    
1468    DD = spm_eeg_invert(DD);
1469 
1470    % Save outputs
1471    for sub=1:Nsub
1472     D       = DD{sub};
1473     D.fname = [D.fname(1:(end-4)) '_grp_fmri.mat'];
1474     fmrigrppreavgnam{sen,sub} = fullfile(D.path, D.fname);
1475     save(fullfile(D.path, D.fname), 'D');
1476     fmri_grp_mod_evd(sub,val,sen) = D.inv{val}.inverse.F1(end);
1477     
1478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1479 
1480     D.inv{val}.contrast.woi  = contwin{val}{1};
1481     D.inv{val}.contrast.fboi = contwin{val}{2};
1482     D.inv{val}.contrast.type = conengy{val};
1483     D.val = val;
1484     D = spm_eeg_inv_results(D); 
1485     spm_eeg_inv_results_display(D); 
1486 
1487     if write3Dflag
1488      D.inv{val}.contrast.smooth = source_smooth_spm;
1489      D.inv{val}.contrast.rms = 1;
1490 %     D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1491      D = spm_eeg_inv_Mesh2Voxels(D);
1492      FmriGrpSourceImgs{sen}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1493     end 
1494     save(fullfile(D.path, D.fname), 'D');
1495    end % end val
1496   end % end sub
1497  end % end sen
1498  
1499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500 % Fuse using Group and fMRI priors (will take a long time!)
1501  if fuseinvertflag
1502   for sub=1:Nsub
1503    clear DD;
1504    for sen=1:Nsen
1505     DD{sen} = spm_eeg_ldata(fmrigrppreavgnam{sen,sub});
1506    end
1507    
1508    for val=1:Nval
1509     for sen=1:Nsen
1510      DD{sen}.val = val;
1511      DD{sen}.inv{val}.inverse.Nm = [];   % Reset any parameters from last inversion
1512      DD{sen}.inv{val}.inverse.Nr = [];   % Reset any parameters from last inversion
1513     % DD{sen}.inv{val}.inverse.QP = [];  % (Important not to reset the source priors QP from the grp inversion above)
1514      DD{sen}.inv{val}.inverse.OutExt = '_fused';
1515     end
1516     
1517     D = spm_eeg_invert_fuse(DD);  
1518     fmri_grp_mod_evd(sub,val,Nsen+1) = D.inv{val}.inverse.F1(end);
1519   
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Contrast
1521 
1522     D.inv{val}.contrast.woi  = contwin{val}{1};
1523     D.inv{val}.contrast.fboi = contwin{val}{2};
1524     D.inv{val}.contrast.type = conengy{val};
1525     D.val = val;
1526     D = spm_eeg_inv_results(D); 
1527     spm_eeg_inv_results_display(D); 
1528 
1529     if write3Dflag
1530      D.inv{val}.contrast.smooth = source_smooth_spm;
1531      D.inv{val}.contrast.rms = 1;
1532 %     D.inv{val}.contrast.scalefactor = 1;     % if want to compare across dif size windows
1533      D = spm_eeg_inv_Mesh2Voxels(D);
1534      FmriGrpSourceImgs{Nsen+1}{val}{sub} = strvcat(D.inv{val}.contrast.sfname{:});
1535     end
1536 
1537     save(fullfile(D.path, D.fname), 'D');
1538    end  % end val
1539 
1540    sennam{Nsen+1} = 'fused';
1541    fmrigrppreavgnam{Nsen+1,sub} = fullfile(D.path,D.fname);
1542   end
1543  end
1544 end
1545 
1546 
1547 % Review model-evidences (note cannot compare fused to individual modality
1548 % inversions, since data differs)
1549 for sub = 1:Nsub
1550    subnum = dosubs(sub);
1551    disp(sprintf('\tSub %d (%d)...',subnum,sub))
1552    for val=1:Nval
1553      disp(sprintf('\t\tModel-evidences (a.u.): %s',mat2str(round(squeeze(fmri_grp_mod_evd(sub,val,:))))))
1554    end
1555 end
1556 
1557 %%%%%%%%%%%%%%%%% Quick look at mean over subjects...
1558 
1559 clear S; S.con = [1 -1]; S.boi{1} = [140 190]; S.boi{2} = []; % boi{2}=[] is all freqs
1560 S.fig = lastfig;
1561 for val=1:Nval
1562  S.val = val;
1563  for sen=1:(Nsen+fuseinvertflag)
1564   S.fig = S.fig+1;
1565   S.P = strvcat(fmrigrppreavgnam{sen,:});
1566   meg_inv_display_con(S);
1567   drawnow
1568  end
1569 end
1570 lastfig = S.fig;
1571 
1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573 %%%%%%%%%%%%%%%%% 3D  SPMs 
1574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1575 
1576 stdir = fullfile(wd,'fMRIGrpSourceSPMs');
1577 try cd(stdir); catch eval(sprintf('!mkdir %s',stdir)); end
1578 
1579 clear grpsubs imgfiles grpcons
1580 grpsubs{1} = [1:Nsub];
1581 % If want to split subjects, eg into two groups, eg:
1582 % grpsubs{1} = [1:4]; grpsubs{2} = [5:Nsub];
1583 grpcons = [1:2];
1584 Ngrp = length(grpsubs);
1585 for val=1:Nval 
1586  valdir = fullfile(stdir,sprintf('Inv%d',val));
1587  try cd(valdir); catch eval(sprintf('!mkdir %s',valdir)); end
1588  for sen = 1:(Nsen+fuseinvertflag)
1589   outdir = fullfile(valdir,sennam{sen})
1590   for grp = 1:Ngrp
1591    for sub = 1:length(grpsubs{grp});
1592    subnum = grpsubs{grp}(sub);
1593    imgfiles{grp}{sub} = FmriGrpSourceImgs{sen}{val}{subnum}(grpcons,:);
1594    end
1595   end
1596   meg_batch_anova(imgfiles,outdir,'/imaging/local/spm/spm5/EEGtemplates/mni_mesh_cortex_8196.nii');
1597  end
1598 end
1599 cd(stdir)
1600 disp('!!!Review the group+fMRI 3D stats if you wish!!!')
1601 
1602 
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604 %%%%%%%%%%%%%%%%% 3D  PPMs 
1605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1606 
1607 % This uses SPMs above to calculate Posterior Probability Maps (PPMs),
1608 % which do not have any mutliple comparison issues (eg no need for RFT)
1609 % However, it will take a long time...
1610 
1611 for val=1:Nval 
1612  valdir = fullfile(stdir,sprintf('Inv%d',val));
1613  cd(valdir); 
1614  for sen = 1:(Nsen+fuseinvertflag)
1615   outdir = fullfile(valdir,sennam{sen})
1616   cd(outdir)
1617   load('SPM.mat');
1618   spm_spm_Bayes(SPM);
1619  end
1620 end
1621 disp('!!!Review the group+fMRI 3D PPMs if you wish!!!')
1622 
1623 
1624 % Phew! You got to here! Well done!

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2009-07-24 16:05:00, 69.8 KB) [[attachment:cbu_meeg_spm5_pipeline.m]]
  • [get | view] (2009-04-16 12:18:36, 64.2 KB) [[attachment:cbu_meeg_spm5_pipeline_13_4_09.m]]
  • [get | view] (2009-05-01 15:22:55, 64.4 KB) [[attachment:cbu_meeg_spm5_pipeline_24-7-09.m]]
  • [get | view] (2009-04-11 11:14:19, 51.7 KB) [[attachment:cbu_meeg_spm5_pipeline_5-3-09.m]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.