SPM12之fMRI批次預處理——NII檔案處理

z_s_s發表於2024-07-25

主要流程:Realignment、Slice Timing Correction、Coregistration、Segmentation、Normalization

程式碼地址:https://github.com/zhoushusheng/fMRI_preprocessing/blob/main/stupid_batch_nii_third_formal_compilable.m

引數設定參考:

1:上海外國網課https://www.bilibili.com/video/BV1ye4y1m72P/spm_id_from=333.880.my_history.page.click&vd_source=9b75cfd2936571e6bc329144e79be03e

2:Andy's brain book:https://andysbrainbook.readthedocs.io/en/latest/SPM/SPM_Short_Course/SPM_04_Preprocessing.html

%-----------------------------------------------------------------------
% Job saved on 02-Sep-2019 18:21:16 by cfg_util (rev $Rev: 6942 $)
% spm SPM - SPM12 (7219)
% cfg_basicio BasicIO - Unknown
%-----------------------------------------------------------------------
%%
% 這個m檔案用來執行spm的matlabbatch
% 該檔案中的檔案位置是基於linux系統的,如果是windows系統需要修改/為\
clear
% spm_path = '~\spm12';      %設定spm12的位置(這裡填的是安裝=spm12的絕對位置) 我這裡已經安裝好了
% addpath(spm_path);
spm('defaults', 'fmri');
spm_jobman('initcfg');

