diff --git a/.circleci/config.yml b/.circleci/config.yml index 7c173d9a7..3ead6b563 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -61,6 +61,7 @@ jobs: datalad get sub-0[1-2]/anat/*MNI*mask.nii.gz \ sub-0[1-2]/anat/*MNI*T1w.nii.gz \ sub-0[1-2]/func/*MNI*desc-preproc*bold.nii.gz \ + sub-0[1-2]/func/*MNI*mask.nii.gz \ sub-*/func/*tsv \ sub-*/func/*json -J 12 datalad status diff --git a/demos/bayes/ds000114_run.m b/demos/bayes/ds000114_run.m index 5ba628d08..8a95fb2f0 100644 --- a/demos/bayes/ds000114_run.m +++ b/demos/bayes/ds000114_run.m @@ -27,7 +27,7 @@ models_dir = fullfile(root_dir, 'models'); -participant_label = {'[0-9]*'}; +participant_label = {'[0-9]*'}; %#ok<*NASGU> if TESTING participant_label = {'^0[12]$'}; end @@ -56,6 +56,14 @@ mutliverse.wm_csf = {'none', 'basic', 'full'}; mutliverse.non_steady_state = [false, true]; +if TESTING + mutliverse.strategy = {'motion', 'wm_csf', 'scrub', 'non_steady_state'}; + mutliverse.motion = {'none', 'basic'}; + mutliverse.scrub = [false, true]; + mutliverse.wm_csf = {'none'}; + mutliverse.non_steady_state = false; +end + create_model_families(models_dir, default_model_file, mutliverse); %% Statistics @@ -92,6 +100,12 @@ function create_model_families(models_dir, default_model_file, mutliverse) % TODO incorporate into bidspm % TODO add support for 12 motion regressors + strategyToSkip = fieldnames(mutliverse); + idxStrategyToSkip = ~ismember(fieldnames(mutliverse), mutliverse.strategy); + strategyToSkip = strategyToSkip(idxStrategyToSkip); + for i = 1:numel(strategyToSkip) + mutliverse.(strategyToSkip{i}) = {''}; + end for i = 1:numel(mutliverse.motion) for j = 1:numel(mutliverse.scrub) diff --git a/lib/bids-matlab b/lib/bids-matlab index 43eb70b8d..aaa0007cf 160000 --- a/lib/bids-matlab +++ b/lib/bids-matlab @@ -1 +1 @@ -Subproject commit 43eb70b8d1879f7742de66170edaeb681c1409d5 +Subproject commit aaa0007cfee69df2d9cdcc7d04a16517465d2cdc diff --git a/src/batches/preproc/setBatchSmoothingFunc.m b/src/batches/preproc/setBatchSmoothingFunc.m index 0e5fb4d79..dbe3061de 100644 --- a/src/batches/preproc/setBatchSmoothingFunc.m +++ b/src/batches/preproc/setBatchSmoothingFunc.m @@ -1,4 +1,4 @@ -function [matlabbatch, allRT] = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel) +function [matlabbatch, srcMetadata] = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel) % % Creates a batch to smooth the bold files of a subject % @@ -42,7 +42,7 @@ [sessions, nbSessions] = getInfo(BIDS, subLabel, opt, 'Sessions'); allFiles = []; - allRT = []; + srcMetadata = struct('RepetitionTime', [], 'SliceTimingCorrected', []); for iSes = 1:nbSessions @@ -66,15 +66,10 @@ for iFile = 1:size(fileName, 1) files{iFile, 1} = validationInputFile(subFuncDataDir(iFile, :), ... fileName(iFile, :)); %#ok<*AGROW> - - if isfield(metadata{iFile}, 'RepetitionTime') - allRT(end + 1) = metadata{iFile}.RepetitionTime; - else - allRT(end + 1) = nan; - end - end + srcMetadata = collectSrcMetadata(srcMetadata, metadata); + % add the files to list allFilesTemp = cellstr(char(files)); allFiles = [allFiles; allFilesTemp]; @@ -91,3 +86,21 @@ num2str(opt.fwhm.func)]); end + +function srcMetadata = collectSrcMetadata(srcMetadata, metadata) + for iFile = 1:numel(metadata) + + if isfield(metadata{iFile}, 'RepetitionTime') + srcMetadata.RepetitionTime(end + 1) = metadata{iFile}.RepetitionTime; + else + srcMetadata.RepetitionTime(end + 1) = nan; + end + + if isfield(metadata{iFile}, 'SliceTimingCorrected') + srcMetadata.SliceTimingCorrected(end + 1) = metadata{iFile}.SliceTimingCorrected; + else + srcMetadata.SliceTimingCorrected(end + 1) = false; + end + + end +end diff --git a/src/bids/getAnatFilename.m b/src/bids/getAnatFilename.m index d1d7877a7..53c05d5da 100644 --- a/src/bids/getAnatFilename.m +++ b/src/bids/getAnatFilename.m @@ -72,9 +72,14 @@ end if numel(anat) > nbImgToReturn - tmp = bids.internal.format_path(anat(1:nbImgToReturn)); - msg = sprintf('More than %i anat file. Found: %i.\n\nTaking the first %i:%s\n', ... + + tmp = anat(1:nbImgToReturn); + tmp = strrep(tmp, [BIDS.pth filesep], ''); + tmp = bids.internal.format_path(tmp); + msg = sprintf(['More than %i anat file in:\n%s.', ... + '\n\nFound: %i.\nTaking the first %i:%s'], ... nbImgToReturn, ... + bids.internal.format_path(BIDS.pth), ... numel(anat), ... nbImgToReturn, ... bids.internal.create_unordered_list(tmp)); diff --git a/src/bids/getAndCheckSliceOrder.m b/src/bids/getAndCheckSliceOrder.m index 5d6bdab46..286c26132 100644 --- a/src/bids/getAndCheckSliceOrder.m +++ b/src/bids/getAndCheckSliceOrder.m @@ -32,6 +32,22 @@ % TODO support for DelayTime and AcquisitionDuration + warning('OFF', 'query:unknowMetadata'); + + filter.target = 'SliceTimingCorrected'; + sliceTimingCorrected = bids.query(BIDS, 'metadata', filter); + stCorrected = areAllSliceTimeCorrected(sliceTimingCorrected); + + % for GLM if data is not slice time corrected + % we will rely on the number of slices + % to figure out the temporal resolution + % to do convolution at. + if strcmp(opt.pipeline.type, 'stats') && ~stCorrected + sliceOrder = []; + warning('ON', 'query:unknowMetadata'); + return + end + filter.target = 'SliceTiming'; sliceTiming = bids.query(BIDS, 'metadata', filter); @@ -48,23 +64,20 @@ id = 'noSliceTimingFound'; logger('WARNING', msg, 'id', id, 'filename', mfilename(), 'options', opt); + warning('ON', 'query:unknowMetadata'); return end sliceTimingLengths = cellfun('length', sliceTiming); if length(unique(sliceTimingLengths)) > 1 - - sliceOrder = []; + warning('ON', 'query:unknowMetadata'); msg = sprintf(['Inconsistent slice timing found for filter:\n%s.\n\n', ... 'Number of slice per volume seems different across bold files.'], ... bids.internal.create_unordered_list(filter)); id = 'inconsistentSliceTimingLength'; logger('ERROR', msg, 'id', id, 'filename', mfilename(), 'options', opt); - - return - end % all slice timing should be the same, @@ -82,6 +95,7 @@ id = 'inconsistentSliceTimingValues'; logger('WARNING', msg, 'id', id, 'filename', mfilename(), 'options', opt); + warning('ON', 'query:unknowMetadata'); return end @@ -90,4 +104,21 @@ msg = ' SLICE TIMING INFORMATION EXTRACTED FROM METADATA.'; logger('INFO', msg, 'options', opt, 'filename', mfilename()); + warning('ON', 'query:unknowMetadata'); + +end + +function stCorrected = areAllSliceTimeCorrected(values) + if isempty(values) || ... + (~iscell(values) && ~values) + stCorrected = false; + return + end + if iscell(values) && any(cellfun('isempty', values)) + stCorrected = false; + return + end + + stCorrected = all(values{1}); + end diff --git a/src/bids_model/getInclusiveMask.m b/src/bids_model/getInclusiveMask.m index 23f8993b2..8f9f15232 100644 --- a/src/bids_model/getInclusiveMask.m +++ b/src/bids_model/getInclusiveMask.m @@ -40,12 +40,14 @@ file = file{1}; elseif numel(file) > 1 - file = bids.internal.format_path(file); - msg = sprintf(['More than 1 mask image found for %s.\n\n' ... - 'Taking the first one:\n\t%s\n\nfrom:%s\n\n'], ... + tmp = strrep(file, [BIDS.pth, filesep], ''); + tmp = bids.internal.format_path(tmp); + msg = sprintf(['More than 1 mask image found in:\n %s\nfor filter: %s.\n\n' ... + 'Taking the first one:\n\t%s\n\nfrom:%s'], ... + BIDS.pth, ... bids.internal.create_unordered_list(mask), ... - file{1}, ... - bids.internal.create_unordered_list(file)); + tmp{1}, ... + bids.internal.create_unordered_list(tmp)); id = 'tooManyMasks'; logger('WARNING', msg, 'id', id, 'options', opt, 'filename', mfilename()); file = file{1}; diff --git a/src/cli/getOptionsFromCliArgument.m b/src/cli/getOptionsFromCliArgument.m index c7528d745..cca09fb71 100644 --- a/src/cli/getOptionsFromCliArgument.m +++ b/src/cli/getOptionsFromCliArgument.m @@ -204,14 +204,15 @@ if ~isfield(args.Results, 'space') return end - if ~isempty(args.Results.space) - if isfield(opt, 'space') && ~all(ismember(args.Results.space, opt.space)) + + if isfield(opt, 'space') && ~all(ismember(args.Results.space, opt.space)) + if ~isempty(args.Results.space) overrideMsg('space', convertToString(args.Results.space), ... 'space', convertToString(opt.space), ... opt); end - opt.space = args.Results.space; end + opt.space = args.Results.space; end function output = convertToString(input) diff --git a/src/reports/boilerplate_preprocess.mustache b/src/reports/boilerplate_preprocess.mustache index 7169b2d58..399847e19 100644 --- a/src/reports/boilerplate_preprocess.mustache +++ b/src/reports/boilerplate_preprocess.mustache @@ -7,8 +7,8 @@ The (f)MRI data were pre-processed with {{>computing_environment}}. {{! TODO mention which task were processed}} The preprocessing of the functional images was performed in the following order: -{{#dummy_scans}}- removing of dummy scans -{{/dummy_scans}} +{{#dummyScans}}- removing of dummy scans +{{/dummyScans}} {{#stc}}- slice timing correction {{/stc}} - realignment{{#unwarp}} and unwarping{{/unwarp}} diff --git a/src/reports/partials/remove_dummies.mustache b/src/reports/partials/remove_dummies.mustache index 1ea800040..5e24ad255 100644 --- a/src/reports/partials/remove_dummies.mustache +++ b/src/reports/partials/remove_dummies.mustache @@ -1,2 +1,2 @@ -{{#dummy_scans}}{{nb}} dummy scans were removed to allow for signal stabilization. -{{/dummy_scans}} +{{#dummyScans}}{{nb}} dummy scans were removed to allow for signal stabilization. +{{/dummyScans}} diff --git a/src/stats/subject_level/createAndReturnCounfoundMatFile.m b/src/stats/subject_level/createAndReturnCounfoundMatFile.m index 15938e3f9..4cfea5282 100644 --- a/src/stats/subject_level/createAndReturnCounfoundMatFile.m +++ b/src/stats/subject_level/createAndReturnCounfoundMatFile.m @@ -59,6 +59,9 @@ opt.query.task = opt.taskName; ffxDir = getFFXdir(bf.entities.sub, opt); + if exist(ffxDir, 'dir') == 0 + spm_mkdir(ffxDir); + end counfoundFile = fullfile(ffxDir, bf.filename); if isempty(names) || isempty(R) diff --git a/src/stats/subject_level/getFFXdir.m b/src/stats/subject_level/getFFXdir.m index 56a8c14c4..6cecc14bd 100644 --- a/src/stats/subject_level/getFFXdir.m +++ b/src/stats/subject_level/getFFXdir.m @@ -1,6 +1,6 @@ function ffxDir = getFFXdir(subLabel, opt) % - % Sets the name the FFX directory and creates it if it does not exist + % Sets the name the FFX directory % % USAGE:: % @@ -39,8 +39,6 @@ ffxDir = [ffxDir '_roi']; end - spm_mkdir(ffxDir); - end function string = deregexify(string) diff --git a/src/workflows/preproc/bidsSmoothing.m b/src/workflows/preproc/bidsSmoothing.m index af7247ae4..70002a6a3 100644 --- a/src/workflows/preproc/bidsSmoothing.m +++ b/src/workflows/preproc/bidsSmoothing.m @@ -1,4 +1,4 @@ -function bidsSmoothing(opt) +function srcMetadata = bidsSmoothing(opt) % % This performs smoothing to the functional data using a full width % half maximum smoothing kernel of size "opt.fwhm.func". @@ -33,7 +33,7 @@ function bidsSmoothing(opt) opt.taskName = bids.query(BIDS, 'tasks'); end - allRT = {}; + srcMetadata = struct('RepetitionTime', [], 'SliceTimingCorrected', []); unRenamedFiles = {}; for iSub = 1:numel(opt.subjects) @@ -49,10 +49,10 @@ function bidsSmoothing(opt) switch modality case 'func' matlabbatch = {}; - [matlabbatch, allRT{iSub}] = setBatchSmoothingFunc(matlabbatch, ... - BIDS, ... - opt, ... - subLabel); + [matlabbatch, srcMetadata(iSub)] = setBatchSmoothingFunc(matlabbatch, ... + BIDS, ... + opt, ... + subLabel); [~, unRenamedFiles{iSub}] = saveAndRunWorkflow(matlabbatch, ... ['smoothing_FWHM-', ... num2str(opt.fwhm.func)], ... @@ -81,25 +81,41 @@ function bidsSmoothing(opt) opt.query.space = opt.space; createdFiles = bidsRename(opt); + transferMetadata(opt, createdFiles, unRenamedFiles, srcMetadata); + +end + +function transferMetadata(opt, createdFiles, unRenamedFiles, srcMetadata) % add Repetition Time to smoothed files metadata + + metadataToTransfer = fieldnames(srcMetadata); + for iSub = 1:numel(opt.subjects) + subLabel = opt.subjects{iSub}; + for iFile = 1:numel(createdFiles) + bf = bids.File(createdFiles{iFile}); if ~strcmp(bf.suffix, 'bold') || ~strcmp(bf.entities.sub, subLabel) continue end + jsonFile = spm_file(createdFiles{iFile}, 'ext', '.json'); if exist(jsonFile, 'file') + metadata = bids.util.jsondecode(jsonFile); idx = ~cellfun('isempty', ... strfind(unRenamedFiles{iSub}{1}.files, ... metadata.SpmFilename)); - rt = allRT{iSub}(idx); - metadata.RepetitionTime = rt; + + for i = 1:numel(metadataToTransfer) + metadata.(metadataToTransfer{i}) = srcMetadata(iSub).(metadataToTransfer{i})(idx); + end + bids.util.jsonencode(jsonFile, metadata); end + end end - end diff --git a/tests/data/derivatives/bidspm-preproc/task-vislocalizer_bold.json b/tests/data/derivatives/bidspm-preproc/task-vislocalizer_bold.json index c2e551ee2..f05568f68 100755 --- a/tests/data/derivatives/bidspm-preproc/task-vislocalizer_bold.json +++ b/tests/data/derivatives/bidspm-preproc/task-vislocalizer_bold.json @@ -9,5 +9,6 @@ "SliceThickness": 3, "FlipAngle": 54, "NumberOfVolumesDiscardedByUser": 4, - "TaskName": "vislocalizer" + "TaskName": "vislocalizer", + "SliceTimingCorrected": false } diff --git a/tests/data/derivatives/bidspm-preproc/task-vismotion_bold.json b/tests/data/derivatives/bidspm-preproc/task-vismotion_bold.json index b841450e7..f40609204 100755 --- a/tests/data/derivatives/bidspm-preproc/task-vismotion_bold.json +++ b/tests/data/derivatives/bidspm-preproc/task-vismotion_bold.json @@ -2,6 +2,16 @@ "ImageType": "ORIGINAL\\PRIMARY\\M\\ND\\MOSAIC", "Modality": "MR", "TotalReadoutTime": 1.0035123, + "SliceTimingCorrected": true, + "RepetitionTime": 1.5, + "PhaseEncodingDirection": "j-", + "EffectiveEchoSpacing": 0.00024499812, + "EchoTime": 0.03, + "SliceThickness": 3, + "FlipAngle": 54, + "NumberOfVolumesDiscardedByUser": 8, + "TaskName": "vismotion", + "PixelBandwidth": 15.873, "SliceTiming": [ 0.5475, 0, @@ -45,14 +55,5 @@ 0.3275, 0.71, 0.165 - ], - "RepetitionTime": 1.5, - "PhaseEncodingDirection": "j-", - "EffectiveEchoSpacing": 0.00024499812, - "EchoTime": 0.03, - "SliceThickness": 3, - "FlipAngle": 54, - "NumberOfVolumesDiscardedByUser": 8, - "TaskName": "vismotion", - "PixelBandwidth": 15.873 + ] } diff --git a/tests/data/derivatives/bidspm-preproc/task-vismotion_desc-preproc_bold.json b/tests/data/derivatives/bidspm-preproc/task-vismotion_desc-preproc_bold.json new file mode 100755 index 000000000..5797b581f --- /dev/null +++ b/tests/data/derivatives/bidspm-preproc/task-vismotion_desc-preproc_bold.json @@ -0,0 +1,5 @@ +{ + "SliceTimingCorrected": true, + "RepetitionTime": 1.5, + "TaskName": "vismotion" +} diff --git a/tests/data/models/model-vislocalizer_smdl.json b/tests/data/models/model-vislocalizer_smdl.json index ec86cb85b..d30e6ea7a 100644 --- a/tests/data/models/model-vislocalizer_smdl.json +++ b/tests/data/models/model-vislocalizer_smdl.json @@ -47,7 +47,7 @@ }, "Software": { "SPM": { - "InclusiveMaskingThreshold": 0, + "InclusiveMaskingThreshold": 0.8, "SerialCorrelation": "FAST" }, "bidspm": { diff --git a/tests/data/models/model-vismotion-desc-1pt6acq_smdl.json b/tests/data/models/model-vismotion-desc-1pt6acq_smdl.json index 851ad383d..d964906ce 100644 --- a/tests/data/models/model-vismotion-desc-1pt6acq_smdl.json +++ b/tests/data/models/model-vismotion-desc-1pt6acq_smdl.json @@ -49,7 +49,8 @@ }, "Software": { "SPM": { - "SerialCorrelation": "FAST" + "SerialCorrelation": "FAST", + "InclusiveMaskingThreshold": 0.8 } } }, diff --git a/tests/data/models/model-vismotion_smdl.json b/tests/data/models/model-vismotion_smdl.json index 9d81097c7..05e3ceaf0 100644 --- a/tests/data/models/model-vismotion_smdl.json +++ b/tests/data/models/model-vismotion_smdl.json @@ -49,7 +49,8 @@ }, "Software": { "SPM": { - "SerialCorrelation": "FAST" + "SerialCorrelation": "FAST", + "InclusiveMaskingThreshold": 0.8 } } }, diff --git a/tests/tests_batches/preproc/test_setBatchSTC.m b/tests/tests_batches/preproc/test_setBatchSTC.m index ec293187c..04c0d2138 100644 --- a/tests/tests_batches/preproc/test_setBatchSTC.m +++ b/tests/tests_batches/preproc/test_setBatchSTC.m @@ -70,7 +70,9 @@ function test_setBatchSTC_empty() BIDS = getLayout(opt); matlabbatch = {}; + warning OFF; matlabbatch = setBatchSTC(matlabbatch, BIDS, opt, subLabel); + warning ON; % no slice timing info for this run so nothing should be returned. assertEqual(matlabbatch, {}); diff --git a/tests/tests_batches/preproc/test_setBatchSmoothingFunc.m b/tests/tests_batches/preproc/test_setBatchSmoothingFunc.m index 6eaa94fa8..f39080e7b 100644 --- a/tests/tests_batches/preproc/test_setBatchSmoothingFunc.m +++ b/tests/tests_batches/preproc/test_setBatchSmoothingFunc.m @@ -31,7 +31,7 @@ function test_setBatchSmoothingFunc_basic() 'suffix', 'bold'); matlabbatch = {}; - matlabbatch = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel); + [matlabbatch, srcMetadata] = setBatchSmoothingFunc(matlabbatch, BIDS, opt, subLabel); expectedBatch{1}.spm.spatial.smooth.fwhm = repmat(opt.fwhm.func, [1, 3]); @@ -44,4 +44,7 @@ function test_setBatchSmoothingFunc_basic() assertEqual(matlabbatch{1}.spm.spatial.smooth.data, expectedBatch{1}.spm.spatial.smooth.data); assertEqual(matlabbatch{1}.spm.spatial.smooth, expectedBatch{1}.spm.spatial.smooth); + assertEqual(srcMetadata, struct('RepetitionTime', [1.5500 1.5500], ... + 'SliceTimingCorrected', [false false])); + end diff --git a/tests/tests_batches/stats/test_setBatchFactorialDesign.m b/tests/tests_batches/stats/test_setBatchFactorialDesign.m index 26748325d..c69a3921f 100644 --- a/tests/tests_batches/stats/test_setBatchFactorialDesign.m +++ b/tests/tests_batches/stats/test_setBatchFactorialDesign.m @@ -31,7 +31,7 @@ function test_setBatchFactorialDesign_within_group() function test_setBatchFactorialDesign_complex() - opt = setOptions('vismotion', {'01' 'ctrl01'}, 'pipelineType', 'stats'); + opt = setOptions('vismotion', {'^01'}, 'pipelineType', 'stats'); opt.model.file = spm_file(opt.model.file, ... 'basename', ... @@ -99,7 +99,7 @@ function test_setBatchFactorialDesign_basic() function test_setBatchFactorialDesign_wrong_model_design_matrix() - opt = setOptions('vismotion', {'01' 'ctrl01'}, 'pipelineType', 'stats'); + opt = setOptions('vismotion', {'^01'}, 'pipelineType', 'stats'); opt.verbosity = 1; diff --git a/tests/tests_batches/stats/test_setBatchSubjectLevelGLMSpec.m b/tests/tests_batches/stats/test_setBatchSubjectLevelGLMSpec.m index a9da24934..c9fcd766d 100644 --- a/tests/tests_batches/stats/test_setBatchSubjectLevelGLMSpec.m +++ b/tests/tests_batches/stats/test_setBatchSubjectLevelGLMSpec.m @@ -12,6 +12,29 @@ % TODO add test to better cover setScans +function test_setBatchSubjectLevelGLMSpec_slicetiming_metadata() + + %% GIVEN + subLabel = '^01'; + + opt = setOptions('vismotion', subLabel, 'pipelineType', 'stats'); + + % needed to update the options with the content of the model + opt = checkOptions(opt); + + BIDS = getLayout(opt); + + %% WHEN + matlabbatch = {}; + matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel); + + %% THEN + assertEqual(numel(matlabbatch{1}.spm.stats.fmri_spec.sess), 4); + assertEqual(matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t, 14); + assertEqual(matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t0, 7); + +end + function test_setBatchSubjectLevelGLMSpec_vismotion_acq_1pt6acq() %% GIVEN @@ -128,7 +151,7 @@ function test_setBatchSubjectLevelGLMSpec_basic() assertEqual(matlabbatch{1}.spm.stats.fmri_spec.sess(1).hpf, 125); assertEqual(matlabbatch{1}.spm.stats.fmri_spec.cvi, 'FAST'); assertEqual(matlabbatch{1}.spm.stats.fmri_spec.bases.hrf.derivs, [1 0]); - assertEqual(matlabbatch{1}.spm.stats.fmri_spec.mthresh, 0); + assertEqual(matlabbatch{1}.spm.stats.fmri_spec.mthresh, 0.8); assertEqual(matlabbatch{1}.spm.stats.fmri_spec.mask, ... {fullfile(spm('dir'), 'tpm', 'mask_ICV.nii')}); @@ -137,29 +160,6 @@ function test_setBatchSubjectLevelGLMSpec_basic() end -function test_setBatchSubjectLevelGLMSpec_slicetiming_metadata() - - %% GIVEN - subLabel = '^01'; - - opt = setOptions('vismotion', subLabel, 'pipelineType', 'stats'); - - % needed to update the options with the content of the model - opt = checkOptions(opt); - - BIDS = getLayout(opt); - - %% WHEN - matlabbatch = {}; - matlabbatch = setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel); - - %% THEN - assertEqual(numel(matlabbatch{1}.spm.stats.fmri_spec.sess), 4); - assertEqual(matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t, 14); - assertEqual(matlabbatch{1}.spm.stats.fmri_spec.timing.fmri_t0, 7); - -end - function test_setBatchSubjectLevelGLMSpec_inconsistent_metadata() %% GIVEN @@ -173,7 +173,7 @@ function test_setBatchSubjectLevelGLMSpec_inconsistent_metadata() %% WHEN matlabbatch = {}; assertExceptionThrown(@()setBatchSubjectLevelGLMSpec(matlabbatch, BIDS, opt, subLabel), ... - 'getAndCheckSliceOrder:inconsistentSliceTimingLength'); + 'getAndCheckRepetitionTime:differentRepetitionTime'); end diff --git a/tests/tests_bids/test_getAnatFilename.m b/tests/tests_bids/test_getAnatFilename.m index 9c728bd43..7063e1705 100644 --- a/tests/tests_bids/test_getAnatFilename.m +++ b/tests/tests_bids/test_getAnatFilename.m @@ -24,10 +24,15 @@ function test_getAnatFilename_return_several() BIDS = getLayout(opt); + warning('OFF'); nbImgToReturn = 3; anatImage = getAnatFilename(BIDS, opt, subLabel, nbImgToReturn); assertEqual(numel(anatImage), 3); + warning('ON'); + + assertWarning(@()getAnatFilename(BIDS, opt, subLabel, nbImgToReturn), ... + 'getAnatFilename:severalAnatFile'); end diff --git a/tests/tests_bids/test_getData.m b/tests/tests_bids/test_getData.m index 4373ea183..6f679aee2 100644 --- a/tests/tests_bids/test_getData.m +++ b/tests/tests_bids/test_getData.m @@ -24,7 +24,7 @@ function test_getData_invalid_dir() function test_getData_error_no_matching_task() - opt = setOptions('dummy'); + opt = setOptions('dummy', '01'); % to speed up testing we use the raw dummy data opt.dir.preproc = getTestDataDir('raw'); @@ -36,7 +36,7 @@ function test_getData_error_no_matching_task() function test_getData_get_also_raw_data_for_stats_pipeline() - opt = setOptions('fmriprep'); + opt = setOptions('fmriprep', '10'); opt.pipeline.type = 'stats'; [BIDS, ~] = getData(opt, opt.dir.input); diff --git a/tests/tests_bids/test_spm2bidsCPP.m b/tests/tests_bids/test_spm2bidsCPP.m index c3d71761e..a018d393c 100644 --- a/tests/tests_bids/test_spm2bidsCPP.m +++ b/tests/tests_bids/test_spm2bidsCPP.m @@ -12,7 +12,7 @@ function test_spm2bidsCPP_lesion_segmenting() anatFile = 'sub-01_T1w.nii'; - opt = setOptions('vismotion'); + opt = setOptions('vismotion', '01'); opt = setFields(opt, ALI_my_defaults()); @@ -57,7 +57,7 @@ function test_spm2bidsCPP_lesion_segmenting() function test_spm2bidsCPP_mapping_func() - opt = setOptions('vismotion'); + opt = setOptions('vismotion', '01'); opt = set_spm_2_bids_defaults(opt); @@ -109,7 +109,7 @@ function test_spm2bidsCPP_mapping_func() function test_spm2bidsCPP_mapping_anat() - opt = setOptions('vismotion'); + opt = setOptions('vismotion', '01'); opt = set_spm_2_bids_defaults(opt); diff --git a/tests/tests_bids/unit_tests/test_getAndCheckSliceOrder.m b/tests/tests_bids/unit_tests/test_getAndCheckSliceOrder.m index 8f1686426..e7f88df15 100644 --- a/tests/tests_bids/unit_tests/test_getAndCheckSliceOrder.m +++ b/tests/tests_bids/unit_tests/test_getAndCheckSliceOrder.m @@ -11,6 +11,7 @@ function test_getAndCheckRepetitionTime_dual_task() [BIDS, opt, filter] = setUp({'vismotion', 'rest'}); + filter.desc = ""; sliceOrder = getAndCheckSliceOrder(BIDS, opt, filter); diff --git a/tests/tests_bids_model/test_bidsModel.m b/tests/tests_bids_model/test_bidsModel.m index a628fe37a..b2e3c976a 100644 --- a/tests/tests_bids_model/test_bidsModel.m +++ b/tests/tests_bids_model/test_bidsModel.m @@ -214,10 +214,10 @@ function test_getInclusiveMaskThreshold() bm = BidsModel('file', opt.model.file, 'verbose', false); inclusiveMaskThreshold = bm.getInclusiveMaskThreshold('Name', 'run_level'); - assertEqual(inclusiveMaskThreshold, 0); + assertEqual(inclusiveMaskThreshold, 0.8); inclusiveMaskThreshold = bm.getInclusiveMaskThreshold(); - assertEqual(inclusiveMaskThreshold, 0); + assertEqual(inclusiveMaskThreshold, 0.8); end diff --git a/tests/tests_bids_model/test_getFFXdir.m b/tests/tests_bids_model/test_getFFXdir.m index cdcb2cced..2a29e320c 100644 --- a/tests/tests_bids_model/test_getFFXdir.m +++ b/tests/tests_bids_model/test_getFFXdir.m @@ -34,9 +34,7 @@ function test_getFFXdir_ignored_desc() 'task-vislocalizer_space-IXI549Space_FWHM-0'); assertEqual(ffxDir, expectedOutput); - assertEqual(exist(expectedOutput, 'dir'), 7); - - rmdir(ffxDir, 's'); + assertEqual(exist(expectedOutput, 'dir'), 0); end end @@ -55,9 +53,7 @@ function test_getFFXdir_basic() ffxDir = getFFXdir(subLabel, opt); assertEqual(ffxDir, expectedOutput); - assertEqual(exist(expectedOutput, 'dir'), 7); - - rmdir(ffxDir, 's'); + assertEqual(exist(expectedOutput, 'dir'), 0); end @@ -78,9 +74,6 @@ function test_getFFXdir_extra_entity() 'task-vismotion_acq-1p60mm_space-IXI549Space_FWHM-6'); assertEqual(ffxDir, expectedOutput); - assertEqual(exist(expectedOutput, 'dir'), 7); - - rmdir(ffxDir, 's'); end @@ -97,8 +90,5 @@ function test_getFFXdir_user_specified() 'task-vismotion_space-individual_FWHM-6_node-globalSignal'); assertEqual(ffxDir, expectedOutput); - assertEqual(exist(expectedOutput, 'dir'), 7); - - rmdir(ffxDir, 's'); end diff --git a/tests/tests_workflows/preproc/test_bidsSTC.m b/tests/tests_workflows/preproc/test_bidsSTC.m index 52b9b0f97..ba15f2823 100644 --- a/tests/tests_workflows/preproc/test_bidsSTC.m +++ b/tests/tests_workflows/preproc/test_bidsSTC.m @@ -11,9 +11,9 @@ function test_bidsStc_dual_task() % Cannot test dual task for now as rest and vismotion - % do not have the same entities (rest has not part entity) + % do not have the same entities (rest has no part entity) % opt = setOptions({'vismotion', 'rest'}, ''); - opt = setOptions({'vismotion'}, ''); + opt = setOptions({'vismotion'}, '^01'); opt.bidsFilterFile.bold.acq = ''; opt.bidsFilterFile.bold.part = 'mag'; @@ -32,7 +32,7 @@ function test_bidsStc_dual_task() function test_bidsStc_basic() - opt = setOptions('vismotion', ''); + opt = setOptions('vismotion', '^01'); opt.bidsFilterFile.bold.acq = ''; @@ -44,9 +44,11 @@ function test_bidsStc_basic() function test_bidsStc_skip() - opt = setOptions('vislocalizer', ''); + opt = setOptions('vislocalizer', '^01'); + warning OFF; matlabbatch = bidsSTC(opt); + warning ON; assertEqual(numel(matlabbatch), 0); diff --git a/tests/tests_workflows/preproc/test_bidsSmoothing.m b/tests/tests_workflows/preproc/test_bidsSmoothing.m index 2c1072e9e..19b1c45a3 100644 --- a/tests/tests_workflows/preproc/test_bidsSmoothing.m +++ b/tests/tests_workflows/preproc/test_bidsSmoothing.m @@ -10,7 +10,7 @@ function test_bidsSmoothing_basic() - opt = setOptions('vislocalizer'); + opt = setOptions('vislocalizer', '^01'); opt.pipeline.type = 'preproc'; @@ -18,21 +18,28 @@ function test_bidsSmoothing_basic() opt = checkOptions(opt); - bidsSmoothing(opt); + srcMetadata = bidsSmoothing(opt); + + assertEqual(srcMetadata, struct('RepetitionTime', [1.5500 1.5500], ... + 'SliceTimingCorrected', [false false])); end function test_bidsSmoothing_fmriprep() - opt = setOptions('fmriprep'); + opt = setOptions('fmriprep', '^10'); opt.space = 'MNI152NLin2009cAsym'; opt.query.space = opt.space; % for bidsCopy only opt.query.desc = 'preproc'; + opt.query.modality = {'func'}; bidsCopyInputFolder(opt, 'unzip', false); - bidsSmoothing(opt); + srcMetadata = bidsSmoothing(opt); + + assertEqual(srcMetadata, struct('RepetitionTime', [2 2 2], ... + 'SliceTimingCorrected', [false false false])); cleanUp(opt.dir.preproc);