From a8eead7d0981c1b4027696e2a8c686bf1a71e1c6 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 26 Jan 2024 15:15:26 +0100 Subject: [PATCH 1/4] check several sessions --- demos/openneuro/Makefile | 14 +++++++++++--- demos/openneuro/ds000201_run.m | 22 ++++++++++++++++++++++ src/IO/getData.m | 4 +++- src/cli/cliPreprocess.m | 9 +++++---- 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 demos/openneuro/ds000201_run.m diff --git a/demos/openneuro/Makefile b/demos/openneuro/Makefile index 7d8070c87..8d6d5eb50 100644 --- a/demos/openneuro/Makefile +++ b/demos/openneuro/Makefile @@ -48,7 +48,7 @@ data_ds000224: data_ds001168: mkdir -p inputs cd inputs && datalad install ///openneuro/ds001168 - cd inputs/ds001168 && datalad get ds001168/sub-0[12] -J 2 + cd inputs/ds001168 && datalad get ds001168/sub-0[12] -J 12 data_ds001734: mkdir -p inputs @@ -65,5 +65,13 @@ data_ds002799: cd inputs && datalad install ///openneuro/ds002799 datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-292/*/func/*MNI152NLin2009cAsym* datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-292/*/func/*tsv - datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*MNI152NLin2009cAsym* -J 2 - datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*tsv -J 2 + datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*MNI152NLin2009cAsym* -J 12 + datalad get -d inputs/ds002799 inputs/ds002799/derivatives/fmriprep/sub-30[27]/*/func/*tsv -J 12 + + +data_ds000201: + mkdir -p inputs + cd inputs && datalad install ///openneuro/ds000201 + datalad get -d inputs/ds000201 inputs/ds000201/sub-900[1-5]/*/anat/*T1w* -J 12 +# datalad get -d inputs/ds000201 inputs/ds000201/sub-900[1-5]/*/func -J 12 +# datalad get -d inputs/ds000201 inputs/ds000201/sub-900[1-5]/*/fmap -J 12 diff --git a/demos/openneuro/ds000201_run.m b/demos/openneuro/ds000201_run.m new file mode 100644 index 000000000..fef0e3607 --- /dev/null +++ b/demos/openneuro/ds000201_run.m @@ -0,0 +1,22 @@ +% (C) Copyright 2024 bidspm developers + +clear; +clc; + +addpath(fullfile(pwd, '..', '..')); +bidspm(); + +% The directory where the data are located +root_dir = fileparts(mfilename('fullpath')); +bids_dir = fullfile(root_dir, 'inputs', 'ds000201'); +output_dir = fullfile(root_dir, 'outputs', 'ds000201', 'derivatives'); + +participant_label = {'9001', '9002', '9003', '9004', '9005'}; + +%% Preprocessing +bidspm(bids_dir, output_dir, 'subject', ... + 'participant_label', participant_label, ... + 'action', 'preprocess', ... + 'anat_only', true, ... + 'space', {'individual', 'IXI549Space'}, ... + 'skip_validation', true); diff --git a/src/IO/getData.m b/src/IO/getData.m index 79301dcd5..a65a7feab 100644 --- a/src/IO/getData.m +++ b/src/IO/getData.m @@ -94,7 +94,9 @@ end % make sure that the required tasks exist in the data set - if isfield(opt, 'taskName') && ~any(ismember(opt.taskName, bids.query(BIDS, 'tasks'))) + if ~opt.anatOnly && ... + isfield(opt, 'taskName') && ... + ~any(ismember(opt.taskName, bids.query(BIDS, 'tasks'))) msg = sprintf(['The task %s that you have asked for ', ... 'does not exist in this dataset.\n', ... diff --git a/src/cli/cliPreprocess.m b/src/cli/cliPreprocess.m index 7c6644e9e..cfa23291d 100644 --- a/src/cli/cliPreprocess.m +++ b/src/cli/cliPreprocess.m @@ -57,10 +57,11 @@ function cliPreprocess(varargin) 'force', false); end - bidsCheckVoxelSize(opt); - - if opt.useFieldmaps && ~opt.anatOnly - bidsCreateVDM(opt); + if ~opt.anatOnly + bidsCheckVoxelSize(opt); + if opt.useFieldmaps + bidsCreateVDM(opt); + end end if ~opt.stc.skip && ~opt.anatOnly From 9decdc89e27b81c2824a4be18f228583365a8ca9 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 26 Jan 2024 18:22:26 +0100 Subject: [PATCH 2/4] update bids matlab --- lib/bids-matlab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bids-matlab b/lib/bids-matlab index 877135919..ccd7f1bea 160000 --- a/lib/bids-matlab +++ b/lib/bids-matlab @@ -1 +1 @@ -Subproject commit 877135919bb18dec4b1eb3bc3bf53c42f5ec11d5 +Subproject commit ccd7f1bea513a3c76b891b30402bf3e480063acf From 6a10b42d601bb42a793e91616313164afac0cb65 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 29 Jan 2024 15:53:01 +0100 Subject: [PATCH 3/4] start creating multianat workflow --- demos/openneuro/ds000201_run.m | 5 +- src/batches/preproc/setBatchSkullStripping.m | 4 +- src/batches/setBatchSelectAnat.m | 12 ++- src/bids/getAnatFilename.m | 2 +- src/cli/cliPreprocess.m | 26 +++--- src/workflows/preproc/bidsSpatialPrepro.m | 93 +++++++++++++++----- tests/create_dummy_dataset.py | 5 +- 7 files changed, 102 insertions(+), 45 deletions(-) diff --git a/demos/openneuro/ds000201_run.m b/demos/openneuro/ds000201_run.m index fef0e3607..53ee62c2a 100644 --- a/demos/openneuro/ds000201_run.m +++ b/demos/openneuro/ds000201_run.m @@ -18,5 +18,6 @@ 'participant_label', participant_label, ... 'action', 'preprocess', ... 'anat_only', true, ... - 'space', {'individual', 'IXI549Space'}, ... - 'skip_validation', true); + 'space', {'individual'}, ... + 'skip_validation', true, ... + 'verbosity', 3); diff --git a/src/batches/preproc/setBatchSkullStripping.m b/src/batches/preproc/setBatchSkullStripping.m index 7f5e217f1..0fd393a5d 100644 --- a/src/batches/preproc/setBatchSkullStripping.m +++ b/src/batches/preproc/setBatchSkullStripping.m @@ -66,8 +66,8 @@ return end - % if this is part of a pipeline we get the segmentation dependency to get - % the input from. + % if this is part of a pipeline + % we get the segmentation dependency to get the input from. % Otherwise the files to process are stored in a cell if isfield(opt, 'orderBatches') && ... isfield(opt.orderBatches, 'segment') && ... diff --git a/src/batches/setBatchSelectAnat.m b/src/batches/setBatchSelectAnat.m index 253fd2730..0582a98d8 100644 --- a/src/batches/setBatchSelectAnat.m +++ b/src/batches/setBatchSelectAnat.m @@ -34,9 +34,17 @@ printBatchName('selecting anatomical image', opt); - [anatImage, anatDataDir] = getAnatFilename(BIDS, opt, subLabel); + nbImgToReturn = 1; + if opt.anatOnly + nbImgToReturn = Inf; + end + [anatImage, anatDataDir] = getAnatFilename(BIDS, opt, subLabel, nbImgToReturn); matlabbatch{end + 1}.cfg_basicio.cfg_named_file.name = 'Anatomical'; - matlabbatch{end}.cfg_basicio.cfg_named_file.files = { {fullfile(anatDataDir, anatImage)} }; + if ischar(anatImage) + matlabbatch{end}.cfg_basicio.cfg_named_file.files = { {fullfile(anatDataDir, anatImage)} }; + else + matlabbatch{end}.cfg_basicio.cfg_named_file.files = { fullfile(anatDataDir, anatImage) }; + end end diff --git a/src/bids/getAnatFilename.m b/src/bids/getAnatFilename.m index 53c05d5da..999bc9ca5 100644 --- a/src/bids/getAnatFilename.m +++ b/src/bids/getAnatFilename.m @@ -102,7 +102,7 @@ anatImage = unzipAndReturnsFullpathName(anat); - msg = sprintf(' selecting anat file: %s', ... + msg = sprintf(' selecting anat file(s): %s', ... bids.internal.create_unordered_list(bids.internal.format_path(anat))); logger('DEBUG', msg, 'options', opt, 'filename', mfilename()); diff --git a/src/cli/cliPreprocess.m b/src/cli/cliPreprocess.m index cfa23291d..8f07c819a 100644 --- a/src/cli/cliPreprocess.m +++ b/src/cli/cliPreprocess.m @@ -39,6 +39,7 @@ function cliPreprocess(varargin) end bidsReport(opt); + % TODO adapt boiler plate for anat only boilerplate(opt, ... 'outputPath', fullfile(opt.dir.output, 'reports'), ... 'pipelineType', 'preprocess', ... @@ -49,23 +50,26 @@ function cliPreprocess(varargin) bidsCopyInputFolder(opt); - if opt.dummyScans > 0 - tmpOpt = opt; - tmpOpt.dir.input = tmpOpt.dir.preproc; - bidsRemoveDummies(tmpOpt, ... - 'dummyScans', tmpOpt.dummyScans, ... - 'force', false); - end - if ~opt.anatOnly + bidsCheckVoxelSize(opt); + + if opt.dummyScans > 0 + tmpOpt = opt; + tmpOpt.dir.input = tmpOpt.dir.preproc; + bidsRemoveDummies(tmpOpt, ... + 'dummyScans', tmpOpt.dummyScans, ... + 'force', false); + end + if opt.useFieldmaps bidsCreateVDM(opt); end - end - if ~opt.stc.skip && ~opt.anatOnly - bidsSTC(opt); + if ~opt.stc.skip + bidsSTC(opt); + end + end bidsSpatialPrepro(opt); diff --git a/src/workflows/preproc/bidsSpatialPrepro.m b/src/workflows/preproc/bidsSpatialPrepro.m index d029c45d8..8c943e5d5 100644 --- a/src/workflows/preproc/bidsSpatialPrepro.m +++ b/src/workflows/preproc/bidsSpatialPrepro.m @@ -79,8 +79,22 @@ printProcessingSubject(iSub, subLabel, opt); + %% Anat matlabbatch = setBatchSelectAnat(matlabbatch, BIDS, opt, subLabel); + anatFiles = matlabbatch{1}.cfg_basicio.cfg_named_file.files{1}; + + if opt.anatOnly && numel(anatFiles) > 1 + printBatchName('coregister all anatomical data to first anatomical', opt); + for iAnat = 2:numel(anatFiles) + matlabbatch = setBatchCoregistration(matlabbatch, ... + opt, ... + anatFiles{1}, ... + anatFiles{iAnat}); + end + end + %% Func + % dependency from SelectAnat if ~opt.realign.useUnwarp action = 'realign'; else @@ -92,36 +106,21 @@ subLabel, ... action); - % dependency from file selector ('Anatomical') matlabbatch = setBatchCoregistrationFuncToAnat(matlabbatch, BIDS, opt, subLabel); matlabbatch = setBatchSaveCoregistrationMatrix(matlabbatch, BIDS, opt, subLabel); - anatFile = matlabbatch{1}.cfg_basicio.cfg_named_file.files{1}{1}; - - % TODO refactor with bidsSegmentSkullstrip - %% Skip segmentation / skullstripping if done previously - if skullstripDo && ... - ~opt.skullstrip.force && ... - skullstrippingAlreadyDone(anatFile, BIDS) - opt.skullstrip.do = false; - end - if segmentDo && ~opt.segment.force && ... - segmentationAlreadyDone(anatFile, BIDS) - opt.segment.do = false; - % but if we must force the skullstripping - % then we will need some segmentation input - elseif opt.skullstrip.do && ... - ~segmentationAlreadyDone(anatFile, BIDS) - opt.segment.do = true; + %% Segmentation / Skullstripping + for iAnat = 1:numel(anatFiles) + [matlabbatch, opt] = setBatchesSegmentationAndSkullstrip(matlabbatch, ... + BIDS, ... + opt, ... + subLabel, ... + segmentDo, ... + skullstripDo, ... + anatFiles{iAnat}); end - [matlabbatch, opt] = setBatchSegmentation(matlabbatch, opt); - - matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel); - opt.orderBatches.skullStripping = numel(matlabbatch) - 1; - opt.orderBatches.skullStrippingMask = numel(matlabbatch); - %% Normalization if ismember('IXI549Space', opt.space) % dependency from segmentation @@ -210,3 +209,49 @@ createdFiles = bidsRename(opt); end + +function [matlabbatch, opt] = setBatchesSegmentationAndSkullstrip(varargin) + + args = inputParser; + + addRequired(args, 'matlabbatch', @iscell); + addRequired(args, 'BIDS', @isstruct); + addRequired(args, 'opt', @isstruct); + addRequired(args, 'subLabel', @ischar); + addRequired(args, 'segmentDo', @islogical); + addRequired(args, 'skullstripDo', @islogical); + addRequired(args, 'anatFile', @ischar); + + parse(args, varargin{:}); + + matlabbatch = args.Results.matlabbatch; + BIDS = args.Results.BIDS; + opt = args.Results.opt; + subLabel = args.Results.subLabel; + segmentDo = args.Results.segmentDo; + skullstripDo = args.Results.skullstripDo; + anatFile = args.Results.anatFile; + + % TODO refactor with bidsSegmentSkullstrip + %% Skip segmentation / skullstripping if done previously + if skullstripDo && ... + ~opt.skullstrip.force && ... + skullstrippingAlreadyDone(anatFile, BIDS) + opt.skullstrip.do = false; + end + if segmentDo && ~opt.segment.force && ... + segmentationAlreadyDone(anatFile, BIDS) + opt.segment.do = false; + % but if we must force the skullstripping + % then we will need some segmentation input + elseif opt.skullstrip.do && ... + ~segmentationAlreadyDone(anatFile, BIDS) + opt.segment.do = true; + end + + [matlabbatch, opt] = setBatchSegmentation(matlabbatch, opt); + + matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel); + opt.orderBatches.skullStripping = numel(matlabbatch) - 1; + opt.orderBatches.skullStrippingMask = numel(matlabbatch); +end diff --git a/tests/create_dummy_dataset.py b/tests/create_dummy_dataset.py index 6691deb03..4aac5f03b 100644 --- a/tests/create_dummy_dataset.py +++ b/tests/create_dummy_dataset.py @@ -42,9 +42,9 @@ def create_raw_dataset(target_dir, subject_list, session_list): create_raw_func_vismotion(target_dir, sub, ses) create_raw_func_vislocalizer(target_dir, sub, ses) create_raw_fmap(target_dir, sub, ses) + create_raw_anat(target_dir, sub, ses) create_raw_func_rest(target_dir, sub, "02") - create_raw_anat(target_dir, sub) def create_raw_func_vismotion(target_dir, sub, ses): @@ -150,8 +150,7 @@ def create_raw_fmap(target_dir, sub, ses): json.dump(content, f, indent=4) -def create_raw_anat(target_dir, sub): - ses = "01" +def create_raw_anat(target_dir, sub, ses="01"): suffix = "T1w" this_dir = target_dir / f"sub-{sub}" / f"ses-{ses}" / "anat" From cdd033877b988ccfbee4e4bba7b523e931c8299b Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 29 Jan 2024 16:51:17 +0100 Subject: [PATCH 4/4] try to deal with segmenting each brain --- demos/openneuro/ds000201_run.m | 3 ++ src/batches/preproc/setBatchSegmentation.m | 45 ++++++++++--------- src/batches/preproc/setBatchSkullStripping.m | 7 +-- src/workflows/preproc/bidsSpatialPrepro.m | 2 +- .../preproc/test_setBatchSegmentation.m | 7 +++ .../preproc/test_setBatchSkullStripping.m | 8 ++++ tests/tests_bids/test_getAnatFilename.m | 4 ++ 7 files changed, 52 insertions(+), 24 deletions(-) diff --git a/demos/openneuro/ds000201_run.m b/demos/openneuro/ds000201_run.m index 53ee62c2a..73f9b8cc8 100644 --- a/demos/openneuro/ds000201_run.m +++ b/demos/openneuro/ds000201_run.m @@ -1,5 +1,7 @@ % (C) Copyright 2024 bidspm developers +% Example of anatomical preprocessing with one anat per session + clear; clc; @@ -20,4 +22,5 @@ 'anat_only', true, ... 'space', {'individual'}, ... 'skip_validation', true, ... + 'dry_run', true, ... 'verbosity', 3); diff --git a/src/batches/preproc/setBatchSegmentation.m b/src/batches/preproc/setBatchSegmentation.m index 0832037fb..b7a4dc398 100644 --- a/src/batches/preproc/setBatchSegmentation.m +++ b/src/batches/preproc/setBatchSegmentation.m @@ -18,11 +18,22 @@ % (C) Copyright 2020 bidspm developers + % TODO + % implement the opt.segment.do and opt.segment.force + % with segmentationAlreadyDone ? + + if nargin < 3 + imageToSegment = ''; + end + if iscell(imageToSegment) + imageToSegment = char(imageToSegment); + end + if ~opt.segment.do - opt.orderBatches.segment = 0; + opt.orderBatches.segment = [0]; return else - opt.orderBatches.segment = numel(matlabbatch) + 1; + opt.orderBatches.segment(end + 1) = numel(matlabbatch) + 1; end printBatchName('Segmentation anatomical image', opt); @@ -34,29 +45,23 @@ % save bias corrected image = true preproc.channel.write = [false true]; - % first part assumes we are in the bidsSpatialPreproc workflow - if isfield(opt, 'orderBatches') && isfield(opt.orderBatches, 'selectAnat') + % assumes vanilla bidsSpatialPreproc workflow + % - not anat only + if ~strcmp(imageToSegment, '') + for iImg = 1:size(imageToSegment, 1) + file = validationInputFile([], deblank(imageToSegment(iImg, :))); + preproc.channel.vols{iImg, 1} = file; + end + + elseif isfield(opt, 'orderBatches') && isfield(opt.orderBatches, 'selectAnat') - % SAVE BIAS CORRECTED IMAGE preproc.channel.vols(1) = cfg_dep('Named File Selector: Anatomical(1) - Files', ... returnDependency(opt, 'selectAnat'), ... substruct('.', 'files', '{}', {1})); - else - % TODO - % implement the opt.segment.do and opt.segment.force - % with segmentationAlreadyDone ? - - % in case a cell was given as input - if iscell(imageToSegment) - imageToSegment = char(imageToSegment); - end - - % add all the images to segment - for iImg = 1:size(imageToSegment, 1) - file = validationInputFile([], deblank(imageToSegment(iImg, :))); - preproc.channel.vols{iImg, 1} = file; - end + else + % ??? + return end diff --git a/src/batches/preproc/setBatchSkullStripping.m b/src/batches/preproc/setBatchSkullStripping.m index 0fd393a5d..2b36f5d87 100644 --- a/src/batches/preproc/setBatchSkullStripping.m +++ b/src/batches/preproc/setBatchSkullStripping.m @@ -24,9 +24,10 @@ % :returns: - :matlabbatch: (structure) The matlabbatch ready to run the spm job % % This function will get its inputs from the segmentation batch by reading - % the dependency from ``opt.orderBatches.segment``. If this field is not specified it will - % try to get the results from the segmentation by relying on the ``anat`` - % image returned by ``getAnatFilename``. + % the dependency from ``opt.orderBatches.segment``. + % If this field is not specified it will try + % to get the results from the segmentation by relying + % on the ``anat`` image returned by ``getAnatFilename``. % % The threshold for inclusion in the mask can be set by:: % diff --git a/src/workflows/preproc/bidsSpatialPrepro.m b/src/workflows/preproc/bidsSpatialPrepro.m index 8c943e5d5..2b7b6c387 100644 --- a/src/workflows/preproc/bidsSpatialPrepro.m +++ b/src/workflows/preproc/bidsSpatialPrepro.m @@ -249,7 +249,7 @@ opt.segment.do = true; end - [matlabbatch, opt] = setBatchSegmentation(matlabbatch, opt); + [matlabbatch, opt] = setBatchSegmentation(matlabbatch, opt, anatFile); matlabbatch = setBatchSkullStripping(matlabbatch, BIDS, opt, subLabel); opt.orderBatches.skullStripping = numel(matlabbatch) - 1; diff --git a/tests/tests_batches/preproc/test_setBatchSegmentation.m b/tests/tests_batches/preproc/test_setBatchSegmentation.m index 9568e72c9..95ba9f3be 100644 --- a/tests/tests_batches/preproc/test_setBatchSegmentation.m +++ b/tests/tests_batches/preproc/test_setBatchSegmentation.m @@ -59,7 +59,9 @@ function test_setBatchSegmentation_images() % check with one file matlabbatch = {}; + matlabbatch = setBatchSegmentation(matlabbatch, opt, anatImage); + expectedBatch = returnExpectedBatch(spmLocation); expectedBatch{end}.spm.spatial.preproc.channel.vols{1} = anatImage; @@ -69,6 +71,7 @@ function test_setBatchSegmentation_images() matlabbatch = {}; anatImage = {anatImage; anatImage}; matlabbatch = setBatchSegmentation(matlabbatch, opt, anatImage); + expectedBatch{end}.spm.spatial.preproc.channel.vols = anatImage; assertEqual(matlabbatch{1}.spm.spatial.preproc.channel, ... @@ -88,10 +91,14 @@ function test_setBatchSegmentation_images() BIDS = getLayout(opt); + warning('OFF', 'getAnatFilename:severalAnatFile'); + [anatImage, anatDataDir] = getAnatFilename(BIDS, opt, subLabel); anatImage = fullfile(anatDataDir, anatImage); + warning('ON', 'getAnatFilename:severalAnatFile'); + end function expectedBatch = returnExpectedBatch(spmLocation) diff --git a/tests/tests_batches/preproc/test_setBatchSkullStripping.m b/tests/tests_batches/preproc/test_setBatchSkullStripping.m index b5a406566..468e31a59 100644 --- a/tests/tests_batches/preproc/test_setBatchSkullStripping.m +++ b/tests/tests_batches/preproc/test_setBatchSkullStripping.m @@ -10,6 +10,8 @@ function test_setBatchSkullStripping_basic() + warning('OFF', 'getAnatFilename:severalAnatFile'); + subLabel = '01'; opt = setOptions('vislocalizer', subLabel); @@ -41,10 +43,14 @@ function test_setBatchSkullStripping_basic() delete(fullfile(BIDS.pth, 'sub-01', 'ses-01', 'anat', ... 'sub-01_ses-01_space-individual_desc-brain_mask.json')); + warning('ON', 'getAnatFilename:severalAnatFile'); + end function test_setBatchSkullStripping_without_segment + warning('OFF', 'getAnatFilename:severalAnatFile'); + subLabel = '01'; opt = setOptions('vislocalizer', subLabel); @@ -56,6 +62,8 @@ function test_setBatchSkullStripping_basic() assertEqual(numel(matlabbatch{1}.spm.util.imcalc.input{1}), 1); + warning('ON', 'getAnatFilename:severalAnatFile'); + end function test_setBatchSkullStripping_skip_skullstrip() diff --git a/tests/tests_bids/test_getAnatFilename.m b/tests/tests_bids/test_getAnatFilename.m index 75df32297..b44e20811 100644 --- a/tests/tests_bids/test_getAnatFilename.m +++ b/tests/tests_bids/test_getAnatFilename.m @@ -86,6 +86,8 @@ function test_getAnatFilename_basic() opt = setOptions('vislocalizer', subLabel, 'useRaw', true); + warning('OFF', 'getAnatFilename:severalAnatFile'); + BIDS = getLayout(opt); [anatImage, anatDataDir] = getAnatFilename(BIDS, opt, subLabel); @@ -110,6 +112,8 @@ function test_getAnatFilename_basic() anatImage = getAnatFilename(BIDS, opt, subLabel); assertEqual(anatImage, 'sub-ctrl01_ses-01_T1w.nii'); + warning('ON', 'getAnatFilename:severalAnatFile'); + end function test_getAnatFilename_no_session()