%%
subjectsdir = {'B:\fMRI\preprocess_for_batch\CN\'};% 這裡是data資料夾的絕對位置
subjects = {'sbj01','sbj02','sbj03','sbj04','sbj05','sbj06','sbj07','sbj08','sbj09','sbj10','sbj11','sbj12','sbj13','sbj14','sbj15','sbj16','sbj17','sbj18','sbj19','sbj20','sbj21','sbj22','sbj23','sbj24','sbj25'...
    ,'sbj26','sbj27','sbj28','sbj29','sbj30','sbj31','sbj32','sbj33','sbj34','sbj35','sbj36'};          % 單個或多個被試的資料夾
funcdir  =  fullfile('fMRI');              % 第一個Session的資料夾(由於preprocessing.mat中只新增了一個Session,所以這裡也只使用一個Session。)
%   F = fullfile(FOLDERNAME1, FOLDERNAME2, ..., FILENAME) builds a full
%   file specification F from the folders and file name specified. Input
%   arguments FOLDERNAME1, FOLDERNAME2, etc. and FILENAME can be strings,
%   character vectors, or cell arrays of character vectors. Non-scalar
%   strings and cell arrays of character vectors must all be the same size.

%   FULLFILE collapses inner repeated file separators unless they appear at 
%   the beginning of the full file specification. FULLFILE also collapses 
%   relative folders indicated by the dot symbol, unless they appear at 
%   the end of the full file specification. Relative folders indicated 
%   by the double-dot symbol are not collapsed.
%


% funcdir2  =  fullfile('Session2');             % 第二個Session的資料夾
anatdir =  fullfile('MRI');              % 結構像的資料夾

%%
% 設定基本的引數,在這裡設定方便後期修改
% head = spm_vol(sessionfiles{1});
% dimension = head.dim;
% slice_number = dimension(1,3);


% slice_number = 35;
% TR = 3;
% TA = TR-TR\slice_number;
% slice_order = [1:2:slice_number 2:2:slice_number];
% refslice1 = 35;
% voxel_size= [3.75 3.75 4];
% smoothing_kernel = [6 6 6];

%%
%每一個被試都建立一個工作流程

nsubj = length(subjects);   % 被試的數量
jobs = cell(nsubj,1);       % job的數量,每個被試一個job
nrun=1;  % session的數量
%ntimepoint=190;  %刪除了前面的10個時間點後剩餘的時間點
%%
for csubj = 24:36
    subjdir = {spm_select('CPath',subjects{csubj}, subjectsdir)};%Cpath 的c = canonical
    % 結構像資料夾
    adir =  spm_select('CPath', anatdir, subjdir);   %選擇當前被試(csubj)的結構像資料夾
    anatfile = strcat(spm_select('FPList', adir, '\\*.nii'),',1');   %在這個資料夾中.nii結尾的檔案,即結構像檔案 % As above, but return files with full paths (i.e. prefixes 'direc' to each)
    %如果沒有結構像檔案就報錯
    if isequal(anatfile,  '')
        warning(sprintf('No anat file found for %s', ...
            subjects{csubj}))
        return
    end
    % Session1資料夾
    fdir =  {spm_select('CPath', funcdir, subjdir)};    %選擇當前被試(csubj)的Session1資料夾
    ffiles = spm_select('List', fdir, '\\*.nii');   %選擇這個資料夾中所有.nii結尾的檔案,即Session1的所有原始功能像檔案
    %如果沒有功能像檔案就報錯
    nimage = size(ffiles,1);
    if nimage == 0
        warning(sprintf('No functional file found for %s', subjects{csubj}))
        return
    end

    cffiles = cellstr(ffiles);
    ntimepoint = length(cffiles);

    funcfiles = cell(1, nrun);
    sessionfiles = cell(nrun,ntimepoint);


    for i = 1:nrun
        for j = 1:ntimepoint
            sessionfiles{i,j}=strcat(fdir{1},'\',cffiles{j});   % 在這裡在每一個功能像檔案的絕對路徑後面新增,1
        end
        funcfiles{1,i} = {sessionfiles{i,:}}';    % 如果有多個Sessions,funcfiles中就會有多個sessionfiles
    end
    clear matlabbatch

    length(cffiles);
    head = spm_vol(sessionfiles{1});
    dimension = head.dim;
    descrip = head.descrip;

    slice_number = dimension(1,3);

    descrip={descrip};%char To cell
    TR = regexp(descrip,'(?<=TR=)\d+|(?<=TR=)\d+\.\d+','match','once');
    TR = str2double(TR);
    TR = TR / 1000;
    
    %如果沒有查到TR就報錯
    if isequal(TR,  '')
        warning(sprintf('No TR parameter found for %s', ...
            subjects{csubj}))
        return
    end

    TA = TR-TR/slice_number;
    
    %這個就得自己看了
%     slice_order = [1:2:slice_number 2:2:slice_number];
%     slice_order = [slice_number:-1:1];
    slice_order = [slice_number:-1:1];
    % preprocessing job
    display 'Creating preprocessing job'  %在matlab的命令列視窗顯示Creating preprocessing job
    
    matlabbatch{1}.spm.spatial.realign.estwrite.data = {funcfiles{1,1}(:,1)};%這裡不加1 也行 ,就是上面查詢的時候
    %%
    matlabbatch{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 = [0 0 0];
    matlabbatch{1}.spm.spatial.realign.estwrite.eoptions.weight = '';
    matlabbatch{1}.spm.spatial.realign.estwrite.roptions.which = [2 1];
    matlabbatch{1}.spm.spatial.realign.estwrite.roptions.interp = 4;
    matlabbatch{1}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0];
    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 = slice_number;
    matlabbatch{2}.spm.temporal.st.tr = TR;
    matlabbatch{2}.spm.temporal.st.ta = TA;
    matlabbatch{2}.spm.temporal.st.so = slice_order;
    matlabbatch{2}.spm.temporal.st.refslice = slice_number/2;
    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 = {anatfile};%ananfile 字串末尾得加一個1,細看對比stupid_batch_nii_third_formal_compilable
    matlabbatch{3}.spm.spatial.coreg.estimate.other = {''};
    matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';
    matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];
    matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];
    matlabbatch{3}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];
    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 = [0 1];
    matlabbatch{4}.spm.spatial.preproc.tissue(1).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,1'};
    matlabbatch{4}.spm.spatial.preproc.tissue(1).ngaus = 1;
    matlabbatch{4}.spm.spatial.preproc.tissue(1).native = [1 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(1).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(2).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,2'};
    matlabbatch{4}.spm.spatial.preproc.tissue(2).ngaus = 1;
    matlabbatch{4}.spm.spatial.preproc.tissue(2).native = [1 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(2).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(3).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,3'};
    matlabbatch{4}.spm.spatial.preproc.tissue(3).ngaus = 2;
    matlabbatch{4}.spm.spatial.preproc.tissue(3).native = [1 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(3).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(4).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,4'};
    matlabbatch{4}.spm.spatial.preproc.tissue(4).ngaus = 3;
    matlabbatch{4}.spm.spatial.preproc.tissue(4).native = [1 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(4).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(5).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,5'};
    matlabbatch{4}.spm.spatial.preproc.tissue(5).ngaus = 4;
    matlabbatch{4}.spm.spatial.preproc.tissue(5).native = [1 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(5).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(6).tpm = {'C:\Program Files\MATLAB\R2021b\toolbox\spm12\tpm\TPM.nii,6'};
    matlabbatch{4}.spm.spatial.preproc.tissue(6).ngaus = 2;
    matlabbatch{4}.spm.spatial.preproc.tissue(6).native = [0 0];
    matlabbatch{4}.spm.spatial.preproc.tissue(6).warped = [0 0];
    matlabbatch{4}.spm.spatial.preproc.warp.mrf = 1;
    matlabbatch{4}.spm.spatial.preproc.warp.cleanup = 1;
    matlabbatch{4}.spm.spatial.preproc.warp.reg = [0 0.001 0.5 0.05 0.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 = [0 1];
    matlabbatch{4}.spm.spatial.preproc.warp.vox = NaN;
    matlabbatch{4}.spm.spatial.preproc.warp.bb = [NaN NaN NaN
                                                  NaN NaN NaN];
    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('Realign: Estimate & Reslice: Resliced Images (Sess 1)', substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','sess', '()',{1}, '.','rfiles'));
    matlabbatch{5}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70
                                                              78 76 85];
    matlabbatch{5}.spm.spatial.normalise.write.woptions.vox = [2 2 2];
    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 = [8 8 8];
    matlabbatch{6}.spm.spatial.smooth.dtype = 0;
    matlabbatch{6}.spm.spatial.smooth.im = 0;
    matlabbatch{6}.spm.spatial.smooth.prefix = 's';

    
    % 儲存matlabbatch
    matfile = sprintf('preprocess_nii_%s.mat', subjects{csubj});
%     save(matfile,'matlabbatch');
    jobs{csubj} = matfile;  %jobs這個變數中儲存了所有被試的matlabbatch
    ['Start preprocessing job' num2str(csubj)]
    

    spm_jobman('run', matlabbatch);
end

%%
% 執行預處理的工作
% for csubj = 15:20
%     display 'Start preprocessing job'   %在matlab的命令列視窗顯示Start preprocessing job
%     load(jobs{csubj});
%     spm_jobman('run', matlabbatch);
% end

  

相關文章