If you are processing data from multiple subjects or sessions, you might want to automate your preprocessing pipeline by writing a script. This can speed up your data processing and ensure that each datapoint has been processed with the same parameters.
To start your script we will use the _job.m file generated when we saved the batch we put together in the previous tutorial on the batch interface.
First, open this your preprocessing_batch_job.m file in MATLAB and inspect its contents. It should look something like this:
We will now add a for loop around this script. This will tell SPM to perform the same operation on all datasets that we specify in our loop.
The basic structure of a for loop in MATLAB is:
fori=1:10#youroperationsend
We will now use this structure to ask SPM to perform all preprocessing steps specified in our batch file on all selected datasets:
clearall% clear all variablesclc% clear command windowroot='/Users/spm/spm_tutorials/preprocessing/MoAEpilot/'% specify the directory where your data livessub={'sub-01'}% specify a list of subjects you want to process% this loop will perform preprocessing steps for all subjects specified in the list subfori=1:numel(sub)disp(['Starting preprocessing for ',sub{i}])% add a print statement to tell you which subject is being processedanat_dir=fullfile(root,sub{i},'anat')% this combines the root with a specific subject directory to create the full path to the folder containing anatomical datafunc_dir=fullfile(root,sub{i},'func')% this combines the root with a specific subject directory to create the full path to the folder containing functional data% find the structural fileanat=spm_select('FPList',anat_dir,'^sub-*.*_T1w.nii$')% this will return the full path (FP) to the T1 file from the anat directory%find and select the functional datafunc=spm_select('ExtFPList',func_dir,'^sub-*.*_task-auditory_bold.nii$',NaN)% this will give the full path to the task data, NaN will ensure you are loading all volumes present (i.e. consider the 4D file as a whole)cd(func_dir)% move into the subject specific folder containing the functional datamatlabbatch{1}.spm.spatial.realign.estwrite.data{1}=cellstr(func);% point the batch to the func variablematlabbatch{1}.spm.spatial.realign.estwrite.eoptions.quality=0.9;matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.sep=4;matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.fwhm=5;matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.rtm=1;matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.interp=2;matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.wrap=[000];matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.weight='';matlabbatch{1}.spm.spatial.realign.estwrite.roptions.which=[01];matlabbatch{1}.spm.spatial.realign.estwrite.roptions.interp=4;matlabbatch{1}.spm.spatial.realign.estwrite.roptions.wrap=[000];matlabbatch{1}.spm.spatial.realign.estwrite.roptions.mask=1;matlabbatch{1}.spm.spatial.realign.estwrite.roptions.prefix='r';matlabbatch{2}.spm.temporal.st.scans{1}(1)=cfg_dep('Realign: Estimate & Reslice: Realigned Images (Sess 1)',substruct('.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1}),substruct('.','sess','()',{1},'.','cfiles'));matlabbatch{2}.spm.temporal.st.nslices=64;matlabbatch{2}.spm.temporal.st.tr=7;matlabbatch{2}.spm.temporal.st.ta=6.890625;matlabbatch{2}.spm.temporal.st.so=[64636261605958575655545352515049484746454443424140393837363534333231302928272625242322212019181716151413121110987654321];matlabbatch{2}.spm.temporal.st.refslice=32;matlabbatch{2}.spm.temporal.st.prefix='a';matlabbatch{3}.spm.spatial.coreg.estimate.ref(1)=cfg_dep('Realign: Estimate & Reslice: Mean Image',substruct('.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1}),substruct('.','rmean'));matlabbatch{3}.spm.spatial.coreg.estimate.source=cellstr(anat);% point the batch to the anat variablematlabbatch{3}.spm.spatial.coreg.estimate.other={''};matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.cost_fun='nmi';matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.sep=[42];matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.tol=[0.020.020.020.0010.0010.0010.010.010.010.0010.0010.001];matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.fwhm=[77];matlabbatch{4}.spm.spatial.preproc.channel.vols(1)=cfg_dep('Coregister: Estimate: Coregistered Images',substruct('.','val','{}',{3},'.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1}),substruct('.','cfiles'));matlabbatch{4}.spm.spatial.preproc.channel.biasreg=0.001;matlabbatch{4}.spm.spatial.preproc.channel.biasfwhm=60;matlabbatch{4}.spm.spatial.preproc.channel.write=[01];matlabbatch{4}.spm.spatial.preproc.tissue(1).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,1')};matlabbatch{4}.spm.spatial.preproc.tissue(1).ngaus=1;matlabbatch{4}.spm.spatial.preproc.tissue(1).native=[10];matlabbatch{4}.spm.spatial.preproc.tissue(1).warped=[00];matlabbatch{4}.spm.spatial.preproc.tissue(2).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,2')};matlabbatch{4}.spm.spatial.preproc.tissue(2).ngaus=1;matlabbatch{4}.spm.spatial.preproc.tissue(2).native=[10];matlabbatch{4}.spm.spatial.preproc.tissue(2).warped=[00];matlabbatch{4}.spm.spatial.preproc.tissue(3).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,3')};matlabbatch{4}.spm.spatial.preproc.tissue(3).ngaus=2;matlabbatch{4}.spm.spatial.preproc.tissue(3).native=[10];matlabbatch{4}.spm.spatial.preproc.tissue(3).warped=[00];matlabbatch{4}.spm.spatial.preproc.tissue(4).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,4')};matlabbatch{4}.spm.spatial.preproc.tissue(4).ngaus=3;matlabbatch{4}.spm.spatial.preproc.tissue(4).native=[10];matlabbatch{4}.spm.spatial.preproc.tissue(4).warped=[00];matlabbatch{4}.spm.spatial.preproc.tissue(5).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,5')};matlabbatch{4}.spm.spatial.preproc.tissue(5).ngaus=4;matlabbatch{4}.spm.spatial.preproc.tissue(5).native=[10];matlabbatch{4}.spm.spatial.preproc.tissue(5).warped=[00];matlabbatch{4}.spm.spatial.preproc.tissue(6).tpm={fullfile(spm('Dir'),'tpm','TPM.nii,6')};matlabbatch{4}.spm.spatial.preproc.tissue(6).ngaus=2;matlabbatch{4}.spm.spatial.preproc.tissue(6).native=[00];matlabbatch{4}.spm.spatial.preproc.tissue(6).warped=[00];matlabbatch{4}.spm.spatial.preproc.warp.mrf=1;matlabbatch{4}.spm.spatial.preproc.warp.cleanup=1;matlabbatch{4}.spm.spatial.preproc.warp.reg=[00.0010.50.050.2];matlabbatch{4}.spm.spatial.preproc.warp.affreg='mni';matlabbatch{4}.spm.spatial.preproc.warp.fwhm=0;matlabbatch{4}.spm.spatial.preproc.warp.samp=3;matlabbatch{4}.spm.spatial.preproc.warp.write=[01];matlabbatch{4}.spm.spatial.preproc.warp.vox=NaN;matlabbatch{4}.spm.spatial.preproc.warp.bb=[NaNNaNNaNNaNNaNNaN];matlabbatch{5}.spm.spatial.normalise.write.subj.def(1)=cfg_dep('Segment: Forward Deformations',substruct('.','val','{}',{4},'.','val','{}',{1},'.','val','{}',{1}),substruct('.','fordef','()',{':'}));matlabbatch{5}.spm.spatial.normalise.write.subj.resample(1)=cfg_dep('Slice Timing: Slice Timing Corr. Images (Sess 1)',substruct('.','val','{}',{2},'.','val','{}',{1},'.','val','{}',{1}),substruct('()',{1},'.','files'));matlabbatch{5}.spm.spatial.normalise.write.woptions.bb=[-78-112-70787685];matlabbatch{5}.spm.spatial.normalise.write.woptions.vox=[333];matlabbatch{5}.spm.spatial.normalise.write.woptions.interp=4;matlabbatch{5}.spm.spatial.normalise.write.woptions.prefix='w';matlabbatch{6}.spm.spatial.smooth.data(1)=cfg_dep('Normalise: Write: Normalised Images (Subj 1)',substruct('.','val','{}',{5},'.','val','{}',{1},'.','val','{}',{1},'.','val','{}',{1}),substruct('()',{1},'.','files'));matlabbatch{6}.spm.spatial.smooth.fwhm=[666];matlabbatch{6}.spm.spatial.smooth.dtype=0;matlabbatch{6}.spm.spatial.smooth.im=0;matlabbatch{6}.spm.spatial.smooth.prefix='s';disp(['Completed preprocessing for ',sub{i}])% add a print statement telling you which subject has been processedsavepreprocessing_batchmatlabbatch% save the setup into a matfile called preprocessing_batch.matspm_jobman('run',matlabbatch)% execute the batchclearmatlabbatch% clear matlabbatchend