diff --git a/.github/workflows/run_system_tests.yml b/.github/workflows/run_system_tests.yml index 88c96be0..9ae64cf0 100644 --- a/.github/workflows/run_system_tests.yml +++ b/.github/workflows/run_system_tests.yml @@ -58,8 +58,7 @@ jobs: - name: Update octave path run: | - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'lib'))); savepath();" - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'src'))); savepath();" + octave $OCTFLAGS --eval "initCppSpm; savepath();" - name: Prepare data run: | diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index f45c7522..6fbd99b0 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -62,8 +62,8 @@ jobs: - name: Update octave path run: | - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'lib'))); savepath();" - octave $OCTFLAGS --eval "addpath(genpath(fullfile(pwd, 'src'))); savepath();" + octave $OCTFLAGS --eval "initCppSpm; savepath();" + octave $OCTFLAGS --eval "addpath(fullfile(pwd, 'tests', 'utils')); savepath();" - name: Prepare data run: | diff --git a/demos/openneuro/ds000001_run.m b/demos/openneuro/ds000001_run.m index 38d9a18e..75bf98a4 100644 --- a/demos/openneuro/ds000001_run.m +++ b/demos/openneuro/ds000001_run.m @@ -9,12 +9,7 @@ FWHM = 6; conFWHM = 6; -% directory with this script becomes the current directory -WD = fileparts(mfilename('fullpath')); - -% we add all the subfunctions that are in the sub directories -addpath(genpath(fullfile(WD, '..', '..', 'src'))); -addpath(genpath(fullfile(WD, '..', '..', 'lib'))); +initCppSpm(); %% Set options opt = ds000001_getOption(); diff --git a/demos/openneuro/ds000114_run.m b/demos/openneuro/ds000114_run.m index 0c72597d..ad3c9366 100644 --- a/demos/openneuro/ds000114_run.m +++ b/demos/openneuro/ds000114_run.m @@ -9,12 +9,7 @@ FWHM = 6; conFWHM = 6; -% directory with this script becomes the current directory -WD = fileparts(mfilename('fullpath')); - -% we add all the subfunctions that are in the sub directories -addpath(genpath(fullfile(WD, '..', '..', 'src'))); -addpath(genpath(fullfile(WD, '..', '..', 'lib'))); +initCppSpm(); %% Set options opt = ds000114_getOption(); diff --git a/demos/openneuro/ds001168_run.m b/demos/openneuro/ds001168_run.m index e8ab780c..26f3b406 100644 --- a/demos/openneuro/ds001168_run.m +++ b/demos/openneuro/ds001168_run.m @@ -8,12 +8,7 @@ % Smoothing to apply FWHM = 6; -% directory with this script becomes the current directory -WD = fileparts(mfilename('fullpath')); - -% we add all the subfunctions that are in the sub directories -addpath(genpath(fullfile(WD, '..', '..', 'src'))); -addpath(genpath(fullfile(WD, '..', '..', 'lib'))); +initCppSpm(); %% Set options opt = ds001168_getOption(); diff --git a/demos/spm_face_rep/face_rep_run.m b/demos/spm_face_rep/face_rep_run.m index 5ea3695e..23a1885f 100644 --- a/demos/spm_face_rep/face_rep_run.m +++ b/demos/spm_face_rep/face_rep_run.m @@ -26,9 +26,7 @@ % directory with this script becomes the current directory WD = fileparts(mfilename('fullpath')); -% we add all the subfunctions that are in the sub directories -addpath(genpath(fullfile(WD, '..', '..', 'src'))); -addpath(genpath(fullfile(WD, '..', '..', 'lib'))); +initCppSpm(); %% Set options opt = FaceRep_getOption(); diff --git a/initCppSpm.m b/initCppSpm.m index 788688e8..dbf73369 100644 --- a/initCppSpm.m +++ b/initCppSpm.m @@ -7,6 +7,11 @@ function initCppSpm() % we add all the subfunctions that are in the sub directories addpath(genpath(fullfile(WD, 'src'))); - addpath(genpath(fullfile(WD, 'lib'))); + addpath(genpath(fullfile(WD, 'lib', 'mancoreg'))); + addpath(genpath(fullfile(WD, 'lib', 'NiftiTools'))); + addpath(genpath(fullfile(WD, 'lib', 'spmup'))); + addpath(genpath(fullfile(WD, 'lib', 'utils'))); + + addpath(fullfile(WD, 'lib', 'bids-matlab')); end diff --git a/src/QA/anatomicalQA.m b/src/QA/anatomicalQA.m index 25d70fa9..c147602d 100644 --- a/src/QA/anatomicalQA.m +++ b/src/QA/anatomicalQA.m @@ -23,43 +23,37 @@ function anatomicalQA(opt) end opt = loadAndCheckOptions(opt); - [group, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); fprintf(1, ' ANATOMICAL: QUALITY CONTROL\n\n'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subID = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subID); - subID = group(iGroup).subNumber{iSub}; + [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); - printProcessingSubject(groupName, iSub, subID); + % get grey and white matter tissue probability maps + TPMs = validationInputFile(anatDataDir, anatImage, 'c[12]'); - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + % sanity check that all images are in the same space. + anatImage = fullfile(anatDataDir, anatImage); + volumesToCheck = {anatImage; TPMs(1, :); TPMs(2, :)}; + spm_check_orientations(spm_vol(char(volumesToCheck))); - % get grey and white matter tissue probability maps - TPMs = validationInputFile(anatDataDir, anatImage, 'c[12]'); + % Basic QA for anatomical data is to get SNR, CNR, FBER and Entropy + % This is useful to check coregistration worked fine + anatQA = spmup_anatQA(anatImage, TPMs(1, :), TPMs(2, :)); %#ok<*NASGU> - % sanity check that all images are in the same space. - anatImage = fullfile(anatDataDir, anatImage); - volumesToCheck = {anatImage; TPMs(1, :); TPMs(2, :)}; - spm_check_orientations(spm_vol(char(volumesToCheck))); + anatQA.avgDistToSurf = spmup_comp_dist2surf(anatImage); - % Basic QA for anatomical data is to get SNR, CNR, FBER and Entropy - % This is useful to check coregistration worked fine - anatQA = spmup_anatQA(anatImage, TPMs(1, :), TPMs(2, :)); %#ok<*NASGU> + spm_jsonwrite( ... + strrep(anatImage, '.nii', '_qa.json'), ... + anatQA, ... + struct('indent', ' ')); - anatQA.avgDistToSurf = spmup_comp_dist2surf(anatImage); - - spm_jsonwrite( ... - strrep(anatImage, '.nii', '_qa.json'), ... - anatQA, ... - struct('indent', ' ')); - - end end end diff --git a/src/QA/functionalQA.m b/src/QA/functionalQA.m index f804344b..fa356499 100644 --- a/src/QA/functionalQA.m +++ b/src/QA/functionalQA.m @@ -35,106 +35,99 @@ function functionalQA(opt) end opt = loadAndCheckOptions(opt); - [group, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); fprintf(1, ' FUNCTIONAL: QUALITY CONTROL\n\n'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subID = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subID); - subID = group(iGroup).subNumber{iSub}; + % get grey and white matter and csf tissue probability maps + [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + TPMs = validationInputFile(anatDataDir, anatImage, 'rc[123]'); - printProcessingSubject(groupName, iSub, subID); + % load metrics from anat QA + anatQA = spm_jsonread( ... + fullfile( ... + anatDataDir, ... + strrep(anatImage, '.nii', '_qa.json'))); - % get grey and white matter and csf tissue probability maps - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); - TPMs = validationInputFile(anatDataDir, anatImage, 'rc[123]'); + [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); - % load metrics from anat QA - anatQA = spm_jsonread( ... - fullfile( ... - anatDataDir, ... - strrep(anatImage, '.nii', '_qa.json'))); + for iSes = 1:nbSessions - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + % get all runs for that subject across all sessions + [runs, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); - for iSes = 1:nbSessions + for iRun = 1:nbRuns - % get all runs for that subject across all sessions - [runs, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + % get the filename for this bold run for this task + [fileName, subFuncDataDir] = getBoldFilename( ... + BIDS, ... + subID, ... + sessions{iSes}, ... + runs{iRun}, ... + opt); - for iRun = 1:nbRuns + prefix = getPrefix('funcQA', opt); + funcImage = validationInputFile(subFuncDataDir, fileName, prefix); - % get the filename for this bold run for this task - [fileName, subFuncDataDir] = getBoldFilename( ... - BIDS, ... - subID, ... - sessions{iSes}, ... - runs{iRun}, ... - opt); + % sanity check that all images are in the same space. + volumesToCheck = {funcImage; TPMs(1, :); TPMs(2, :); TPMs(3, :)}; + spm_check_orientations(spm_vol(char(volumesToCheck))); - prefix = getPrefix('funcQA', opt); - funcImage = validationInputFile(subFuncDataDir, fileName, prefix); + fMRIQA = computeFuncQAMetrics(funcImage, TPMs, anatQA.avgDistToSurf, opt); - % sanity check that all images are in the same space. - volumesToCheck = {funcImage; TPMs(1, :); TPMs(2, :); TPMs(3, :)}; - spm_check_orientations(spm_vol(char(volumesToCheck))); + % TODO + % find an ouput format that is leaner than a 3 Gb json file!!! + % spm_jsonwrite( ... + % fullfile( ... + % subFuncDataDir, ... + % strrep(fileName, '.nii', '_qa.json')), ... + % fMRIQA, ... + % struct('indent', ' ')); + % save( ... + % fullfile( ... + % subFuncDataDir, ... + % strrep(fileName, '.nii', '_qa.mat')), ... + % 'fMRIQA'); - fMRIQA = computeFuncQAMetrics(funcImage, TPMs, anatQA.avgDistToSurf, opt); + outputFiles = spmup_first_level_qa( ... + funcImage, ... + 'Voltera', 'on', ... + 'Radius', anatQA.avgDistToSurf); - % TODO - % find an ouput format that is leaner than a 3 Gb json file!!! - % spm_jsonwrite( ... - % fullfile( ... - % subFuncDataDir, ... - % strrep(fileName, '.nii', '_qa.json')), ... - % fMRIQA, ... - % struct('indent', ' ')); - % save( ... - % fullfile( ... - % subFuncDataDir, ... - % strrep(fileName, '.nii', '_qa.mat')), ... - % 'fMRIQA'); + movefile( ... + fullfile(subFuncDataDir, 'spmup_QC.ps'), ... + fullfile(subFuncDataDir, strrep(fileName, '.nii', '_qa.ps'))); - outputFiles = spmup_first_level_qa( ... - funcImage, ... - 'Voltera', 'on', ... - 'Radius', anatQA.avgDistToSurf); + confounds = load(outputFiles.design); - movefile( ... - fullfile(subFuncDataDir, 'spmup_QC.ps'), ... - fullfile(subFuncDataDir, strrep(fileName, '.nii', '_qa.ps'))); + spm_save( ... + fullfile( ... + subFuncDataDir, ... + strrep(fileName, ... + '_bold.nii', ... + '_desc-confounds_regressors.tsv')), ... + confounds); - confounds = load(outputFiles.design); + delete(outputFiles.design); - spm_save( ... - fullfile( ... - subFuncDataDir, ... - strrep(fileName, ... - '_bold.nii', ... - '_desc-confounds_regressors.tsv')), ... - confounds); + createDataDictionary(subFuncDataDir, fileName, size(confounds, 2)); - delete(outputFiles.design); - - createDataDictionary(subFuncDataDir, fileName, size(confounds, 2)); - - % create carpet plot - - % horrible hack to prevent the "abrupt" way spmup_volumecorr crashes - % if nansum is not there - if exist('nansum', 'file') == 2 - spmup_timeseriesplot(funcImage, TPMs(1, :), TPMs(2, :), TPMs(3, :), ... - 'motion', 'on', ... - 'nuisances', 'on', ... - 'correlation', 'on', ... - 'makefig', 'on'); - end + % create carpet plot + % horrible hack to prevent the "abrupt" way spmup_volumecorr crashes + % if nansum is not there + if exist('nansum', 'file') == 2 + spmup_timeseriesplot(funcImage, TPMs(1, :), TPMs(2, :), TPMs(3, :), ... + 'motion', 'on', ... + 'nuisances', 'on', ... + 'correlation', 'on', ... + 'makefig', 'on'); end end diff --git a/src/batches/setBatchCoregistrationFmap.m b/src/batches/setBatchCoregistrationFmap.m index ca220f41..cdf5ab90 100644 --- a/src/batches/setBatchCoregistrationFmap.m +++ b/src/batches/setBatchCoregistrationFmap.m @@ -1,20 +1,20 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subLabel) % % Set the batch for the coregistration of field maps % % USAGE:: % - % matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subID) + % matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subLabel) % % :param BIDS: BIDS layout returned by ``getData``. % :type BIDS: structure % :param opt: structure or json filename containing the options. See % ``checkOptions()`` and ``loadAndCheckOptions()``. % :type opt: structure - % :param subID: subject ID - % :type subID: string + % :param subLabel: + % :type subLabel: string % % :returns: - :matlabbatch: (structure) The matlabbatch ready to run the spm job % @@ -26,23 +26,23 @@ % Use a rough mean of the 1rst run to improve SNR for coregistration % created by spmup - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1}); - [fileName, subFuncDataDir] = getBoldFilename(BIDS, subID, sessions{1}, runs{1}, opt); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{1}); + [fileName, subFuncDataDir] = getBoldFilename(BIDS, subLabel, sessions{1}, runs{1}, opt); refImage = validationInputFile(subFuncDataDir, fileName, 'mean_'); for iSes = 1:nbSessions runs = bids.query(BIDS, 'runs', ... 'modality', 'fmap', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', sessions{iSes}); for iRun = 1:numel(runs) metadata = bids.query(BIDS, 'metadata', ... 'modality', 'fmap', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', sessions{iSes}, ... 'run', runs{iRun}); @@ -50,7 +50,7 @@ fmapFiles = bids.query(BIDS, 'data', ... 'modality', 'fmap', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', sessions{iSes}, ... 'run', runs{iRun}); diff --git a/src/batches/setBatchCoregistrationFuncToAnat.m b/src/batches/setBatchCoregistrationFuncToAnat.m index f1b54fe5..b9bc7dfa 100644 --- a/src/batches/setBatchCoregistrationFuncToAnat.m +++ b/src/batches/setBatchCoregistrationFuncToAnat.m @@ -1,6 +1,6 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subLabel) % % Set the batch for corregistering the functional images to the % anatomical image @@ -16,8 +16,8 @@ % :param opt: structure or json filename containing the options. See % ``checkOptions()`` and ``loadAndCheckOptions()``. % :type opt: structure - % :param subID: subject ID - % :type subID: string + % :param subLabel: subject ID + % :type subLabel: string % % :returns: - :matlabbatch: (structure) The matlabbatch ready to run the spm job % @@ -53,14 +53,14 @@ % OTHER IMAGES : DEPENDENCY FROM REALIGNEMENT - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); runCounter = 1; for iSes = 1:nbSessions % get all runs for that subject for this session - [~, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + [~, nbRuns] = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); for iRun = 1:nbRuns diff --git a/src/batches/setBatchFactorialDesign.m b/src/batches/setBatchFactorialDesign.m index f183b9d4..ec5c9262 100644 --- a/src/batches/setBatchFactorialDesign.m +++ b/src/batches/setBatchFactorialDesign.m @@ -28,7 +28,7 @@ smoothPrefix = ['s', num2str(conFWHM)]; end - [group, opt] = getData(opt); + [~, opt] = getData(opt); rfxDir = getRFXdir(opt, funcFWHM, conFWHM); @@ -54,34 +54,27 @@ mkdir(directory); - % For each group - for iGroup = 1:length(group) + icell(1).levels = 1; %#ok<*AGROW> - groupName = group(iGroup).name; + for iSub = 1:numel(opt.subjects) - icell(iGroup).levels = iGroup; %#ok<*AGROW> + subLabel = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + % FFX directory and load SPM.mat of that subject + ffxDir = getFFXdir(subLabel, funcFWHM, opt); + load(fullfile(ffxDir, 'SPM.mat')); - printProcessingSubject(groupName, iSub, subID); + % find which contrast of that subject has the name of the contrast we + % want to bring to the group level + conIdx = find(strcmp({SPM.xCon.name}, conName)); + fileName = sprintf('con_%0.4d.nii', conIdx); + file = validationInputFile(ffxDir, fileName, smoothPrefix); - % FFX directory and load SPM.mat of that subject - ffxDir = getFFXdir(subID, funcFWHM, opt); - load(fullfile(ffxDir, 'SPM.mat')); + icell(1).scans(iSub, :) = {file}; - % find which contrast of that subject has the name of the contrast we - % want to bring to the group level - conIdx = find(strcmp({SPM.xCon.name}, conName)); - fileName = sprintf('con_%0.4d.nii', conIdx); - file = validationInputFile(ffxDir, fileName, smoothPrefix); - - icell(iGroup).scans(iSub, :) = {file}; - - fprintf(1, ' %s\n\n', file); - - end + fprintf(1, ' %s\n\n', file); end diff --git a/src/batches/setBatchMeanAnatAndMask.m b/src/batches/setBatchMeanAnatAndMask.m index bd845192..41839db5 100644 --- a/src/batches/setBatchMeanAnatAndMask.m +++ b/src/batches/setBatchMeanAnatAndMask.m @@ -2,7 +2,7 @@ function matlabbatch = setBatchMeanAnatAndMask(matlabbatch, opt, funcFWHM, outputDir) % - % Creates batxh to create mean anatomical image and a grop mask + % Creates batxh to create mean anatomical image and a group mask % % USAGE:: % @@ -19,42 +19,37 @@ % :returns: - :matlabbatch: (structure) % - [group, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); printBatchName('create mean anatomical image and mask'); inputAnat = {}; inputMask = {}; - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + %% Anat + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); - printProcessingSubject(groupName, iSub, subID); + anatImage = validationInputFile( ... + anatDataDir, ... + anatImage, ... + [spm_get_defaults('normalise.write.prefix'), ... + spm_get_defaults('deformations.modulate.prefix')]); - %% Anat - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + inputAnat{end + 1, 1} = anatImage; %#ok<*AGROW> - anatImage = validationInputFile( ... - anatDataDir, ... - anatImage, ... - [spm_get_defaults('normalise.write.prefix'), ... - spm_get_defaults('deformations.modulate.prefix')]); + %% Mask + ffxDir = getFFXdir(subLabel, funcFWHM, opt); - inputAnat{end + 1, 1} = anatImage; %#ok<*AGROW> + files = validationInputFile(ffxDir, 'mask.nii'); - %% Mask - ffxDir = getFFXdir(subID, funcFWHM, opt); + inputMask{end + 1, 1} = files; - files = validationInputFile(ffxDir, 'mask.nii'); - - inputMask{end + 1, 1} = files; - - end end %% Generate the equation to get the mean of the mask and structural image diff --git a/src/batches/setBatchRealign.m b/src/batches/setBatchRealign.m index e509008e..a911aa12 100644 --- a/src/batches/setBatchRealign.m +++ b/src/batches/setBatchRealign.m @@ -6,7 +6,11 @@ % % USAGE:: % - % [matlabbatch, voxDim] = setBatchRealign(matlabbatch, [action = 'realign'], BIDS, opt, subID) + % [matlabbatch, voxDim] = setBatchRealign(matlabbatch, ... + % [action = 'realign'], ... + % BIDS, ... + % opt, ... + % subLabel) % % :param matlabbatch: SPM batch % :type matlabbatch: structure @@ -16,8 +20,8 @@ % :type action: string % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure - % :type subID: string - % :param subID: subject label + % :type subLabel: string + % :param subLabel: subject label % % :returns: - :matlabbatch: (structure) (dimension) % - :voxDim: (array) (dimension) @@ -26,10 +30,10 @@ % make which image is resliced more consistent 'which = []' if numel(varargin) < 5 - [matlabbatch, BIDS, opt, subID] = deal(varargin{:}); + [matlabbatch, BIDS, opt, subLabel] = deal(varargin{:}); action = ''; else - [matlabbatch, action, BIDS, opt, subID] = deal(varargin{:}); + [matlabbatch, action, BIDS, opt, subLabel] = deal(varargin{:}); end if isempty(action) @@ -61,21 +65,21 @@ printBatchName(msg); - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); runCounter = 1; for iSes = 1:nbSessions % get all runs for that subject across all sessions - [runs, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + [runs, nbRuns] = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); for iRun = 1:nbRuns % get the filename for this bold run for this task [boldFilename, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, ... + subLabel, ... sessions{iSes}, ... runs{iRun}, ... opt); diff --git a/src/batches/setBatchSTC.m b/src/batches/setBatchSTC.m index 473687dd..0d4d9658 100644 --- a/src/batches/setBatchSTC.m +++ b/src/batches/setBatchSTC.m @@ -1,6 +1,6 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel) % % Creates batch for slice timing correction % @@ -49,6 +49,10 @@ nbSlices = length(sliceOrder); % unique is necessary in case of multi echo TR = opt.metadata.RepetitionTime; TA = TR - (TR / nbSlices); + % round acquisition time to the upper millisecond + % mostly to avoid having errors when checking: + % any(sliceOrder > TA) + TA = ceil(TA * 1000) / 1000; maxSliceTime = max(sliceOrder); minSliceTime = min(sliceOrder); @@ -83,21 +87,21 @@ matlabbatch{end}.spm.temporal.st.so = sliceOrder * 1000; matlabbatch{end}.spm.temporal.st.refslice = referenceSlice * 1000; - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); runCounter = 1; for iSes = 1:nbSessions % get all runs for that subject for this session - [runs, nbRuns] = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + [runs, nbRuns] = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); for iRun = 1:nbRuns % get the filename for this bold run for this task [fileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{iSes}, runs{iRun}, opt); + subLabel, sessions{iSes}, runs{iRun}, opt); % check that the file with the right prefix exist file = validationInputFile(subFuncDataDir, fileName); diff --git a/src/batches/setBatchSaveCoregistrationMatrix.m b/src/batches/setBatchSaveCoregistrationMatrix.m index 82212043..ab9fb872 100644 --- a/src/batches/setBatchSaveCoregistrationMatrix.m +++ b/src/batches/setBatchSaveCoregistrationMatrix.m @@ -1,6 +1,6 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subLabel) % % Short description of what the function does goes here. % @@ -14,8 +14,8 @@ % :type BIDS: structure % :param opt: % :type opt: Options chosen for the analysis. See ``checkOptions()``. - % :param subID: - % :type subID: + % :param subLabel: + % :type subLabel: string % % :returns: - :matlabbatch: % @@ -24,11 +24,11 @@ % create name of the output file based on the name of the first image of the % first session - sessions = getInfo(BIDS, subID, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1}); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{1}); [fileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{1}, runs{1}, opt); + subLabel, sessions{1}, runs{1}, opt); fileName = strrep(fileName, '_bold.nii', '_from-scanner_to-T1w_mode-image_xfm.mat'); diff --git a/src/batches/setBatchSelectAnat.m b/src/batches/setBatchSelectAnat.m index cb60668f..e8e11bd1 100644 --- a/src/batches/setBatchSelectAnat.m +++ b/src/batches/setBatchSelectAnat.m @@ -1,6 +1,6 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subLabel) % % Creates a batch to set an anatomical image % @@ -15,8 +15,8 @@ % :param opt: structure or json filename containing the options. See % ``checkOptions()`` and ``loadAndCheckOptions()``. % :type opt: structure - % :param subID: subject ID - % :type subID: string + % :param subLabel: subject label + % :type subLabel: string % % :returns: :matlabbatch: (structure) % @@ -29,7 +29,7 @@ printBatchName('selecting anatomical image'); - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); matlabbatch{end + 1}.cfg_basicio.cfg_named_file.name = 'Anatomical'; matlabbatch{end}.cfg_basicio.cfg_named_file.files = { {fullfile(anatDataDir, anatImage)} }; diff --git a/src/batches/setBatchSkullStripping.m b/src/batches/setBatchSkullStripping.m index 286b65a6..52166108 100644 --- a/src/batches/setBatchSkullStripping.m +++ b/src/batches/setBatchSkullStripping.m @@ -1,13 +1,13 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subID) +function matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel) % % Creates a batch to compute a brain mask based on the tissue probability maps % from the segmentation. % % USAGE:: % - % matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subID) + % matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel) % % :param matlabbatch: list of SPM batches % :type matlabbatch: structure @@ -16,8 +16,8 @@ % :param opt: structure or json filename containing the options. See % ``checkOptions()`` and ``loadAndCheckOptions()``. % :type opt: structure - % :param subID: subject ID - % :type subID: string + % :param subLabel: subject ID + % :type subLabel: string % % :returns: - :matlabbatch: (structure) The matlabbatch ready to run the spm job % @@ -36,7 +36,7 @@ printBatchName('skull stripping'); - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); output = ['m' strrep(anatImage, '.nii', '_skullstripped.nii')]; expression = sprintf('i1.*((i2+i3+i4)>%f)', opt.skullstrip.threshold); diff --git a/src/batches/setBatchSmoothConImages.m b/src/batches/setBatchSmoothConImages.m index 8e19b61c..9e8d6dd0 100644 --- a/src/batches/setBatchSmoothConImages.m +++ b/src/batches/setBatchSmoothConImages.m @@ -1,6 +1,6 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSmoothConImages(matlabbatch, group, opt, funcFWHM, conFWHM) +function matlabbatch = setBatchSmoothConImages(matlabbatch, opt, funcFWHM, conFWHM) % % Creates a batch to smooth all the con images of all subjects % @@ -24,29 +24,22 @@ printBatchName('smoothing contrast images'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subNumber = group(iGroup).subNumber{iSub}; + ffxDir = getFFXdir(subLabel, funcFWHM, opt); - printProcessingSubject(groupName, iSub, subNumber); + conImg = spm_select('FPlist', ffxDir, '^con*.*nii$'); + data = cellstr(conImg); - ffxDir = getFFXdir(subNumber, funcFWHM, opt); - - conImg = spm_select('FPlist', ffxDir, '^con*.*nii$'); - data = cellstr(conImg); - - matlabbatch = setBatchSmoothing( ... - matlabbatch, ... - data, ... - conFWHM, ... - [spm_get_defaults('smooth.prefix'), num2str(conFWHM)]); - - end + matlabbatch = setBatchSmoothing( ... + matlabbatch, ... + data, ... + conFWHM, ... + [spm_get_defaults('smooth.prefix'), num2str(conFWHM)]); end diff --git a/src/batches/setBatchSubjectLevelContrasts.m b/src/batches/setBatchSubjectLevelContrasts.m index ad971576..593d4973 100644 --- a/src/batches/setBatchSubjectLevelContrasts.m +++ b/src/batches/setBatchSubjectLevelContrasts.m @@ -1,19 +1,19 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subID, funcFWHM) +function matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subLabel, funcFWHM) % % Short description of what the function does goes here. % % USAGE:: % - % matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subID, funcFWHM) + % matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subLabel, funcFWHM) % % :param matlabbatch: % :type matlabbatch: structure % :param opt: % :type opt: structure - % :param subID: - % :type subID: string + % :param subLabel: + % :type subLabel: string % :param funcFWHM: % :type funcFWHM: % @@ -22,7 +22,7 @@ printBatchName('subject level contrasts specification'); - ffxDir = getFFXdir(subID, funcFWHM, opt); + ffxDir = getFFXdir(subLabel, funcFWHM, opt); spmMatFile = cellstr(fullfile(ffxDir, 'SPM.mat')); diff --git a/src/batches/setBatchSubjectLevelGLMSpec.m b/src/batches/setBatchSubjectLevelGLMSpec.m index 2b353d61..65688901 100644 --- a/src/batches/setBatchSubjectLevelGLMSpec.m +++ b/src/batches/setBatchSubjectLevelGLMSpec.m @@ -6,7 +6,7 @@ % % USAGE:: % - % matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subID, funcFWHM) + % matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel, funcFWHM) % % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet, % consectetur adipiscing elit. Ut congue nec est ac lacinia. @@ -19,7 +19,7 @@ % - :argout2: (type) (dimension) % - [matlabbatch, BIDS, opt, subID, funcFWHM] = deal(varargin{:}); + [matlabbatch, BIDS, opt, subLabel, funcFWHM] = deal(varargin{:}); printBatchName('specify subject level fmri model'); @@ -34,7 +34,7 @@ % slice in the first bold image to set the number of time bins % we will use to upsample our model during regression creation fileName = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'type', 'bold'); fileName = strrep(fileName{1}, '.gz', ''); hdr = spm_vol(fileName); @@ -64,7 +64,7 @@ % Create ffxDir if it doesnt exist % If it exists, issue a warning that it has been overwritten - ffxDir = getFFXdir(subID, funcFWHM, opt); + ffxDir = getFFXdir(subLabel, funcFWHM, opt); if exist(ffxDir, 'dir') % warning('overwriting directory: %s \n', ffxDir); rmdir(ffxDir, 's'); @@ -87,20 +87,20 @@ % matlabbatch{end}.spm.stats.fmri_spec.cvi = 'AR(1)'; % identify sessions for this subject - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); sesCounter = 1; for iSes = 1:nbSessions % get all runs for that subject across all sessions [runs, nbRuns] = ... - getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); for iRun = 1:nbRuns % get functional files [fullpathBoldFileName, prefix] = ... - getBoldFilenameForFFX(BIDS, opt, subID, funcFWHM, iSes, iRun); + getBoldFilenameForFFX(BIDS, opt, subLabel, funcFWHM, iSes, iRun); disp(fullpathBoldFileName); @@ -108,12 +108,12 @@ {fullpathBoldFileName}; % get stimuli onset time file - tsvFile = getInfo(BIDS, subID, opt, 'filename', ... + tsvFile = getInfo(BIDS, subLabel, opt, 'filename', ... sessions{iSes}, ... runs{iRun}, ... 'events'); fullpathOnsetFileName = createAndReturnOnsetFile(opt, ... - subID, ... + subLabel, ... tsvFile, ... funcFWHM); diff --git a/src/batches/setBatchSubjectLevelResults.m b/src/batches/setBatchSubjectLevelResults.m index 0b5cd0f9..1f8aa354 100644 --- a/src/batches/setBatchSubjectLevelResults.m +++ b/src/batches/setBatchSubjectLevelResults.m @@ -12,8 +12,8 @@ % :type matlabbatch: structure % :param opt: % :type opt: structure - % :param subID: - % :type subID: string + % :param subLabel: + % :type subLabel: string % :param funcFWHM: % :type funcFWHM: float % :param iStep: @@ -24,7 +24,7 @@ % :returns: - :matlabbatch: (structure) % - [matlabbatch, opt, subID, funcFWHM, iStep, iCon] = deal(varargin{:}); + [matlabbatch, opt, subLabel, funcFWHM, iStep, iCon] = deal(varargin{:}); result.Contrasts = opt.result.Steps(iStep).Contrasts(iCon); @@ -33,8 +33,8 @@ end result.space = opt.space; - result.dir = getFFXdir(subID, funcFWHM, opt); - result.label = subID; + result.dir = getFFXdir(subLabel, funcFWHM, opt); + result.label = subLabel; result.nbSubj = 1; result.contrastNb = getContrastNb(result); diff --git a/src/getAnatFilename.m b/src/getAnatFilename.m index 74b83485..03a21add 100644 --- a/src/getAnatFilename.m +++ b/src/getAnatFilename.m @@ -1,6 +1,6 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt) +function [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt) % % Short description of what the function does goes here. % @@ -18,7 +18,7 @@ % :returns: - :argout1: (type) (dimension) % - :argout2: (type) (dimension) % - % [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt) + % [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt) % % Get the filename and the directory of an anat file for a given session / % run. @@ -26,27 +26,27 @@ anatType = opt.anatReference.type; - sessions = getInfo(BIDS, subID, opt, 'Sessions'); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); % get all anat images for that subject fo that type % TODO allow for the session to be referenced by a string e.g ses-retest anat = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'type', anatType); if ~isempty(opt.anatReference.session) anatSession = opt.anatReference.session; anat = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', sessions{anatSession}, ... 'type', anatType); end if isempty(anat) anat = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'type', anatType); error('No anat file for the subject %s. Here are all anat file:\n%s', ... - subID, ... + subLabel, ... char(anat)); end diff --git a/src/getData.m b/src/getData.m index d28da2b2..c0dca3d6 100644 --- a/src/getData.m +++ b/src/getData.m @@ -1,12 +1,12 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function [group, opt, BIDS] = getData(opt, BIDSdir, type) +function [BIDS, opt] = getData(opt, BIDSdir, type) % - % Short description of what the function does goes here. + % Reads the specified BIDS data set and updates the list of subjects to analyze. % % USAGE:: % - % [group, opt, BIDS] = getData(opt, [BIDSdir], [type = 'bold']) + % [BIDS, opt] = getData(opt, [BIDSdir], [type = 'bold']) % % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure @@ -17,41 +17,10 @@ % supported: ``'bold'`` (default) and ``T1w`` % :type type: string % - % :returns: - :group: (structure) + % :returns: % - :opt: (structure) % - :BIDS: (structure) % - % ``getData()`` reads the specified BIDS data set and gets the groups and - % subjects to analyze. This can be specified in the opt structure in different ways. - % - % Set the group of subjects to analyze:: - % - % opt.groups = {'control', 'blind'}; - % - % If there are no groups (i.e subjects names are of the form ``sub-01`` for - % example) or if you want to run all subjects of all groups then use:: - % - % opt.groups = {''}; - % opt.subjects = {[]}; - % - % If you have 2 groups (``cont`` and ``cat`` for example) the following will - % run ``cont01``, ``cont02``, ``cat03``, ``cat04``:: - % - % opt.groups = {'cont', 'cat'}; - % opt.subjects = {[1 2], [3 4]}; - % - % If you have more than 2 groups but want to only run the subjects of 2 - % groups then you can use:: - % - % opt.groups = {'cont', 'cat'}; - % opt.subjects = {[], []}; - % - % You can also directly specify the subject label for the participants you - % want to run:: - % - % opt.groups = {''}; - % opt.subjects = {'01', 'cont01', 'cat02', 'ctrl02', 'blind01'}; - % % .. todo % Check if the following is true? Ideally write a test to make sure. % @@ -88,43 +57,15 @@ end % get IDs of all subjects - subjects = bids.query(BIDS, 'subjects'); + opt = getSubjectList(BIDS, opt); % get metadata for bold runs for that task % we take those from the first run of the first subject assuming it can % apply to all others. - opt = getMetaData(BIDS, opt, subjects, type); - - %% Add the different groups in the experiment - for iGroup = 1:numel(opt.groups) % for each group - - clear idx; - - % Name of the group - group(iGroup).name = opt.groups{iGroup}; %#ok<*AGROW> - - group = getSpecificSubjects(opt, group, iGroup, subjects); + opt = getMetaData(BIDS, opt, opt.subjects, type); - % check that all the subjects asked for exist - if ~all(ismember(group(iGroup).subNumber, subjects)) - fprintf('subjects specified\n'); - disp(group(iGroup).subNumber); - fprintf('subjects present\n'); - disp(subjects); - - errorStruct.identifier = 'getData:noMatchingSubject'; - msg = ['Some of the subjects specified do not exist in this data set.' ... - 'This can be due to wrong zero padding: see opt.zeropad in getOptions']; - errorStruct.message = msg; - error(errorStruct); - end - - % Number of subjects in the group - group(iGroup).numSub = length(group(iGroup).subNumber); - - fprintf(1, 'WILL WORK ON SUBJECTS\n'); - disp(group(iGroup).subNumber); - end + fprintf(1, 'WILL WORK ON SUBJECTS\n'); + disp(opt.subjects); end diff --git a/src/getFuncVoxelDims.m b/src/getFuncVoxelDims.m index 99c825b2..296398fc 100644 --- a/src/getFuncVoxelDims.m +++ b/src/getFuncVoxelDims.m @@ -6,19 +6,20 @@ % % USAGE:: % - % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3]) + % [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, fileName) % % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure - % :param argin2: optional argument and its default value. And some of the - % options can be shown in litteral like ``this`` or ``that``. - % :type argin2: string - % :param argin3: (dimension) optional argument + % :param subFuncDataDir: + % :type subFuncDataDir: + % :param prefix: + % :type prefix: + % :param fileName: + % :type fileName: % - % :returns: - :argout1: (type) (dimension) - % - :argout2: (type) (dimension) + % :returns: - :voxDim: + % - :opt: % - % [voxDim, opt] = getFuncVoxelDims(opt, subFuncDataDir, prefix, fileName) % % diff --git a/src/getInfo.m b/src/getInfo.m index 8e56ef5a..01bbe415 100644 --- a/src/getInfo.m +++ b/src/getInfo.m @@ -1,22 +1,22 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function varargout = getInfo(BIDS, subID, opt, info, varargin) +function varargout = getInfo(BIDS, subLabel, opt, info, varargin) % % Wrapper function to fetch specific info in a BIDS structure returned by % spm_bids. % % USAGE:: % - % varargout = getInfo(BIDS, subID, opt, info, varargin) + % varargout = getInfo(BIDS, subLabel, opt, info, varargin) % % :param BIDS: (structure) returned by bids.query when exploring a BIDS data set. - % :param subID: ID of the subject + % :param subLabel: ID of the subject % :param opt: (structure) Mostly used to find the task name. % :param info: (strint) ``sessions``, ``runs``, ``filename``. % :param varargin: see below % - % - subID - ID of the subject ; in BIDS lingo that means that for a file name - % ``sub-02_task-foo_bold.nii`` the subID will be the string ``02`` + % - subLabel - ID of the subject ; in BIDS lingo that means that for a file name + % ``sub-02_task-foo_bold.nii`` the subLabel will be the string ``02`` % - session - ID of the session of interes ; in BIDS lingo that means that for a file name % ``sub-02_ses-pretest_task-foo_bold.nii`` the sesssion will be the string % ``pretest`` @@ -41,7 +41,7 @@ case 'sessions' sessions = bids.query(BIDS, 'sessions', ... - 'sub', subID, ... + 'sub', subLabel, ... 'task', opt.taskName); nbSessions = size(sessions, 2); if nbSessions == 0 @@ -56,7 +56,7 @@ session = varargin{1}; runs = bids.query(BIDS, 'runs', ... - 'sub', subID, ... + 'sub', subLabel, ... 'task', opt.taskName, ... 'ses', session, ... 'type', 'bold'); @@ -74,7 +74,7 @@ [session, run, type] = deal(varargin{:}); varargout = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'run', run, ... 'ses', session, ... 'task', opt.taskName, ... diff --git a/src/getMeanFuncFilename.m b/src/getMeanFuncFilename.m index 98297502..b9057cc6 100644 --- a/src/getMeanFuncFilename.m +++ b/src/getMeanFuncFilename.m @@ -1,36 +1,29 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subID, opt) +function [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subLabel, opt) % - % Short description of what the function does goes here. + % Get the filename and the directory of an mean functional file. % % USAGE:: % - % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3]) + % [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subLabel, opt) % - % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet, - % consectetur adipiscing elit. Ut congue nec est ac lacinia. - % :type argin1: type - % :param argin2: optional argument and its default value. And some of the - % options can be shown in litteral like ``this`` or ``that``. - % :type argin2: string + % :param BIDS: + % :type BIDS: structure + % :param subLabel: + % :type subLabel: string % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure % - % :returns: - :argout1: (type) (dimension) - % - :argout2: (type) (dimension) + % :returns: - :meanImage: (string) + % - :meanFuncDir: (string) % - % [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt) - % - % Get the filename and the directory of an anat file for a given session / - % run. - % Unzips the file if necessary. - sessions = getInfo(BIDS, subID, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1}); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{1}); [boldFileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{1}, runs{1}, opt); + subLabel, sessions{1}, runs{1}, opt); prefix = getPrefix('mean', opt); diff --git a/src/getPrefix.m b/src/getPrefix.m index e99d41cc..5c8c334b 100644 --- a/src/getPrefix.m +++ b/src/getPrefix.m @@ -2,25 +2,23 @@ function [prefix, motionRegressorPrefix] = getPrefix(step, opt, funcFWHM) % - % Short description of what the function does goes here. + % Generates prefix to append to file name to look for % % USAGE:: % - % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3]) + % [prefix, motionRegressorPrefix] = getPrefix(step, opt, funcFWHM) % - % :param argin1: (dimension) obligatory argument. Lorem ipsum dolor sit amet, - % consectetur adipiscing elit. Ut congue nec est ac lacinia. - % :type argin1: type + % :param step: + % :type step: string % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure - % :param argin3: (dimension) optional argument + % :param funcFWHM: + % :type funcFWHM: scalar % - % :returns: - :argout1: (type) (dimension) - % - :argout2: (type) (dimension) + % :returns: - :prefix: + % - :motionRegressorPrefix: % - % [prefix, motionRegressorPrefix] = getPrefix(step, opt, funcFWHM) % - % generates prefix to append to file name to look for if nargin < 3 funcFWHM = 0; diff --git a/src/getSpecificSubjects.m b/src/getSpecificSubjects.m deleted file mode 100644 index 0314deaa..00000000 --- a/src/getSpecificSubjects.m +++ /dev/null @@ -1,61 +0,0 @@ -% (C) Copyright 2020 CPP BIDS SPM-pipeline developers - -function group = getSpecificSubjects(opt, group, iGroup, subjects) - % - % Short description of what the function does goes here. - % - % USAGE:: - % - % [argout1, argout2] = templateFunction(argin1, [argin2 == default,] [argin3]) - % - % :param opt: Options chosen for the analysis. See ``checkOptions()``. - % :type opt: structure - % :param argin2: optional argument and its default value. And some of the - % options can be shown in litteral like ``this`` or ``that``. - % :type argin2: string - % :param argin3: (dimension) optional argument - % - % :returns: - :argout1: (type) (dimension) - % - :argout2: (type) (dimension) - % - % add a test for ata set with subject only blind02 and we ask for this one - % specifically - - % if no group or subject was specified we take all of them - if numel(opt.groups) == 1 && ... - strcmp(group(iGroup).name, '') && ... - isempty(opt.subjects{iGroup}) - - group(iGroup).subNumber = subjects; - - % if subject ID were directly specified by users we take those - elseif strcmp(group(iGroup).name, '') && iscellstr(opt.subjects) - - group(iGroup).subNumber = opt.subjects; - - % if group was specified we figure out which subjects to take - elseif ~isempty(opt.subjects{iGroup}) - - idx = opt.subjects{iGroup}; - - % else we take all subjects of that group - elseif isempty(opt.subjects{iGroup}) - - % count how many subjects in that group - idx = sum(~cellfun(@isempty, strfind(subjects, group(iGroup).name))); - idx = 1:idx; - - else - - error('Not sure what to do.'); - - end - - % if only indices were specified we get the subject from that group with that - if exist('idx', 'var') - pattern = [group(iGroup).name '%0' num2str(opt.zeropad) '.0f_']; - temp = strsplit(sprintf(pattern, idx), '_'); - group(iGroup).subNumber = temp(1:end - 1); - end - -end diff --git a/src/reports/copyFigures.m b/src/reports/copyFigures.m index 607aecd1..04bcce9f 100644 --- a/src/reports/copyFigures.m +++ b/src/reports/copyFigures.m @@ -1,29 +1,29 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function copyFigures(BIDS, opt, subID) +function copyFigures(BIDS, opt, subLabel) % % Copy the figures from spatial preprocessing into a separate folder. % % USAGE:: % - % copyFigures(BIDS, opt, subID) + % copyFigures(BIDS, opt, subLabel) % % :param BIDS: BIDS layout returned by ``getData``. % :type BIDS: structure % :param opt: Options chosen for the analysis. See ``checkOptions()``. % :type opt: structure - % :param subID: Subject label (for example `'01'`). - % :type subID: string + % :param subLabel: Subject label (for example `'01'`). + % :type subLabel: string % % - imgNb = copyGraphWindownOutput(opt, subID, 'realign'); + imgNb = copyGraphWindownOutput(opt, subLabel, 'realign'); % loop through the figures outputed for unwarp: one per run if opt.realign.useUnwarp runs = bids.query(BIDS, 'runs', ... - 'sub', subID, ... + 'sub', subLabel, ... 'task', opt.taskName, ... 'type', 'bold'); @@ -32,10 +32,10 @@ function copyFigures(BIDS, opt, subID) nbRuns = 1; end - imgNb = copyGraphWindownOutput(opt, subID, 'unwarp', imgNb:(imgNb + nbRuns - 1)); + imgNb = copyGraphWindownOutput(opt, subLabel, 'unwarp', imgNb:(imgNb + nbRuns - 1)); end - imgNb = copyGraphWindownOutput(opt, subID, 'func2anatCoreg', imgNb); %#ok + imgNb = copyGraphWindownOutput(opt, subLabel, 'func2anatCoreg', imgNb); %#ok end diff --git a/src/utils/getSubjectList.m b/src/utils/getSubjectList.m new file mode 100644 index 00000000..75d05ef1 --- /dev/null +++ b/src/utils/getSubjectList.m @@ -0,0 +1,88 @@ +% (C) Copyright 2021 CPP BIDS SPM-pipeline developers + +function opt = getSubjectList(BIDS, opt) + % + % Returns the subjects to analyze in ``opt.subjects`` + % + % USAGE:: + % + % opt = getSubjectList(BIDS, opt) + % + % :param opt: Options chosen for the analysis. See ``checkOptions()``. + % :type opt: structure + % :param BIDSdir: the directory where the data is ; default is : + % ``fullfile(opt.dataDir, '..', 'derivatives', 'cpp_spm')`` + % :type BIDSdir: string + % + % :returns: + % - :opt: (structure) + % + % To set set the groups of subjects to analyze:: + % + % opt.groups = {'control', 'blind'}; + % + % If there are no groups (i.e subjects names are of the form ``sub-01`` for + % example) or if you want to run all subjects of all groups then use:: + % + % opt.groups = {''}; + % opt.subjects = {[]}; + % + % If you have more than 2 groups but want to only run the subjects of 2 + % groups then you can use:: + % + % opt.groups = {'cont', 'cat'}; + % opt.subjects = {[], []}; + % + % You can also directly specify the subject label for the participants you + % want to run:: + % + % opt.groups = {''}; + % opt.subjects = {'01', 'cont01', 'cat02', 'ctrl02', 'blind01'}; + + allSubjects = bids.query(BIDS, 'subjects'); + + % Whatever subject entered must be returned "linearized" + tmp = opt.subjects; + tmp = tmp(:); + + % if any group is mentioned + if ~isempty(opt.groups{1}) && ... + any(strcmpi({'group'}, fieldnames(BIDS.participants))) + + fields = fieldnames(BIDS.participants); + fieldIdx = strcmpi({'group'}, fields); + + subjectIdx = strcmp(BIDS.participants.(fields{fieldIdx}), opt.groups); + + subjects = char(BIDS.participants.participant_id); + subjects = cellstr(subjects(subjectIdx, 5:end)); + + tmp = cat(1, tmp, subjects); + + end + + % If no subject specified so far we take all subjects + if isempty(tmp) || iscell(tmp) && isempty(tmp{1}) + tmp = allSubjects; + end + + % remove duplicates + opt.subjects = unique(tmp); + + if size(opt.subjects, 1) == 1 + opt.subjects = opt.subjects'; + end + + % check that all the subjects asked for exist + if any(~ismember(opt.subjects, allSubjects)) + fprintf('subjects specified\n'); + disp(opt.subjects); + fprintf('subjects present\n'); + disp(allSubjects); + + errorStruct.identifier = 'getSubjectList:noMatchingSubject'; + errorStruct.message = 'Some of the subjects specified do not exist in this data set.'; + error(errorStruct); + end + +end diff --git a/src/utils/printProcessingSubject.m b/src/utils/printProcessingSubject.m index cb5a27a5..a0668d42 100644 --- a/src/utils/printProcessingSubject.m +++ b/src/utils/printProcessingSubject.m @@ -1,11 +1,10 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function printProcessingSubject(groupName, iSub, subID) +function printProcessingSubject(iSub, subLabel) fprintf(1, [ ... - ' PROCESSING GROUP: %s' ... - 'SUBJECT No.: %i ' ... + ' PROCESSING SUBJECT No.: %i ' ... 'SUBJECT ID : %s \n'], ... - groupName, iSub, subID); + iSub, subLabel); end diff --git a/src/workflows/bidsConcatBetaTmaps.m b/src/workflows/bidsConcatBetaTmaps.m index b2a6ff46..dc757327 100644 --- a/src/workflows/bidsConcatBetaTmaps.m +++ b/src/workflows/bidsConcatBetaTmaps.m @@ -22,55 +22,51 @@ function bidsConcatBetaTmaps(opt, funcFWHM, deleteIndBeta, deleteIndTmaps) deleteIndTmaps = 1; end - [~, opt, group] = setUpWorkflow(opt, 'merge beta images and t-maps'); + [~, opt] = setUpWorkflow(opt, 'merge beta images and t-maps'); - % clear previous matlabbatch and files - matlabbatch = []; RT = 0; - %% Loop through the groups, subjects - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - for iSub = 1:group(iGroup).numSub + subLabel = opt.subjects{iSub}; - subID = group(iGroup).subNumber{iSub}; + printProcessingSubject(iSub, subLabel); - ffxDir = getFFXdir(subID, funcFWHM, opt); + ffxDir = getFFXdir(subLabel, funcFWHM, opt); - contrasts = specifyContrasts(ffxDir, opt.taskName, opt); + contrasts = specifyContrasts(ffxDir, opt.taskName, opt); - beta_maps = cell(length(contrasts), 1); - t_maps = cell(length(contrasts), 1); + beta_maps = cell(length(contrasts), 1); + t_maps = cell(length(contrasts), 1); - % path to beta and t-map files. - for iContrast = 1:length(beta_maps) - % Note that the betas are created from the idx (Beta_idx(iBeta)) - fileName = sprintf('beta_%04d.nii', find(contrasts(iContrast).C)); - fileName = validationInputFile(ffxDir, fileName); - beta_maps{iContrast, 1} = [fileName, ',1']; + % path to beta and t-map files. + for iContrast = 1:length(beta_maps) + % Note that the betas are created from the idx (Beta_idx(iBeta)) + fileName = sprintf('beta_%04d.nii', find(contrasts(iContrast).C)); + fileName = validationInputFile(ffxDir, fileName); + beta_maps{iContrast, 1} = [fileName, ',1']; - % while the contrastes (t-maps) are not from the index. They were created - fileName = sprintf('spmT_%04d.nii', iContrast); - fileName = validationInputFile(ffxDir, fileName); - t_maps{iContrast, 1} = [fileName, ',1']; - end + % while the contrastes (t-maps) are not from the index. They were created + fileName = sprintf('spmT_%04d.nii', iContrast); + fileName = validationInputFile(ffxDir, fileName); + t_maps{iContrast, 1} = [fileName, ',1']; + end - % beta maps - outputName = ['4D_beta_', num2str(funcFWHM), '.nii']; + % beta maps + outputName = ['4D_beta_', num2str(funcFWHM), '.nii']; - matlabbatch = []; - matlabbatch = setBatch3Dto4D(matlabbatch, beta_maps, RT, outputName); + matlabbatch = []; + matlabbatch = setBatch3Dto4D(matlabbatch, beta_maps, RT, outputName); - % t-maps - outputName = ['4D_t_maps_', num2str(funcFWHM), '.nii']; + % t-maps + outputName = ['4D_t_maps_', num2str(funcFWHM), '.nii']; - matlabbatch = setBatch3Dto4D(matlabbatch, t_maps, RT, outputName); + matlabbatch = setBatch3Dto4D(matlabbatch, t_maps, RT, outputName); - saveAndRunWorkflow(matlabbatch, 'concat_betaImg_tMaps', opt, subID); + saveAndRunWorkflow(matlabbatch, 'concat_betaImg_tMaps', opt, subLabel); - removeBetaImgTmaps(t_maps, deleteIndBeta, deleteIndTmaps, ffxDir); + removeBetaImgTmaps(t_maps, deleteIndBeta, deleteIndTmaps, ffxDir); - end end end diff --git a/src/workflows/bidsCopyRawFolder.m b/src/workflows/bidsCopyRawFolder.m index f59a6391..e647e77e 100644 --- a/src/workflows/bidsCopyRawFolder.m +++ b/src/workflows/bidsCopyRawFolder.m @@ -66,54 +66,50 @@ function bidsCopyRawFolder(opt, deleteZippedNii, modalitiesToCopy, unZip) copyTsvJson(rawDir, derivativesDir); %% Loop through the groups, subjects, sessions - [group, opt, BIDS] = getData(opt, rawDir); + [BIDS, opt] = getData(opt, rawDir); - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - for iSub = 1:group(iGroup).numSub + subLabel = opt.subjects{iSub}; - subID = group(iGroup).subNumber{iSub}; + subDir = returnSubjectDir(subLabel); - subDir = returnSubjectDir(subID); + fprintf('copying subject: %s \n', subDir); - fprintf('copying subject: %s \n', subDir); + [~, ~, ~] = mkdir(fullfile(derivativesDir, subDir)); - [~, ~, ~] = mkdir(fullfile(derivativesDir, subDir)); + % copy scans.tsv files + copyTsvJson( ... + fullfile(rawDir, subDir), ... + fullfile(derivativesDir, subDir)); - % copy scans.tsv files - copyTsvJson( ... - fullfile(rawDir, subDir), ... - fullfile(derivativesDir, subDir)); + [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); - [sessions, nbSessions] = getInfo(BIDS, subID, opt, 'Sessions'); + %% copy the whole subject's folder + % use a call to system cp function to use the derefence option (-L) + % to get the data 'out' of an eventual datalad dataset - %% copy the whole subject's folder - % use a call to system cp function to use the derefence option (-L) - % to get the data 'out' of an eventual datalad dataset + for iSes = 1:nbSessions - for iSes = 1:nbSessions + sessionDir = returnSessionDir(sessions{iSes}); - sessionDir = returnSessionDir(sessions{iSes}); + fprintf(' copying session: %s \n', sessionDir); - fprintf(' copying session: %s \n', sessionDir); + [~, ~, ~] = mkdir(fullfile(derivativesDir, subDir, sessionDir)); - [~, ~, ~] = mkdir(fullfile(derivativesDir, subDir, sessionDir)); - - % copy scans.tsv files - copyTsvJson( ... - fullfile(rawDir, subDir, sessionDir), ... - fullfile(derivativesDir, subDir, sessionDir)); + % copy scans.tsv files + copyTsvJson( ... + fullfile(rawDir, subDir, sessionDir), ... + fullfile(derivativesDir, subDir, sessionDir)); - modalities = bids.query(BIDS, 'modalities', ... - 'sub', subID, ... - 'ses', sessions{iSes}); - modalities = intersect(modalities, modalitiesToCopy); + modalities = bids.query(BIDS, 'modalities', ... + 'sub', subLabel, ... + 'ses', sessions{iSes}); + modalities = intersect(modalities, modalitiesToCopy); - copyModalities(BIDS, opt, modalities, subID, sessions{iSes}); + copyModalities(BIDS, opt, modalities, subLabel, sessions{iSes}); - end end - end if unZip @@ -131,9 +127,9 @@ function bidsCopyRawFolder(opt, deleteZippedNii, modalitiesToCopy, unZip) end -function subDir = returnSubjectDir(subID) +function subDir = returnSubjectDir(subLabel) - subDir = ['sub-', subID]; + subDir = ['sub-', subLabel]; end @@ -164,11 +160,11 @@ function copyTsvJson(srcDir, targetDir) end -function copyModalities(BIDS, opt, modalities, subID, session) +function copyModalities(BIDS, opt, modalities, subLabel, session) [rawDir, derivativesDir] = returnRawAndDerivativeDir(opt); - subDir = returnSubjectDir(subID); + subDir = returnSubjectDir(subLabel); sessionDir = returnSessionDir(session); @@ -189,7 +185,7 @@ function copyModalities(BIDS, opt, modalities, subID, session) if strcmp(modalities{iModality}, 'func') files = bids.query(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', session, ... 'task', opt.taskName); @@ -253,8 +249,8 @@ function unzipFiles(derivativesDir, deleteZippedNii, opt) % for bold, physio and stim files, we only unzip the files of the task of % interest - if any(strcmp(fragments.type, {'bold', 'stim', 'physio'})) && ... - isfield(fragments, 'task') && strcmp(fragments.task, opt.taskName) + if any(strcmp(fragments.type, {'bold', 'stim'})) && ... + isfield(fragments, 'task') && strcmp(fragments.task, opt.taskName) % load the nifti image and saves the functional data as unzipped nii n = load_untouch_nii(file); diff --git a/src/workflows/bidsCreateVDM.m b/src/workflows/bidsCreateVDM.m index b06b1e7e..baf622a1 100644 --- a/src/workflows/bidsCreateVDM.m +++ b/src/workflows/bidsCreateVDM.m @@ -25,45 +25,39 @@ function bidsCreateVDM(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'create voxel displacement map'); + [BIDS, opt] = setUpWorkflow(opt, 'create voxel displacement map'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + % TODO Move to getInfo + types = bids.query(BIDS, 'types', 'sub', subLabel); - subID = group(iGroup).subNumber{iSub}; + if any(ismember(types, {'phase12', 'phasediff', 'fieldmap', 'epi'})) - % TODO Move to getInfo - types = bids.query(BIDS, 'types', 'sub', subID); + printProcessingSubject(iSub, subLabel); - if any(ismember(types, {'phase12', 'phasediff', 'fieldmap', 'epi'})) + % Create rough mean of the 1rst run to improve SNR for coregistration + % TODO use the slice timed EPI if STC was used ? + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{1}); + [fileName, subFuncDataDir] = getBoldFilename(BIDS, subLabel, sessions{1}, runs{1}, opt); + spmup_basics(fullfile(subFuncDataDir, fileName), 'mean'); - printProcessingSubject(groupName, iSub, subID); + matlabbatch = []; + matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subLabel); + saveAndRunWorkflow(matlabbatch, 'coregister_fmap', opt, subLabel); - % Create rough mean of the 1rst run to improve SNR for coregistration - % TODO use the slice timed EPI if STC was used ? - sessions = getInfo(BIDS, subID, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{1}); - [fileName, subFuncDataDir] = getBoldFilename(BIDS, subID, sessions{1}, runs{1}, opt); - spmup_basics(fullfile(subFuncDataDir, fileName), 'mean'); + matlabbatch = []; + matlabbatch = setBatchCreateVDMs(matlabbatch, BIDS, opt, subLabel); + saveAndRunWorkflow(matlabbatch, 'create_vdm', opt, subLabel); - matlabbatch = []; - matlabbatch = setBatchCoregistrationFmap(matlabbatch, BIDS, opt, subID); - saveAndRunWorkflow(matlabbatch, 'coregister_fmap', opt, subID); - - matlabbatch = []; - matlabbatch = setBatchCreateVDMs(matlabbatch, BIDS, opt, subID); - saveAndRunWorkflow(matlabbatch, 'create_vdm', opt, subID); - - % TODO - % delete temporary mean images ?? - - end + % TODO + % delete temporary mean images ?? end end + end diff --git a/src/workflows/bidsFFX.m b/src/workflows/bidsFFX.m index 3ad26a53..e6e75db6 100644 --- a/src/workflows/bidsFFX.m +++ b/src/workflows/bidsFFX.m @@ -32,70 +32,61 @@ function bidsFFX(action, opt, funcFWHM) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'subject level GLM'); + [BIDS, opt] = setUpWorkflow(opt, 'subject level GLM'); if isempty(opt.model.file) opt = createDefaultModel(BIDS, opt); end - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + matlabbatch = []; - printProcessingSubject(groupName, iSub, subID); + switch action - matlabbatch = []; + case 'specifyAndEstimate' - switch action + matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel, funcFWHM); + matlabbatch = setBatchPrintFigure(matlabbatch, [ ... + 'sub-', subLabel, ... + '_task-', opt.taskName, ... + '_design_before_estimation']); + matlabbatch = setBatchEstimateModel(matlabbatch, opt); + matlabbatch = setBatchPrintFigure(matlabbatch, [ ... + 'sub-', subLabel, ... + '_task-', opt.taskName, ... + '_design_after_estimation']); - case 'specifyAndEstimate' + batchName = ... + ['specify_estimate_ffx_task-', opt.taskName, ... + '_space-', opt.space, ... + '_FWHM-', num2str(funcFWHM)]; - matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subID, funcFWHM); - matlabbatch = setBatchPrintFigure(matlabbatch, [ ... - 'sub-', subID, ... - '_task-', opt.taskName, ... - '_design_before_estimation']); - matlabbatch = setBatchEstimateModel(matlabbatch, opt); - matlabbatch = setBatchPrintFigure(matlabbatch, [ ... - 'sub-', subID, ... - '_task-', opt.taskName, ... - '_design_after_estimation']); + saveAndRunWorkflow(matlabbatch, batchName, opt, subLabel); - batchName = ... - ['specify_estimate_ffx_task-', opt.taskName, ... - '_space-', opt.space, ... - '_FWHM-', num2str(funcFWHM)]; + if opt.glmQA.do + plot_power_spectra_of_GLM_residuals( ... + getFFXdir(subLabel, funcFWHM, opt), ... + opt.metadata.RepetitionTime); - saveAndRunWorkflow(matlabbatch, batchName, opt, subID); + deleteResidualImages(getFFXdir(subLabel, funcFWHM, opt)); - if opt.glmQA.do - plot_power_spectra_of_GLM_residuals( ... - getFFXdir(subID, funcFWHM, opt), ... - opt.metadata.RepetitionTime); + end - deleteResidualImages(getFFXdir(subID, funcFWHM, opt)); + case 'contrasts' - movefile(['sub-', subID, '_task-', opt.taskName, '_design_*'], ... - getFFXdir(subID, funcFWHM, opt)); - end + matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subLabel, funcFWHM); - case 'contrasts' + batchName = ... + ['contrasts_ffx_task-', opt.taskName, ... + '_space-', opt.space, ... + '_FWHM-', num2str(funcFWHM)]; - matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subID, funcFWHM); - - batchName = ... - ['contrasts_ffx_task-', opt.taskName, ... - '_space-', opt.space, ... - '_FWHM-', num2str(funcFWHM)]; - - saveAndRunWorkflow(matlabbatch, batchName, opt, subID); - - end + saveAndRunWorkflow(matlabbatch, batchName, opt, subLabel); end diff --git a/src/workflows/bidsRFX.m b/src/workflows/bidsRFX.m index c4990bec..f7a66606 100644 --- a/src/workflows/bidsRFX.m +++ b/src/workflows/bidsRFX.m @@ -43,14 +43,14 @@ function bidsRFX(action, opt, funcFWHM, conFWHM) conFWHM = 0; end - [~, opt, group] = setUpWorkflow(opt, 'group level GLM'); + [~, opt] = setUpWorkflow(opt, 'group level GLM'); switch action case 'smoothContrasts' matlabbatch = []; - matlabbatch = setBatchSmoothConImages(matlabbatch, group, opt, funcFWHM, conFWHM); + matlabbatch = setBatchSmoothConImages(matlabbatch, opt, funcFWHM, conFWHM); saveAndRunWorkflow(matlabbatch, ... ['smooth_con_FWHM-', num2str(conFWHM), '_task-', opt.taskName], ... @@ -82,7 +82,7 @@ function bidsRFX(action, opt, funcFWHM, conFWHM) % Load the list of contrasts of interest for the RFX grpLvlCon = getGrpLevelContrastToCompute(opt); - matlabbatch = setBatchEstimateModel(matlabbatch, grpLvlCon, opt); + matlabbatch = setBatchEstimateModel(matlabbatch, opt, grpLvlCon); saveAndRunWorkflow(matlabbatch, 'group_level_model_specification_estimation', opt); diff --git a/src/workflows/bidsRealignReslice.m b/src/workflows/bidsRealignReslice.m index 66f46cbf..3ab69d17 100644 --- a/src/workflows/bidsRealignReslice.m +++ b/src/workflows/bidsRealignReslice.m @@ -19,35 +19,26 @@ function bidsRealignReslice(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'realign and reslice'); + [BIDS, opt] = setUpWorkflow(opt, 'realign and reslice'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - % Get the ID of the subject - % (i.e SubNumber doesnt have to match the iSub if one subject - % is exluded for any reason) - subID = group(iGroup).subNumber{iSub}; % Get the subject ID + matlabbatch = []; + [matlabbatch, ~] = setBatchRealign( ... + matlabbatch, ... + BIDS, ... + subLabel, ... + opt, ... + 'realignReslice'); - printProcessingSubject(groupName, iSub, subID); + saveAndRunWorkflow(matlabbatch, 'realign_reslice', opt, subLabel); - matlabbatch = []; - [matlabbatch, ~] = setBatchRealign( ... - matlabbatch, ... - BIDS, ... - subID, ... - opt, ... - 'realignReslice'); + copyFigures(BIDS, opt, subLabel); - saveAndRunWorkflow(matlabbatch, 'realign_reslice', opt, subID); - - copyFigures(BIDS, opt, subID); - - end end end diff --git a/src/workflows/bidsRealignUnwarp.m b/src/workflows/bidsRealignUnwarp.m index e8db8d0b..fc299f3a 100644 --- a/src/workflows/bidsRealignUnwarp.m +++ b/src/workflows/bidsRealignUnwarp.m @@ -22,35 +22,26 @@ function bidsRealignUnwarp(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'realign and unwarp'); + [BIDS, opt] = setUpWorkflow(opt, 'realign and unwarp'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - % Get the ID of the subject - % (i.e SubNumber doesnt have to match the iSub if one subject - % is exluded for any reason) - subID = group(iGroup).subNumber{iSub}; % Get the subject ID + matlabbatch = []; + [matlabbatch, ~] = setBatchRealign( ... + matlabbatch, ... + BIDS, ... + subLabel, ... + opt, ... + 'realignUnwarp'); - printProcessingSubject(groupName, iSub, subID); + saveAndRunWorkflow(matlabbatch, 'realign_unwarp', opt, subLabel); - matlabbatch = []; - [matlabbatch, ~] = setBatchRealign( ... - matlabbatch, ... - BIDS, ... - subID, ... - opt, ... - 'realignUnwarp'); + copyFigures(BIDS, opt, subLabel); - saveAndRunWorkflow(matlabbatch, 'realign_unwarp', opt, subID); - - copyFigures(BIDS, opt, subID); - - end end end diff --git a/src/workflows/bidsResliceTpmToFunc.m b/src/workflows/bidsResliceTpmToFunc.m index 0421e856..561f3398 100644 --- a/src/workflows/bidsResliceTpmToFunc.m +++ b/src/workflows/bidsResliceTpmToFunc.m @@ -25,52 +25,44 @@ function bidsResliceTpmToFunc(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, ... - 'reslicing tissue probability maps to functional dimension'); + [BIDS, opt] = setUpWorkflow(opt, 'reslicing tissue probability maps to functional dimension'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + for iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - for iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subLabel, opt); - printProcessingSubject(groupName, iSub, subID); + % get grey and white matter and CSF tissue probability maps + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); + TPMs = validationInputFile(anatDataDir, anatImage, 'c[123]'); - [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subID, opt); + matlabbatch = []; + matlabbatch = setBatchReslice(matlabbatch, ... + fullfile(meanFuncDir, meanImage), ... + cellstr(TPMs)); - % get grey and white matter and CSF tissue probability maps - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); - TPMs = validationInputFile(anatDataDir, anatImage, 'c[123]'); + saveAndRunWorkflow(matlabbatch, 'reslice_tpm', opt, subLabel); - matlabbatch = []; - matlabbatch = setBatchReslice(matlabbatch, ... - fullfile(meanFuncDir, meanImage), ... - cellstr(TPMs)); + %% Compute brain mask of functional + TPMs = validationInputFile(anatDataDir, anatImage, 'rc[123]'); + % greay matter + input{1, 1} = TPMs(1, :); + % white matter + input{2, 1} = TPMs(2, :); + % csf + input{3, 1} = TPMs(3, :); - saveAndRunWorkflow(matlabbatch, 'reslice_tpm', opt, subID); + output = strrep(meanImage, '.nii', '_mask.nii'); - %% Compute brain mask of functional - TPMs = validationInputFile(anatDataDir, anatImage, 'rc[123]'); - % greay matter - input{1, 1} = TPMs(1, :); - % white matter - input{2, 1} = TPMs(2, :); - % csf - input{3, 1} = TPMs(3, :); + expression = sprintf('(i1+i2+i3)>%f', opt.skullstrip.threshold); - output = strrep(meanImage, '.nii', '_mask.nii'); + matlabbatch = []; + matlabbatch = setBatchImageCalculation(matlabbatch, input, output, meanFuncDir, expression); - expression = sprintf('(i1+i2+i3)>%f', opt.skullstrip.threshold); - - matlabbatch = []; - matlabbatch = setBatchImageCalculation(matlabbatch, input, output, meanFuncDir, expression); - - saveAndRunWorkflow(matlabbatch, 'create_functional_brain_mask', opt, subID); - - end + saveAndRunWorkflow(matlabbatch, 'create_functional_brain_mask', opt, subLabel); end diff --git a/src/workflows/bidsResults.m b/src/workflows/bidsResults.m index 05c00a88..8b129d5e 100644 --- a/src/workflows/bidsResults.m +++ b/src/workflows/bidsResults.m @@ -25,7 +25,7 @@ function bidsResults(opt, funcFWHM, conFWHM) opt = []; end - [~, opt, group] = setUpWorkflow(opt, 'computing GLM results'); + [~, opt] = setUpWorkflow(opt, 'computing GLM results'); matlabbatch = []; @@ -47,34 +47,29 @@ function bidsResults(opt, funcFWHM, conFWHM) case 'subject' - for iGroup = 1:length(group) + % For each subject + for iSub = 1:numel(opt.subjects) - % For each subject - for iSub = 1:group(iGroup).numSub + subLabel = opt.subjects{iSub}; - for iCon = 1:length(opt.result.Steps(iStep).Contrasts) + for iCon = 1:length(opt.result.Steps(iStep).Contrasts) - % Get the Subject ID - subID = group(iGroup).subNumber{iSub}; - - matlabbatch = ... - setBatchSubjectLevelResults( ... - matlabbatch, ... - opt, ... - subID, ... - funcFWHM, ... - iStep, ... - iCon); - - end + matlabbatch = ... + setBatchSubjectLevelResults( ... + matlabbatch, ... + opt, ... + subLabel, ... + funcFWHM, ... + iStep, ... + iCon); end - batchName = sprintf('compute_sub-%s_results', subID); + end - saveAndRunWorkflow(matlabbatch, batchName, opt, subID); + batchName = sprintf('compute_sub-%s_results', subLabel); - end + saveAndRunWorkflow(matlabbatch, batchName, opt, subLabel); case 'dataset' diff --git a/src/workflows/bidsSTC.m b/src/workflows/bidsSTC.m index ade9c400..ee83b8e3 100644 --- a/src/workflows/bidsSTC.m +++ b/src/workflows/bidsSTC.m @@ -34,25 +34,19 @@ function bidsSTC(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'slice timing correction'); + [BIDS, opt] = setUpWorkflow(opt, 'slice timing correction'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + matlabbatch = []; + matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel); - printProcessingSubject(groupName, iSub, subID); + saveAndRunWorkflow(matlabbatch, 'STC', opt, subLabel); - matlabbatch = []; - matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subID); - - saveAndRunWorkflow(matlabbatch, 'STC', opt, subID); - - end end end diff --git a/src/workflows/bidsSegmentSkullStrip.m b/src/workflows/bidsSegmentSkullStrip.m index 1e2da98a..f29a3a7b 100644 --- a/src/workflows/bidsSegmentSkullStrip.m +++ b/src/workflows/bidsSegmentSkullStrip.m @@ -17,32 +17,27 @@ function bidsSegmentSkullStrip(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'segmentation and skulltripping'); + [BIDS, opt] = setUpWorkflow(opt, 'segmentation and skulltripping'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + opt.orderBatches.selectAnat = 1; + opt.orderBatches.segment = 2; - groupName = group(iGroup).name; + parfor iSub = 1:numel(opt.subjects) - for iSub = 1:group(iGroup).numSub + subLabel = opt.subjects{iSub}; - subID = group(iGroup).subNumber{iSub}; + printProcessingSubject(iSub, subLabel); - printProcessingSubject(groupName, iSub, subID); + matlabbatch = []; + matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subLabel); - matlabbatch = []; - matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subID); - opt.orderBatches.selectAnat = 1; + % dependency from file selector ('Anatomical') + matlabbatch = setBatchSegmentation(matlabbatch, opt); - % dependency from file selector ('Anatomical') - matlabbatch = setBatchSegmentation(matlabbatch, opt); - opt.orderBatches.segment = 2; + matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, subLabel, opt); - matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, subID, opt); + saveAndRunWorkflow(matlabbatch, 'segment_skullstrip', opt, subLabel); - saveAndRunWorkflow(matlabbatch, 'segment_skullstrip', opt, subID); - - end end end diff --git a/src/workflows/bidsSmoothing.m b/src/workflows/bidsSmoothing.m index 2dd19d46..199d8d63 100644 --- a/src/workflows/bidsSmoothing.m +++ b/src/workflows/bidsSmoothing.m @@ -22,25 +22,19 @@ function bidsSmoothing(funcFWHM, opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'smoothing functional data'); + [BIDS, opt] = setUpWorkflow(opt, 'smoothing functional data'); - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + subLabel = opt.subjects{iSub}; - parfor iSub = 1:group(iGroup).numSub + printProcessingSubject(iSub, subLabel); - subID = group(iGroup).subNumber{iSub}; + matlabbatch = []; + matlabbatch = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel, funcFWHM); - printProcessingSubject(groupName, iSub, subID); + saveAndRunWorkflow(matlabbatch, ['smoothing_FWHM-' num2str(funcFWHM)], opt, subLabel); - matlabbatch = []; - matlabbatch = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subID, funcFWHM); - - saveAndRunWorkflow(matlabbatch, ['smoothing_FWHM-' num2str(funcFWHM)], opt, subID); - - end end end diff --git a/src/workflows/bidsSpatialPrepro.m b/src/workflows/bidsSpatialPrepro.m index 91e73a34..c29ac266 100644 --- a/src/workflows/bidsSpatialPrepro.m +++ b/src/workflows/bidsSpatialPrepro.m @@ -42,7 +42,7 @@ function bidsSpatialPrepro(opt) opt = []; end - [BIDS, opt, group] = setUpWorkflow(opt, 'spatial preprocessing'); + [BIDS, opt] = setUpWorkflow(opt, 'spatial preprocessing'); opt.orderBatches.selectAnat = 1; opt.orderBatches.realign = 2; @@ -52,59 +52,51 @@ function bidsSpatialPrepro(opt) opt.orderBatches.skullStripping = 6; opt.orderBatches.skullStrippingMask = 7; - %% Loop through the groups, subjects, and sessions - for iGroup = 1:length(group) + parfor iSub = 1:numel(opt.subjects) - groupName = group(iGroup).name; + matlabbatch = []; - parfor iSub = 1:group(iGroup).numSub + subLabel = opt.subjects{iSub}; - matlabbatch = []; - % Get the ID of the subject - % (i.e SubNumber doesnt have to match the iSub if one subject - % is exluded for any reason) - subID = group(iGroup).subNumber{iSub}; + printProcessingSubject(iSub, subLabel); - printProcessingSubject(groupName, iSub, subID); + matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subLabel); - matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subID); - - % if action is emtpy then only realign will be done - action = []; - if ~opt.realign.useUnwarp - action = 'realign'; - end - [matlabbatch, voxDim] = setBatchRealign(matlabbatch, action, BIDS, opt, subID); + % if action is emtpy then only realign will be done + action = []; + if ~opt.realign.useUnwarp + action = 'realign'; + end + [matlabbatch, voxDim] = setBatchRealign(matlabbatch, action, BIDS, opt, subLabel); - % dependency from file selector ('Anatomical') - matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subID); + % dependency from file selector ('Anatomical') + matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subLabel); - matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subLabel); - % dependency from file selector ('Anatomical') - matlabbatch = setBatchSegmentation(matlabbatch, opt); + % dependency from file selector ('Anatomical') + matlabbatch = setBatchSegmentation(matlabbatch, opt); - matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel); - if strcmp(opt.space, 'MNI') - % dependency from segmentation - % dependency from coregistration - matlabbatch = setBatchNormalizationSpatialPrepro(matlabbatch, opt, voxDim); - end + if strcmp(opt.space, 'MNI') + % dependency from segmentation + % dependency from coregistration + matlabbatch = setBatchNormalizationSpatialPrepro(matlabbatch, opt, voxDim); + end - % if no unwarping was done on func, we reslice the func, so we can use - % them for the functionalQA - if ~opt.realign.useUnwarp - matlabbatch = setBatchRealign(matlabbatch, 'reslice', BIDS, opt, subID); - end + % if no unwarping was done on func, we reslice the func, so we can use + % them for the functionalQA + if ~opt.realign.useUnwarp + matlabbatch = setBatchRealign(matlabbatch, 'reslice', BIDS, opt, subLabel); + end - batchName = ['spatial_preprocessing-' upper(opt.space(1)) opt.space(2:end)]; + batchName = ['spatial_preprocessing-' upper(opt.space(1)) opt.space(2:end)]; - saveAndRunWorkflow(matlabbatch, batchName, opt, subID); + saveAndRunWorkflow(matlabbatch, batchName, opt, subLabel); - copyFigures(BIDS, opt, subID); + copyFigures(BIDS, opt, subLabel); - end end end diff --git a/src/workflows/saveAndRunWorkflow.m b/src/workflows/saveAndRunWorkflow.m index 363b305b..d6972712 100644 --- a/src/workflows/saveAndRunWorkflow.m +++ b/src/workflows/saveAndRunWorkflow.m @@ -1,6 +1,6 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function saveAndRunWorkflow(matlabbatch, batchName, opt, subID) +function saveAndRunWorkflow(matlabbatch, batchName, opt, subLabel) % % Saves the SPM matlabbatch and runs it % @@ -19,12 +19,12 @@ function saveAndRunWorkflow(matlabbatch, batchName, opt, subID) % :type subID: string if nargin < 4 - subID = []; + subLabel = []; end if ~isempty(matlabbatch) - saveMatlabBatch(matlabbatch, batchName, opt, subID); + saveMatlabBatch(matlabbatch, batchName, opt, subLabel); spm_jobman('run', matlabbatch); diff --git a/src/workflows/setUpWorkflow.m b/src/workflows/setUpWorkflow.m index 60e36f47..d79ffb29 100644 --- a/src/workflows/setUpWorkflow.m +++ b/src/workflows/setUpWorkflow.m @@ -1,6 +1,6 @@ % (C) Copyright 2019 CPP BIDS SPM-pipeline developers -function [BIDS, opt, group] = setUpWorkflow(opt, workflowName) +function [BIDS, opt] = setUpWorkflow(opt, workflowName) % % Calls some common functions to: % - check the configuraton, @@ -28,7 +28,7 @@ opt = loadAndCheckOptions(opt); % load the subjects/Groups information and the task name - [group, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); cleanCrash(); diff --git a/tests/dummyData/derivatives/cpp_spm/participants.tsv b/tests/dummyData/derivatives/cpp_spm/participants.tsv index 0672bef8..6db63977 100755 --- a/tests/dummyData/derivatives/cpp_spm/participants.tsv +++ b/tests/dummyData/derivatives/cpp_spm/participants.tsv @@ -1,6 +1,7 @@ -participant_id Sex Age Educational level Smoker Medication Handedness -sub-01 1 66 14 0 1 30 -sub-02 1 28 16 1 0 12 -sub-ctrl01 0 61 16 0 0 18 - - +participant_id Sex Group Age Educational level Smoker Medication Handedness +sub-01 1 n/a 66 14 0 1 30 +sub-02 0 blind 28 16 1 0 12 +sub-ctrl01 1 ctrl 61 16 0 0 18 +sub-ctrl02 1 ctrl 45 16 0 0 18 +sub-blind01 1 blind 12 16 0 0 18 +sub-blind02 0 blind 61 16 0 0 18 diff --git a/tests/miss_hit.cfg b/tests/miss_hit.cfg index 1aa3765a..d4c4fc66 100644 --- a/tests/miss_hit.cfg +++ b/tests/miss_hit.cfg @@ -1,7 +1,6 @@ # style guide (https://florianschanda.github.io/miss_hit/style_checker.html) line_length: 100 -regex_function_name: "((test_[a-z]+)|[a-z]+)(([A-Z]){1}[A-Za-z0-9]+)*" -suppress_rule: "copyright_notice" +regex_function_name: "(test(_unit){0,1}_[a-z]+|[a-z]+)(([A-Z]){1}[A-Za-z0-9]+)*" # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) metric "cnest": limit 4 diff --git a/tests/test_bidsCopyRawFolder.m b/tests/test_bidsCopyRawFolder.m index ad8adadc..523c96bb 100644 --- a/tests/test_bidsCopyRawFolder.m +++ b/tests/test_bidsCopyRawFolder.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_bidsCopyRawFolder %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,11 +10,7 @@ function test_bidsCopyRawFolderBasic() - opt.dataDir = fullfile( ... - fileparts(mfilename('fullpath')), ... - '..', 'demos', 'MoAE', 'output', 'MoAEpilot'); - - opt.taskName = 'auditory'; + opt = setOptions('MoAE'); opt = checkOptions(opt); diff --git a/tests/test_checkOptions.m b/tests/test_checkOptions.m index 158e4d40..6390bfa0 100644 --- a/tests/test_checkOptions.m +++ b/tests/test_checkOptions.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_checkOptions %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_createAndReturnOnsetFile.m b/tests/test_createAndReturnOnsetFile.m index a3189511..493b6dfe 100644 --- a/tests/test_createAndReturnOnsetFile.m +++ b/tests/test_createAndReturnOnsetFile.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_createAndReturnOnsetFile %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,28 +10,27 @@ function test_createAndReturnOnsetFileBasic() - subID = '01'; + subLabel = '01'; funcFWHM = 6; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {'01'}; + opt = setOptions('vislocalizer', subLabel); + opt.model.file = fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'models', ... 'model-vislocalizer_smdl.json'); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - sessions = getInfo(BIDS, subID, opt, 'sessions'); - runs = getInfo(BIDS, subID, opt, 'runs', sessions{iSes}); + sessions = getInfo(BIDS, subLabel, opt, 'sessions'); + runs = getInfo(BIDS, subLabel, opt, 'runs', sessions{iSes}); - tsvFile = getInfo(BIDS, subID, opt, 'filename', sessions{iSes}, runs{iRun}, 'events'); + tsvFile = getInfo(BIDS, subLabel, opt, 'filename', sessions{iSes}, runs{iRun}, 'events'); - onsetFileName = createAndReturnOnsetFile(opt, subID, tsvFile, funcFWHM); + onsetFileName = createAndReturnOnsetFile(opt, subLabel, tsvFile, funcFWHM); expectedFileName = fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'derivatives', 'cpp_spm', 'sub-01', 'stats', ... diff --git a/tests/test_createDefaultModel.m b/tests/test_createDefaultModel.m index b10f963b..f95e98a3 100644 --- a/tests/test_createDefaultModel.m +++ b/tests/test_createDefaultModel.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_createDefaultModel %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,12 +10,11 @@ function test_createDefaultModelBasic() - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); + opt = setOptions('vislocalizer'); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); createDefaultModel(BIDS, opt); diff --git a/tests/test_getAnatFilename.m b/tests/test_getAnatFilename.m index c888f724..a2e04330 100644 --- a/tests/test_getAnatFilename.m +++ b/tests/test_getAnatFilename.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getAnatFilename %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -14,18 +16,15 @@ function test_getAnatFilenameBasic() - subID = '01'; + subLabel = '01'; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.groups = {''}; - opt.subjects = {subID}; + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); expectedFileName = 'sub-01_ses-01_T1w.nii'; diff --git a/tests/test_getBoldFilename.m b/tests/test_getBoldFilename.m index be89963e..cb55235c 100644 --- a/tests/test_getBoldFilename.m +++ b/tests/test_getBoldFilename.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getBoldFilename %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,25 +10,24 @@ function test_getBoldFilenameBasic() - subID = '01'; + subLabel = '01'; funcFWHM = 6; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.groups = {''}; - opt.subjects = {'01'}; + opt = setOptions('vislocalizer', subLabel); + + opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - sessions = getInfo(BIDS, subID, opt, 'Sessions'); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); [fileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{iSes}, runs{iRun}, opt); + subLabel, sessions{iSes}, runs{iRun}, opt); expectedFileName = 'sub-01_ses-01_task-vislocalizer_bold.nii'; diff --git a/tests/test_getBoldFilenameForFFX.m b/tests/test_getBoldFilenameForFFX.m index bfbc0c25..f677e761 100644 --- a/tests/test_getBoldFilenameForFFX.m +++ b/tests/test_getBoldFilenameForFFX.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getBoldFilenameForFFX %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,20 +10,18 @@ function test_getBoldFilenameForFFXBasic() - subID = '01'; + subLabel = '01'; funcFWHM = 6; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {'01'}; + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subID, funcFWHM, iSes, iRun); + [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subLabel, funcFWHM, iSes, iRun); expectedFileName = fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'derivatives', 'cpp_spm', 'sub-01', ... @@ -35,21 +35,19 @@ function test_getBoldFilenameForFFXBasic() function test_getBoldFilenameForFFXNativeSpace() - subID = '01'; + subLabel = '01'; funcFWHM = 6; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.dataDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData', 'derivatives'); - opt.subjects = {'01'}; + opt = setOptions('vislocalizer', subLabel); opt.space = 'individual'; opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subID, funcFWHM, iSes, iRun); + [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subLabel, funcFWHM, iSes, iRun); expectedFileName = fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'derivatives', 'cpp_spm', 'sub-01', ... diff --git a/tests/test_getData.m b/tests/test_getData.m index 7f4a07f4..dfa32545 100644 --- a/tests/test_getData.m +++ b/tests/test_getData.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getData %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -6,64 +8,12 @@ initTestSuite; end -function test_getDataBasic() - % Small test to ensure that getData returns what we asked for - - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; - opt.zeropad = 2; - - %% Get all groups all subjects - opt.groups = {''}; - opt.subjects = {[]}; - - [group] = getData(opt); - - assert(isequal(group(1).name, '')); - assert(isequal(group.numSub, 6)); - assert(isequal(group.subNumber, ... - {'01' '02' 'blind01' 'blind02' 'ctrl01' 'ctrl02'})); - - %% Get some subjects of some groups - opt.groups = {'ctrl', 'blind'}; - opt.subjects = {[1 2], 2}; - - [group] = getData(opt); - - assert(isequal(group(1).name, 'ctrl')); - assert(isequal(group(1).numSub, 2)); - assert(isequal(group(1).subNumber, {'ctrl01' 'ctrl02'})); - assert(isequal(group(2).name, 'blind')); - assert(isequal(group(2).numSub, 1)); - assert(isequal(group(2).subNumber, {'blind02'})); - - %% Get all subjects of some groups - opt.groups = {'ctrl', 'blind'}; - opt.subjects = {[], []}; - - [group] = getData(opt); - - assert(isequal(group(1).name, 'ctrl')); - assert(isequal(group(1).numSub, 2)); - assert(isequal(group(1).subNumber, {'ctrl01' 'ctrl02'})); - assert(isequal(group(2).name, 'blind')); - assert(isequal(group(2).numSub, 2)); - assert(isequal(group(2).subNumber, {'blind01' 'blind02'})); - - %% Get some specified subjects - opt.groups = {''}; - opt.subjects = {'01', 'ctrl02', 'blind02'}; +function test_getDataMetadata() - [group] = getData(opt); + subLabel = '01'; - assert(isequal(group(1).name, '')); - assert(isequal(group(1).numSub, 3)); - assert(isequal(group(1).subNumber, {'01', 'ctrl02', 'blind02'})); - - %% Only get anat metadata - opt.groups = {''}; - - opt.subjects = {'01'}; + opt = setOptions('vismotion', subLabel); + opt = checkOptions(opt); [~, opt] = getData(opt, [], 'T1w'); @@ -72,34 +22,12 @@ function test_getDataBasic() end function test_getDataErrorTask() - % Small test to ensure that getData returns what we asked for - - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'testTask'; - opt.zeropad = 2; - %% Get all groups all subjects - opt.groups = {''}; - opt.subjects = {[]}; + opt = setOptions('testTask'); + opt = checkOptions(opt); assertExceptionThrown( ... @()getData(opt), ... 'getData:noMatchingTask'); end - -function test_getDataErrorSubject() - % Small test to ensure that getData returns what we asked for - - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; - - %% Get all groups all subjects - opt.groups = {''}; - opt.subjects = {'03'}; - - assertExceptionThrown( ... - @()getData(opt), ... - 'getData:noMatchingSubject'); - -end diff --git a/tests/test_getInfo.m b/tests/test_getInfo.m deleted file mode 100644 index 837a276e..00000000 --- a/tests/test_getInfo.m +++ /dev/null @@ -1,64 +0,0 @@ -function test_suite = test_getInfo %#ok<*STOUT> - try % assignment of 'localfunctions' is necessary in Matlab >= 2016 - test_functions = localfunctions(); %#ok<*NASGU> - catch % no problem; early Matlab versions can use initTestSuite fine - end - initTestSuite; -end - -function test_getInfoBasic() - % Small test to ensure that getSliceOrder returns what we asked for - - % write tests for when no session or only one run - - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), ... - 'dummyData', 'derivatives', 'cpp_spm'); - opt.groups = {''}; - opt.subjects = {[], []}; - - %% Get sessions from BIDS - opt.taskName = 'vismotion'; - subID = 'ctrl01'; - info = 'sessions'; - [~, opt, BIDS] = getData(opt); - sessions = getInfo(BIDS, subID, opt, info); - assert(all(strcmp(sessions, {'01' '02'}))); - - %% Get runs from BIDS - opt.taskName = 'vismotion'; - subID = 'ctrl01'; - info = 'runs'; - session = '01'; - [~, opt, BIDS] = getData(opt); - runs = getInfo(BIDS, subID, opt, info, session); - assert(all(strcmp(runs, {'1' '2'}))); - - %% Get runs from BIDS when no run in filename - opt.taskName = 'vislocalizer'; - subID = 'ctrl01'; - info = 'runs'; - session = '01'; - [~, opt, BIDS] = getData(opt); - runs = getInfo(BIDS, subID, opt, info, session); - assert(strcmp(runs, {''})); - - %% Get filename from BIDS - opt.taskName = 'vismotion'; - subID = 'ctrl01'; - session = '01'; - run = '1'; - info = 'filename'; - [~, opt, BIDS] = getData(opt); - filename = getInfo(BIDS, subID, opt, info, session, run, 'bold'); - FileName = fullfile(fileparts(mfilename('fullpath')), 'dummyData', ... - 'derivatives', 'cpp_spm', ... - ['sub-' subID], ['ses-' session], 'func', ... - ['sub-' subID, ... - '_ses-' session, ... - '_task-' opt.taskName, ... - '_run-' run, ... - '_bold.nii']); - - assert(strcmp(filename, FileName)); - -end diff --git a/tests/test_getMeanFuncFilename.m b/tests/test_getMeanFuncFilename.m index d57159ad..623c1ec1 100644 --- a/tests/test_getMeanFuncFilename.m +++ b/tests/test_getMeanFuncFilename.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getMeanFuncFilename %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,18 +10,14 @@ function test_getMeanFuncFilenameBasic() - subID = '01'; - - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.groups = {''}; - opt.subjects = {subID}; + subLabel = '01'; + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subID, opt); + [meanImage, meanFuncDir] = getMeanFuncFilename(BIDS, subLabel, opt); expectedMeanImage = 'meanusub-01_ses-01_task-vislocalizer_bold.nii'; diff --git a/tests/test_getRealignParamFile.m b/tests/test_getRealignParamFile.m index e4e66f66..9ebce4ea 100644 --- a/tests/test_getRealignParamFile.m +++ b/tests/test_getRealignParamFile.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_getRealignParamFile %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,19 +10,16 @@ function test_getRealignParamFileBasic() - subID = '01'; + subLabel = '01'; session = '01'; run = ''; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {subID}; - + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [boldFileName, subFuncDataDir] = getBoldFilename(BIDS, subID, session, run, opt); + [boldFileName, subFuncDataDir] = getBoldFilename(BIDS, subLabel, session, run, opt); realignParamFile = getRealignParamFile(fullfile(subFuncDataDir, boldFileName)); expectedFileName = fullfile(fileparts(mfilename('fullpath')), ... @@ -34,20 +33,17 @@ function test_getRealignParamFileBasic() function test_getRealignParamFileNativeSpace() - subID = '01'; + subLabel = '01'; session = '01'; run = ''; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {subID}; + opt = setOptions('vislocalizer', subLabel); opt.space = 'individual'; - opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [boldFileName, subFuncDataDir] = getBoldFilename(BIDS, subID, session, run, opt); + [boldFileName, subFuncDataDir] = getBoldFilename(BIDS, subLabel, session, run, opt); realignParamFile = getRealignParamFile(fullfile(subFuncDataDir, boldFileName)); expectedFileName = fullfile(fileparts(mfilename('fullpath')), ... @@ -61,21 +57,17 @@ function test_getRealignParamFileNativeSpace() function test_getRealignParamFileFFX() - subID = '01'; + subLabel = '01'; funcFWHM = 6; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {subID}; - opt.space = 'MNI'; - + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subID, funcFWHM, iSes, iRun); + [boldFileName, prefix] = getBoldFilenameForFFX(BIDS, opt, subLabel, funcFWHM, iSes, iRun); [subFuncDataDir, boldFileName, ext] = spm_fileparts(boldFileName); realignParamFile = getRealignParamFile(fullfile(subFuncDataDir, [boldFileName, ext]), prefix); diff --git a/tests/test_loadAndCheckOptions.m b/tests/test_loadAndCheckOptions.m index dd35d983..e0a4cb07 100644 --- a/tests/test_loadAndCheckOptions.m +++ b/tests/test_loadAndCheckOptions.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_loadAndCheckOptions %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_modelFiles.m b/tests/test_modelFiles.m index 4c442b60..1a80e561 100644 --- a/tests/test_modelFiles.m +++ b/tests/test_modelFiles.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_modelFiles %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_saveMatlabBatch.m b/tests/test_saveMatlabBatch.m index a05c72a7..af8327e7 100644 --- a/tests/test_saveMatlabBatch.m +++ b/tests/test_saveMatlabBatch.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_saveMatlabBatch %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatch3Dto4D.m b/tests/test_setBatch3Dto4D.m index 6a169d3e..53d3eded 100644 --- a/tests/test_setBatch3Dto4D.m +++ b/tests/test_setBatch3Dto4D.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatch3Dto4D %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchComputeVDM.m b/tests/test_setBatchComputeVDM.m index 64774ded..1f46e1a5 100644 --- a/tests/test_setBatchComputeVDM.m +++ b/tests/test_setBatchComputeVDM.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchComputeVDM %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchCoregistrationFuncToAnat.m b/tests/test_setBatchCoregistrationFuncToAnat.m index fe07cb59..20c163eb 100644 --- a/tests/test_setBatchCoregistrationFuncToAnat.m +++ b/tests/test_setBatchCoregistrationFuncToAnat.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchCoregistrationFuncToAnat %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -11,20 +13,18 @@ function test_setBatchCoregistrationFuncToAnatBasic() % necessarry to deal with SPM module dependencies spm_jobman('initcfg'); - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; + subLabel = '02'; + opt = setOptions('vismotion', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - - subID = '02'; + [BIDS, opt] = getData(opt); opt.orderBatches.selectAnat = 1; opt.orderBatches.realign = 2; matlabbatch = {}; - matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subLabel); nbRuns = 4; @@ -49,21 +49,20 @@ function test_setBatchCoregistrationFuncToAnatNoUnwarp() % necessarry to deal with SPM module dependencies spm_jobman('initcfg'); - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; - opt.realign.useUnwarp = false; + subLabel = '02'; + opt = setOptions('vismotion', subLabel); + opt = checkOptions(opt); + opt.realign.useUnwarp = false; opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - - subID = '02'; + [BIDS, opt] = getData(opt); opt.orderBatches.selectAnat = 1; opt.orderBatches.realign = 2; matlabbatch = {}; - matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subLabel); nbRuns = 4; diff --git a/tests/test_setBatchFactorialDesign.m b/tests/test_setBatchFactorialDesign.m index f8b75325..5cbb1fef 100644 --- a/tests/test_setBatchFactorialDesign.m +++ b/tests/test_setBatchFactorialDesign.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchFactorialDesign %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -11,9 +13,8 @@ function test_setBatchFactorialDesignBasic() funcFWHM = 6; conFWHM = 6; + opt = setOptions('vismotion'); opt.subjects = {'01' '02'}; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; opt.model.file = fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'models', 'model-visMotionLoc_smdl.json'); diff --git a/tests/test_setBatchImageCalculation.m b/tests/test_setBatchImageCalculation.m index 235d27a4..bc21e0db 100644 --- a/tests/test_setBatchImageCalculation.m +++ b/tests/test_setBatchImageCalculation.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchImageCalculation %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchMeanAnatAndMask.m b/tests/test_setBatchMeanAnatAndMask.m index 780567c4..36b8f0c1 100644 --- a/tests/test_setBatchMeanAnatAndMask.m +++ b/tests/test_setBatchMeanAnatAndMask.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchMeanAnatAndMask %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -10,14 +12,10 @@ function test_setBatchMeanAnatAndMaskBasic() funcFWHM = 6; + opt = setOptions('vismotion'); opt.subjects = {'01', '02'}; - opt.taskName = 'vismotion'; - opt.space = 'MNI'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), ... - 'dummyData', ... - 'derivatives', ... - 'cpp_spm'); + opt = setDerivativesDir(opt); opt = checkOptions(opt); matlabbatch = []; diff --git a/tests/test_setBatchNormalizationSpatialPrepro.m b/tests/test_setBatchNormalizationSpatialPrepro.m index 7a3199a5..ca36ac08 100644 --- a/tests/test_setBatchNormalizationSpatialPrepro.m +++ b/tests/test_setBatchNormalizationSpatialPrepro.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchNormalizationSpatialPrepro %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchRealign.m b/tests/test_setBatchRealign.m index 5be5d90f..abccf14b 100644 --- a/tests/test_setBatchRealign.m +++ b/tests/test_setBatchRealign.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchRealign %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -14,18 +16,14 @@ function test_setBatchRealignBasic() % add test realign and unwarp % check it returns the right voxDim - opt.dataDir = fullfile(fileparts(mfilename('fullpath')), '..', 'demos', ... - 'MoAE', 'output', 'MoAEpilot'); - opt.taskName = 'auditory'; + subLabel = '01'; + opt = setOptions('MoAE', subLabel); opt = checkOptions(opt); - - [~, opt, BIDS] = getData(opt); - - subID = '01'; + [BIDS, opt] = getData(opt); matlabbatch = []; - matlabbatch = setBatchRealign(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchRealign(matlabbatch, BIDS, opt, subLabel); expectedBatch{1}.spm.spatial.realignunwarp.eoptions.weight = {''}; expectedBatch{end}.spm.spatial.realignunwarp.uwroptions.uwwhich = [2 1]; @@ -33,7 +31,7 @@ function test_setBatchRealignBasic() runCounter = 1; for iSes = 1 fileName = spm_BIDS(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'task', opt.taskName, ... 'type', 'bold'); diff --git a/tests/test_setBatchResults.m b/tests/test_setBatchResults.m index ca500734..1a39cfa5 100644 --- a/tests/test_setBatchResults.m +++ b/tests/test_setBatchResults.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchResults %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchSTC.m b/tests/test_setBatchSTC.m index 10dda843..93c4941c 100644 --- a/tests/test_setBatchSTC.m +++ b/tests/test_setBatchSTC.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSTC %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,16 +10,16 @@ function test_setBatchSTCEmpty() - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vislocalizer'; + subLabel = '02'; + opt = setOptions('vislocalizer', subLabel); + opt = setDerivativesDir(opt); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - subID = '02'; matlabbatch = []; - matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel); % no slice timing info for this run so nothing should be returned. assertEqual(matlabbatch, []); @@ -26,8 +28,11 @@ function test_setBatchSTCEmpty() function test_setBatchSTCForce() - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vislocalizer'; + subLabel = '02'; + + opt = setOptions('vislocalizer', subLabel); + opt = setDerivativesDir(opt); + % we give it some slice timing value to force slice timing to happen opt.sliceOrder = linspace(0, 1.6, 10); opt.sliceOrder(end - 1:end) = []; @@ -35,12 +40,10 @@ function test_setBatchSTCForce() opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - - subID = '02'; + [BIDS, opt] = getData(opt); matlabbatch = []; - matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel); TR = 1.55; expectedBatch = returnExpectedBatch(opt.sliceOrder, opt.STC_referenceSlice, TR); @@ -48,7 +51,7 @@ function test_setBatchSTCForce() runCounter = 1; for iSes = 1:2 fileName = spm_BIDS(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'ses', sprintf('0%i', iSes), ... 'task', opt.taskName, ... 'type', 'bold'); @@ -62,17 +65,16 @@ function test_setBatchSTCForce() function test_setBatchSTCBasic() - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; + subLabel = '02'; + opt = setOptions('vismotion', subLabel); + opt = setDerivativesDir(opt); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - - subID = '02'; + [BIDS, opt] = getData(opt); matlabbatch = []; - matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel); TR = 1.5; sliceOrder = repmat([ ... @@ -85,11 +87,11 @@ function test_setBatchSTCBasic() runCounter = 1; for iSes = 1:2 - fileName = spm_BIDS(BIDS, 'data', ... - 'sub', subID, ... - 'ses', sprintf('0%i', iSes), ... - 'task', opt.taskName, ... - 'type', 'bold'); + fileName = bids.query(BIDS, 'data', ... + 'sub', subLabel, ... + 'ses', sprintf('0%i', iSes), ... + 'task', opt.taskName, ... + 'type', 'bold'); expectedBatch{1}.spm.temporal.st.scans{runCounter} = ... {fileName{1}}; expectedBatch{1}.spm.temporal.st.scans{runCounter + 1} = ... @@ -103,8 +105,10 @@ function test_setBatchSTCBasic() function test_setBatchSTCErrorInvalidInputTime() - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vislocalizer'; + subLabel = '02'; + + opt = setOptions('vislocalizer', subLabel); + opt = setDerivativesDir(opt); opt.sliceOrder = linspace(0, 1.6, 10); opt.sliceOrder(end) = []; @@ -112,14 +116,12 @@ function test_setBatchSTCErrorInvalidInputTime() opt = checkOptions(opt); - subID = '02'; - - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); matlabbatch = []; assertExceptionThrown( ... - @()setBatchSTC(matlabbatch, BIDS, opt, subID), ... + @()setBatchSTC(matlabbatch, BIDS, opt, subLabel), ... 'setBatchSTC:invalidInputTime'); end @@ -128,6 +130,7 @@ function test_setBatchSTCErrorInvalidInputTime() nbSlices = length(sliceOrder); TA = TR - (TR / nbSlices); + TA = ceil(TA*1000)/1000; expectedBatch{1}.spm.temporal.st.nslices = nbSlices; expectedBatch{1}.spm.temporal.st.tr = TR; diff --git a/tests/test_setBatchSaveCoregistrationMatrix.m b/tests/test_setBatchSaveCoregistrationMatrix.m index 89889ce1..dda848aa 100644 --- a/tests/test_setBatchSaveCoregistrationMatrix.m +++ b/tests/test_setBatchSaveCoregistrationMatrix.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSaveCoregistrationMatrix %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -11,18 +13,18 @@ function test_setBatchSaveCoregistrationMatrixBasic() % necessarry to deal with SPM module dependencies spm_jobman('initcfg'); - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; + subLabel = '02'; + opt = setOptions('vismotion', subLabel); + opt = setDerivativesDir(opt); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - subID = '02'; + [BIDS, opt] = getData(opt); opt.orderBatches.coregister = 1; matlabbatch = {}; - matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subLabel); expectedBatch = returnExpectedBatch(); assertEqual(matlabbatch, expectedBatch); diff --git a/tests/test_setBatchSegmentation.m b/tests/test_setBatchSegmentation.m index 9e63d69a..7304369b 100644 --- a/tests/test_setBatchSegmentation.m +++ b/tests/test_setBatchSegmentation.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSegmentation %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -60,17 +62,17 @@ function test_setBatchSegmentationImages() function anatImage = returnLocalAnatFilename() - subID = '01'; + subLabel = '01'; opt.taskName = 'vislocalizer'; opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.subjects = {subID}; + opt.subjects = {subLabel}; opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - [anatImage, anatDataDir] = getAnatFilename(BIDS, subID, opt); + [anatImage, anatDataDir] = getAnatFilename(BIDS, subLabel, opt); anatImage = fullfile(anatDataDir, anatImage); diff --git a/tests/test_setBatchSelectAnat.m b/tests/test_setBatchSelectAnat.m index 14ba13c7..38023a7c 100644 --- a/tests/test_setBatchSelectAnat.m +++ b/tests/test_setBatchSelectAnat.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSelectAnat %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -12,18 +14,15 @@ function test_setBatchSelectAnatBasic() % add test to check if anat is not in first session % add test to check if anat is not a T1w - opt.dataDir = fullfile(fileparts(mfilename('fullpath')), '..', 'demos', ... - 'MoAE', 'output', 'MoAEpilot'); - opt.taskName = 'auditory'; + subLabel = '01'; + opt = setOptions('MoAE', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); - - subID = '01'; + [BIDS, opt] = getData(opt); matlabbatch = []; - matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subLabel); expectedBatch{1}.cfg_basicio.cfg_named_file.name = 'Anatomical'; diff --git a/tests/test_setBatchSkullStripping.m b/tests/test_setBatchSkullStripping.m index 51d5cba2..f6f88159 100644 --- a/tests/test_setBatchSkullStripping.m +++ b/tests/test_setBatchSkullStripping.m @@ -10,21 +10,17 @@ function test_setBatchSkullStrippingBasic() - subID = '01'; - - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.groups = {''}; - opt.subjects = {subID}; + subLabel = '01'; + opt = setOptions('vislocalizer', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); opt.orderBatches.segment = 2; matlabbatch = []; - matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subID); + matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel); expectedBatch = returnExpectedBatch(opt); diff --git a/tests/test_setBatchSmoothConImages.m b/tests/test_setBatchSmoothConImages.m index 87cf445e..6579c4ce 100644 --- a/tests/test_setBatchSmoothConImages.m +++ b/tests/test_setBatchSmoothConImages.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSmoothConImages %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,22 +10,18 @@ function test_setBatchSmoothConImagesBasic() - opt.groups = {''}; - opt.subjects = {'01', '02'}; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), ... - 'dummyData', ... - 'derivatives', ... - 'cpp_spm'); - opt.taskName = 'vismotion'; - funcFWHM = 6; conFWHM = 6; + opt = setOptions('vismotion'); + opt.subjects = {'01', '02'}; + opt.taskName = 'vismotion'; opt = checkOptions(opt); - [group, opt] = getData(opt); + + [~, opt] = getData(opt); matlabbatch = []; - matlabbatch = setBatchSmoothConImages(matlabbatch, group, opt, funcFWHM, conFWHM); + matlabbatch = setBatchSmoothConImages(matlabbatch, opt, funcFWHM, conFWHM); expectedBatch{1}.spm.spatial.smooth.fwhm = [6 6 6]; expectedBatch{1}.spm.spatial.smooth.prefix = 's6'; diff --git a/tests/test_setBatchSmoothing.m b/tests/test_setBatchSmoothing.m index 982219e3..ec5f0e2d 100644 --- a/tests/test_setBatchSmoothing.m +++ b/tests/test_setBatchSmoothing.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSmoothing %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_setBatchSmoothingFunc.m b/tests/test_setBatchSmoothingFunc.m index 0ea2ea31..66b6f60f 100644 --- a/tests/test_setBatchSmoothingFunc.m +++ b/tests/test_setBatchSmoothingFunc.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSmoothingFunc %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -11,21 +13,18 @@ function test_setBatchSmoothingFuncBasic() % TODO % need a test with several sessions and runs - subID = '01'; + subLabel = '01'; funcFWHM = 6; - opt.dataDir = fullfile(fileparts(mfilename('fullpath')), '..', 'demos', ... - 'MoAE', 'output', 'MoAEpilot'); - opt.taskName = 'auditory'; - + opt = setOptions('MoAE', subLabel); opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); % create dummy normalized file fileName = spm_BIDS(BIDS, 'data', ... - 'sub', subID, ... + 'sub', subLabel, ... 'task', opt.taskName, ... 'type', 'bold'); [filepath, filename, ext] = fileparts(fileName{1}); @@ -37,7 +36,7 @@ function test_setBatchSmoothingFuncBasic() system(sprintf('touch %s', fileName)); matlabbatch = []; - matlabbatch = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subID, funcFWHM); + matlabbatch = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel, funcFWHM); expectedBatch{1}.spm.spatial.smooth.fwhm = [6 6 6]; expectedBatch{1}.spm.spatial.smooth.dtype = 0; diff --git a/tests/test_setBatchSubjectLevelContrasts.m b/tests/test_setBatchSubjectLevelContrasts.m index 5fc7855c..5da6d60b 100644 --- a/tests/test_setBatchSubjectLevelContrasts.m +++ b/tests/test_setBatchSubjectLevelContrasts.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSubjectLevelContrasts %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -8,23 +10,21 @@ function test_setBatchSubjectLevelContrastsBasic() - subID = '01'; + subLabel = '01'; funcFWHM = 6; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); + opt = setOptions('vismotion', subLabel); opt.space = 'MNI'; - opt.taskName = 'vismotion'; opt.model.file = ... fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', ... 'models', ... 'model-visMotionLoc_smdl.json'); - opt = setDerivativesDir(opt); opt = checkOptions(opt); matlabbatch = []; - matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subID, funcFWHM); + matlabbatch = setBatchSubjectLevelContrasts(matlabbatch, opt, subLabel, funcFWHM); expectedBatch = []; expectedBatch{end + 1}.spm.stats.con.spmmat = {fullfile(opt.derivativesDir, ... diff --git a/tests/test_setBatchSubjectLevelGLMSpec.m b/tests/test_setBatchSubjectLevelGLMSpec.m index d2a13cd2..ec2305f0 100644 --- a/tests/test_setBatchSubjectLevelGLMSpec.m +++ b/tests/test_setBatchSubjectLevelGLMSpec.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSubjectLevelGLMSpec %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -9,29 +11,24 @@ function test_setBatchSubjectLevelGLMSpecBasic() funcFWHM = 6; - subID = '01'; + subLabel = '01'; iSes = 1; iRun = 1; - opt.subjects = {subID}; - opt.taskName = 'auditory'; - opt.dataDir = fullfile( ... - fileparts(mfilename('fullpath')), ... - '..', 'demos', 'MoAE', 'output', 'MoAEpilot'); - opt.model.file = fullfile(fileparts(mfilename('fullpath')), ... - '..', 'demos', 'MoAE', 'models', 'model-MoAE_smdl.json'); + opt = setOptions('MoAE', subLabel); + opt = checkOptions(opt); bidsCopyRawFolder(opt, 1); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); % create dummy preprocessed data - sessions = getInfo(BIDS, subID, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); [fileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{iSes}, runs{iRun}, opt); + subLabel, sessions{iSes}, runs{iRun}, opt); copyfile(fullfile(subFuncDataDir, fileName), ... fullfile(subFuncDataDir, ['s6wu', fileName])); @@ -40,7 +37,7 @@ function test_setBatchSubjectLevelGLMSpecBasic() fullfile(subFuncDataDir, ['rp_', strrep(fileName, '.nii', '.txt')]))); matlabbatch = []; - matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subID, funcFWHM); + matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel, funcFWHM); % TODO add assert % expectedBatch = returnExpectedBatch(); diff --git a/tests/test_setBatchSubjectLevelResults.m b/tests/test_setBatchSubjectLevelResults.m index b50a0b67..d6dce7b0 100644 --- a/tests/test_setBatchSubjectLevelResults.m +++ b/tests/test_setBatchSubjectLevelResults.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setBatchSubjectLevelResults %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> @@ -11,20 +13,18 @@ function test_setBatchSubjectLevelResultsBasic() iStep = 1; iCon = 1; - subID = '01'; + subLabel = '01'; funcFWHM = 6; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); + opt = setOptions('vismotion', subLabel); opt.space = 'MNI'; - opt.taskName = 'vismotion'; - opt = setDerivativesDir(opt); opt = checkOptions(opt); opt.result.Steps.Contrasts.Name = 'VisMot'; matlabbatch = []; - matlabbatch = setBatchSubjectLevelResults(matlabbatch, opt, subID, funcFWHM, iStep, iCon); + matlabbatch = setBatchSubjectLevelResults(matlabbatch, opt, subLabel, funcFWHM, iStep, iCon); expectedBatch = {}; @@ -56,13 +56,11 @@ function test_setBatchSubjectLevelResultsErrorMissingContrastName() iStep = 1; iCon = 1; - subID = '01'; + subLabel = '01'; funcFWHM = 6; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); + opt = setOptions('vismotion', subLabel); opt.space = 'MNI'; - opt.taskName = 'vismotion'; - opt = setDerivativesDir(opt); opt = checkOptions(opt); @@ -70,7 +68,7 @@ function test_setBatchSubjectLevelResultsErrorMissingContrastName() assertExceptionThrown( ... @()setBatchSubjectLevelResults(matlabbatch, ... opt, ... - subID, ... + subLabel, ... funcFWHM, ... iStep, ... iCon), ... @@ -83,23 +81,24 @@ function test_setBatchSubjectLevelResultsErrorNoMAtchingContrast() iStep = 1; iCon = 1; - subID = '01'; + subLabel = '01'; funcFWHM = 6; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.space = 'MNI'; - opt.taskName = 'vismotion'; - - opt.result.Steps.Contrasts.Name = 'NotAContrast'; + subLabel = '01'; + funcFWHM = 6; + opt = setOptions('vismotion', subLabel); + opt.space = 'MNI'; opt = setDerivativesDir(opt); opt = checkOptions(opt); + opt.result.Steps.Contrasts.Name = 'NotAContrast'; + matlabbatch = []; assertExceptionThrown( ... @()setBatchSubjectLevelResults(matlabbatch, ... opt, ... - subID, ... + subLabel, ... funcFWHM, ... iStep, ... iCon), ... diff --git a/tests/test_setDefaultFields.m b/tests/test_setDefaultFields.m index 548101ae..3debd2bb 100644 --- a/tests/test_setDefaultFields.m +++ b/tests/test_setDefaultFields.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_setDefaultFields %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_cleanCrash.m b/tests/test_unit_cleanCrash.m similarity index 81% rename from tests/test_cleanCrash.m rename to tests/test_unit_cleanCrash.m index d1781f88..ae8cbfbe 100644 --- a/tests/test_cleanCrash.m +++ b/tests/test_unit_cleanCrash.m @@ -1,4 +1,6 @@ -function test_suite = test_cleanCrash %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_cleanCrash %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_copyGraphWindownOutput.m b/tests/test_unit_copyGraphWindownOutput.m similarity index 93% rename from tests/test_copyGraphWindownOutput.m rename to tests/test_unit_copyGraphWindownOutput.m index 0958cc5a..b0698f7b 100644 --- a/tests/test_copyGraphWindownOutput.m +++ b/tests/test_unit_copyGraphWindownOutput.m @@ -1,4 +1,6 @@ -function test_suite = test_copyGraphWindownOutput %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_copyGraphWindownOutput %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_createDataDictionary.m b/tests/test_unit_createDataDictionary.m similarity index 65% rename from tests/test_createDataDictionary.m rename to tests/test_unit_createDataDictionary.m index 1ee7ceb5..4cc3bdd0 100644 --- a/tests/test_createDataDictionary.m +++ b/tests/test_unit_createDataDictionary.m @@ -1,4 +1,6 @@ -function test_suite = test_createDataDictionary %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_createDataDictionary %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -8,24 +10,23 @@ function test_createDataDictionaryBasic() - subID = '01'; + subLabel = '01'; iSes = 1; iRun = 1; - opt.taskName = 'vislocalizer'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.groups = {''}; - opt.subjects = {'01'}; + opt = setOptions('vislocalizer', subLabel); + + opt = checkOptions(opt); - [~, opt, BIDS] = getData(opt); + [BIDS, opt] = getData(opt); - sessions = getInfo(BIDS, subID, opt, 'Sessions'); + sessions = getInfo(BIDS, subLabel, opt, 'Sessions'); - runs = getInfo(BIDS, subID, opt, 'Runs', sessions{iSes}); + runs = getInfo(BIDS, subLabel, opt, 'Runs', sessions{iSes}); [fileName, subFuncDataDir] = getBoldFilename( ... BIDS, ... - subID, sessions{iSes}, runs{iRun}, opt); + subLabel, sessions{iSes}, runs{iRun}, opt); createDataDictionary(subFuncDataDir, fileName, 3); diff --git a/tests/test_getFFXdir.m b/tests/test_unit_getFFXdir.m similarity index 72% rename from tests/test_getFFXdir.m rename to tests/test_unit_getFFXdir.m index ba269464..09fecf07 100644 --- a/tests/test_getFFXdir.m +++ b/tests/test_unit_getFFXdir.m @@ -1,4 +1,6 @@ -function test_suite = test_getFFXdir %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getFFXdir %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -9,19 +11,17 @@ function test_getFFXdirBasic() funcFWFM = 0; - subID = '01'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'funcLocalizer'; + subLabel = '01'; + opt = setOptions('funcLocalizer', subLabel); opt = setDerivativesDir(opt); - opt = checkOptions(opt); expectedOutput = fullfile(fileparts(mfilename('fullpath')), 'dummyData', 'derivatives', ... 'cpp_spm', 'sub-01', 'stats', 'ffx_task-funcLocalizer', ... 'ffx_space-MNI_FWHM-0'); - ffxDir = getFFXdir(subID, funcFWFM, opt); + ffxDir = getFFXdir(subLabel, funcFWFM, opt); assertEqual(exist(expectedOutput, 'dir'), 7); @@ -30,20 +30,18 @@ function test_getFFXdirBasic() function test_getFFXdirMvpa() funcFWFM = 6; - subID = '02'; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'nBack'; - opt.space = 'individual'; + subLabel = '02'; + opt = setOptions('nBack', subLabel); + opt.space = 'individual'; opt = setDerivativesDir(opt); - opt = checkOptions(opt); expectedOutput = fullfile(fileparts(mfilename('fullpath')), 'dummyData', 'derivatives', ... 'cpp_spm', 'sub-02', 'stats', 'ffx_task-nBack', ... 'ffx_space-individual_FWHM-6'); - ffxDir = getFFXdir(subID, funcFWFM, opt); + ffxDir = getFFXdir(subLabel, funcFWFM, opt); assertEqual(exist(expectedOutput, 'dir'), 7); diff --git a/tests/test_getFuncVoxelDims.m b/tests/test_unit_getFuncVoxelDims.m similarity index 90% rename from tests/test_getFuncVoxelDims.m rename to tests/test_unit_getFuncVoxelDims.m index f7800da6..0527b2a4 100644 --- a/tests/test_getFuncVoxelDims.m +++ b/tests/test_unit_getFuncVoxelDims.m @@ -1,4 +1,6 @@ -function test_suite = test_getFuncVoxelDims %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getFuncVoxelDims %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_getGrpLevelContrastToCompute.m b/tests/test_unit_getGrpLevelContrastToCompute.m similarity index 90% rename from tests/test_getGrpLevelContrastToCompute.m rename to tests/test_unit_getGrpLevelContrastToCompute.m index 6ac688d0..7b1723c5 100644 --- a/tests/test_getGrpLevelContrastToCompute.m +++ b/tests/test_unit_getGrpLevelContrastToCompute.m @@ -1,4 +1,6 @@ -function test_suite = test_getGrpLevelContrastToCompute %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getGrpLevelContrastToCompute %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_unit_getInfo.m b/tests/test_unit_getInfo.m new file mode 100644 index 00000000..eed1dcfa --- /dev/null +++ b/tests/test_unit_getInfo.m @@ -0,0 +1,66 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getInfo %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_getInfoBasic() + + subLabel = 'ctrl01'; + opt = setOptions('vismotion', subLabel); + opt = setDerivativesDir(opt); + opt = checkOptions(opt); + + %% Get sessions from BIDS + info = 'sessions'; + + [BIDS, opt] = getData(opt); + sessions = getInfo(BIDS, subLabel, opt, info); + assert(all(strcmp(sessions, {'01' '02'}))); + + %% Get runs from BIDS + info = 'runs'; + + session = '01'; + + [BIDS, opt] = getData(opt); + runs = getInfo(BIDS, subLabel, opt, info, session); + assert(all(strcmp(runs, {'1' '2'}))); + + %% Get filename from BIDS + info = 'filename'; + + session = '01'; + run = '1'; + + [BIDS, opt] = getData(opt); + filename = getInfo(BIDS, subLabel, opt, info, session, run, 'bold'); + FileName = fullfile(fileparts(mfilename('fullpath')), 'dummyData', ... + 'derivatives', 'cpp_spm', ... + ['sub-' subLabel], ['ses-' session], 'func', ... + ['sub-' subLabel, ... + '_ses-' session, ... + '_task-' opt.taskName, ... + '_run-' run, ... + '_bold.nii']); + + assert(strcmp(filename, FileName)); + + %% Get runs from BIDS when no run in filename + subLabel = 'ctrl01'; + opt = setOptions('vislocalizer', subLabel); + opt = checkOptions(opt); + + info = 'runs'; + + session = '01'; + + [BIDS, opt] = getData(opt); + runs = getInfo(BIDS, subLabel, opt, info, session); + assert(strcmp(runs, {''})); + +end diff --git a/tests/test_getPrefix.m b/tests/test_unit_getPrefix.m similarity index 98% rename from tests/test_getPrefix.m rename to tests/test_unit_getPrefix.m index dfbdeccb..27e2e50f 100644 --- a/tests/test_getPrefix.m +++ b/tests/test_unit_getPrefix.m @@ -1,4 +1,6 @@ -function test_suite = test_getPrefix %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getPrefix %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -10,6 +12,7 @@ function test_getPrefixSTC() step = 'realign'; funcFWHM = 6; + opt.metadata.SliceTiming = 1:0.2:1.8; opt.sliceOrder = 1:10; @@ -26,6 +29,7 @@ function test_getPrefixSTC() function test_getPrefixNoSTC() step = 'realign'; + opt.metadata = []; opt.sliceOrder = []; diff --git a/tests/test_getRFXdir.m b/tests/test_unit_getRFXdir.m similarity index 83% rename from tests/test_getRFXdir.m rename to tests/test_unit_getRFXdir.m index 3473ae94..cbdaadec 100644 --- a/tests/test_getRFXdir.m +++ b/tests/test_unit_getRFXdir.m @@ -1,4 +1,6 @@ -function test_suite = test_getRFXdir %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getRFXdir %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -11,9 +13,7 @@ function test_getRFXdirBasic() funcFWHM = 0; conFWHM = 0; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'funcLocalizer'; - + opt = setOptions('funcLocalizer'); opt = setDerivativesDir(opt); rfxDir = getRFXdir(opt, funcFWHM, conFWHM); diff --git a/tests/test_getSliceOrder.m b/tests/test_unit_getSliceOrder.m similarity index 72% rename from tests/test_getSliceOrder.m rename to tests/test_unit_getSliceOrder.m index 25e06a14..12f55d2a 100644 --- a/tests/test_getSliceOrder.m +++ b/tests/test_unit_getSliceOrder.m @@ -1,4 +1,6 @@ -function test_suite = test_getSliceOrder %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getSliceOrder %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -7,11 +9,8 @@ end function test_getSliceOrderBasic() - % Small test to ensure that getSliceOrder returns what we asked for - - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vismotion'; + opt = setOptions('vismotion'); opt = checkOptions(opt); [~, opt] = getData(opt); @@ -40,10 +39,7 @@ function test_getSliceOrderBasic() function test_getSliceOrderEmpty() - %% Get empty slice order from BIDS - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.taskName = 'vislocalizer'; - + opt = setOptions('vislocalizer'); opt = checkOptions(opt); [~, opt] = getData(opt); @@ -56,12 +52,9 @@ function test_getSliceOrderEmpty() function test_getSliceOrderFromOptions() - %% Get slice order from options - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); + opt = setOptions('vislocalizer'); opt.STC_referenceSlice = 1000; opt.sliceOrder = 0:250:2000; - opt.taskName = 'vislocalizer'; - opt = checkOptions(opt); [~, opt] = getData(opt); diff --git a/tests/test_unit_getSubjectList.m b/tests/test_unit_getSubjectList.m new file mode 100644 index 00000000..4d4a6e5b --- /dev/null +++ b/tests/test_unit_getSubjectList.m @@ -0,0 +1,76 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_getSubjectList %#ok<*STOUT> + try % assignment of 'localfunctions' is necessary in Matlab >= 2016 + test_functions = localfunctions(); %#ok<*NASGU> + catch % no problem; early Matlab versions can use initTestSuite fine + end + initTestSuite; +end + +function test_getSubjectListNone() + + opt = setOptions('vismotion'); + opt = setDerivativesDir(opt); + opt = checkOptions(opt); + + BIDS = bids.layout(opt.derivativesDir); + + %% Get all groups all subjects + opt = getSubjectList(BIDS, opt); + + assertEqual(opt.subjects, ... + {'01' '02' 'blind01' 'blind02' 'ctrl01' 'ctrl02'}'); + +end + +function test_getSubjectListGroup() + + opt = setOptions('vismotion'); + opt = setDerivativesDir(opt); + opt = checkOptions(opt); + + BIDS = bids.layout(opt.derivativesDir); + + %% Get all subjects of a group and a subject from another group + opt.groups = {'blind'}; + opt.subjects = {'ctrl01'}; + + opt = getSubjectList(BIDS, opt); + + % 'sub-02' is defined a blind in the participants.tsv + assertEqual(opt.subjects, {'02', 'blind01', 'blind02', 'ctrl01'}'); + +end + +function test_getSubjectListBasic() + + opt = setOptions('vismotion'); + opt = setDerivativesDir(opt); + opt = checkOptions(opt); + + BIDS = bids.layout(opt.derivativesDir); + + %% Get some specified subjects + opt.groups = {''}; + opt.subjects = {'01', '02'; 'ctrl02', 'blind02'}; + + opt = getSubjectList(BIDS, opt); + + assertEqual(opt.subjects, {'01', '02', 'blind02', 'ctrl02'}'); + +end + +function test_getSubjectListErrorSubject() + + opt = setOptions('vismotion', '03'); + opt = setDerivativesDir(opt); + opt = checkOptions(opt); + + BIDS = bids.layout(opt.derivativesDir); + + assertExceptionThrown( ... + @()getSubjectList(BIDS, opt), ... + 'getSubjectList:noMatchingSubject'); + +end diff --git a/tests/test_manageWorkersPool.m b/tests/test_unit_manageWorkersPool.m similarity index 91% rename from tests/test_manageWorkersPool.m rename to tests/test_unit_manageWorkersPool.m index 9754a9ea..b7c6c6f8 100644 --- a/tests/test_manageWorkersPool.m +++ b/tests/test_unit_manageWorkersPool.m @@ -1,4 +1,6 @@ -function test_suite = test_manageWorkersPool %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_manageWorkersPool %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_returnDefaultResultsStructure.m b/tests/test_unit_returnDefaultResultsStructure.m similarity index 93% rename from tests/test_returnDefaultResultsStructure.m rename to tests/test_unit_returnDefaultResultsStructure.m index 75cd688c..8ef9ec10 100644 --- a/tests/test_returnDefaultResultsStructure.m +++ b/tests/test_unit_returnDefaultResultsStructure.m @@ -1,6 +1,6 @@ % (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function test_suite = test_returnDefaultResultsStructure %#ok<*STOUT> +function test_suite = test_unit_returnDefaultResultsStructure %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_returnEmptyModel.m b/tests/test_unit_returnEmptyModel.m similarity index 83% rename from tests/test_returnEmptyModel.m rename to tests/test_unit_returnEmptyModel.m index 343ee25b..cb006589 100644 --- a/tests/test_returnEmptyModel.m +++ b/tests/test_unit_returnEmptyModel.m @@ -1,6 +1,6 @@ -% (C) Copyright 2019 CPP BIDS SPM-pipeline developers +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers -function test_suite = test_returnEmptyModel %#ok<*STOUT> +function test_suite = test_unit_returnEmptyModel %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_setDerivativesDir.m b/tests/test_unit_setDerivativesDir.m similarity index 91% rename from tests/test_setDerivativesDir.m rename to tests/test_unit_setDerivativesDir.m index 4afab5cb..4df4a2cc 100644 --- a/tests/test_setDerivativesDir.m +++ b/tests/test_unit_setDerivativesDir.m @@ -1,4 +1,6 @@ -function test_suite = test_setDerivativesDir %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_setDerivativesDir %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_specifyContrasts.m b/tests/test_unit_specifyContrasts.m similarity index 80% rename from tests/test_specifyContrasts.m rename to tests/test_unit_specifyContrasts.m index 5c3ff220..45fb979c 100644 --- a/tests/test_specifyContrasts.m +++ b/tests/test_unit_specifyContrasts.m @@ -1,4 +1,6 @@ -function test_suite = test_specifyContrasts %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_specifyContrasts %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine @@ -9,19 +11,18 @@ function test_specifyContrastsBasic() % Small test to ensure that pmCon returns what we asked for - subID = '01'; + subLabel = '01'; funcFWFM = 6; - opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), 'dummyData'); - opt.space = 'MNI'; - opt.taskName = 'vismotion'; + opt = setOptions('vismotion', subLabel); + opt = checkOptions(opt); + opt = setDerivativesDir(opt); + opt.model.file = ... fullfile(fileparts(mfilename('fullpath')), ... 'dummyData', 'models', 'model-visMotionLoc_smdl.json'); - opt = setDerivativesDir(opt); - - ffxDir = getFFXdir(subID, funcFWFM, opt); + ffxDir = getFFXdir(subLabel, funcFWFM, opt); contrasts = specifyContrasts(ffxDir, opt.taskName, opt); diff --git a/tests/test_validationInputFile.m b/tests/test_unit_validationInputFile.m similarity index 90% rename from tests/test_validationInputFile.m rename to tests/test_unit_validationInputFile.m index b72e8413..29ad4135 100644 --- a/tests/test_validationInputFile.m +++ b/tests/test_unit_validationInputFile.m @@ -1,4 +1,6 @@ -function test_suite = test_validationInputFile %#ok<*STOUT> +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + +function test_suite = test_unit_validationInputFile %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_utils.m b/tests/test_utils.m index 4418b9cc..ec276918 100644 --- a/tests/test_utils.m +++ b/tests/test_utils.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_utils %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/test_writeDatasetDescription.m b/tests/test_writeDatasetDescription.m index cbb964ff..a88804f7 100644 --- a/tests/test_writeDatasetDescription.m +++ b/tests/test_writeDatasetDescription.m @@ -1,3 +1,5 @@ +% (C) Copyright 2020 CPP BIDS SPM-pipeline developers + function test_suite = test_writeDatasetDescription %#ok<*STOUT> try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> diff --git a/tests/utils/setOptions.m b/tests/utils/setOptions.m new file mode 100644 index 00000000..b9c9c4d3 --- /dev/null +++ b/tests/utils/setOptions.m @@ -0,0 +1,27 @@ +% (C) Copyright 2021 CPP BIDS SPM-pipeline developers + +function opt = setOptions(task, subLabel) + + if strcmp(task, 'MoAE') + + opt.dataDir = fullfile( ... + fileparts(mfilename('fullpath')), ... + '..', '..', 'demos', 'MoAE', 'output', 'MoAEpilot'); + opt.model.file = fullfile( ... + fileparts(mfilename('fullpath')), ... + '..', '..', 'demos', 'MoAE', 'models', 'model-MoAE_smdl.json'); + + opt.taskName = 'auditory'; + + else + + opt.taskName = task; + opt.derivativesDir = fullfile(fileparts(mfilename('fullpath')), '..', 'dummyData'); + + end + + if nargin > 1 + opt.subjects = {subLabel}; + end + +end