Skip to content

Commit b30dcad

Browse files
authored
[FIX] properly handle bids filter with bidspm copy (#1275)
* fix 627 * do not expect space to be set * fix test
1 parent 82c954f commit b30dcad

File tree

6 files changed

+188
-39
lines changed

6 files changed

+188
-39
lines changed

src/IO/getData.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
if ~anatOnly && isfield(opt, 'taskName') && ...
113113
~any(ismember(opt.taskName, bids.query(BIDS, 'tasks')))
114114

115-
msg = sprintf(['The task %s that you have asked for ', ...
115+
msg = sprintf(['The task "%s" that you have asked for ', ...
116116
'does not exist in this dataset.\n', ...
117117
'List of tasks present in this dataset:\n%s'], ...
118118
strjoin(opt.taskName), ...

src/cli/cliCopy.m

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,41 +18,44 @@ function cliCopy(varargin)
1818

1919
opt = checkOptions(opt);
2020

21-
opt.query.desc = {'preproc', 'brain'};
22-
opt.query.suffix = {'T1w', 'bold', 'mask'};
23-
if opt.anatOnly
24-
opt.query.suffix = {'T1w', 'mask'};
25-
end
21+
bidsFilterFile = getBidsFilterFile(args);
22+
2623
if isempty(opt.taskName)
2724
opt = rmfield(opt, 'taskName');
2825
end
29-
opt.query.space = opt.space;
3026

31-
bidsFilterFile = getBidsFilterFile(args);
27+
if isempty(bidsFilterFile)
28+
opt.query.desc = {'preproc', 'brain'};
29+
30+
opt.query.suffix = {'T1w', 'mask', 'bold', 'events'};
31+
32+
if opt.anatOnly
33+
opt.query.suffix = {'T1w', 'mask'};
34+
end
35+
36+
opt.query.space = opt.space;
37+
38+
saveOptions(opt);
39+
40+
bidsCopyInputFolder(opt, 'unzip', true, 'force', args.Results.force);
41+
42+
else
3243

33-
if ~isempty(bidsFilterFile)
3444
suffixes = fieldnames(bidsFilterFile);
35-
modalities = {};
3645
for i = 1:numel(suffixes)
37-
modalities{end + 1} = bidsFilterFile.(suffixes{i}).modality; %#ok<*AGROW>
38-
if isfield(bidsFilterFile.(suffixes{i}), 'suffix')
39-
opt.query.suffix = cat(2, ...
40-
opt.query.suffix, ...
41-
bidsFilterFile.(suffixes{i}).suffix);
42-
end
43-
if isfield(bidsFilterFile.(suffixes{i}), 'desc')
44-
opt.query.desc = cat(2, ...
45-
opt.query.desc, ...
46-
bidsFilterFile.(suffixes{i}).desc);
46+
47+
if opt.anatOnly && ~strcmp(bidsFilterFile.(suffixes{i}).modality, 'anat')
48+
continue
4749
end
48-
end
49-
opt.query.modality = unique(modalities);
50-
end
51-
opt.query.suffix = unique(opt.query.suffix);
52-
opt.query.desc = unique(opt.query.desc);
5350

54-
saveOptions(opt);
51+
opt.query = bidsFilterFile.(suffixes{i});
5552

56-
bidsCopyInputFolder(opt, 'unzip', true, 'force', args.Results.force);
53+
saveOptions(opt);
54+
55+
bidsCopyInputFolder(opt, 'unzip', true, 'force', args.Results.force);
56+
57+
end
58+
59+
end
5760

5861
end

src/cli/getOptionsFromCliArgument.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
if opt.verbosity > 3
7878
unfold(opt);
7979
end
80-
unfold(opt);
8180

8281
end
8382

src/workflows/bidsCopyInputFolder.m

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ function bidsCopyInputFolder(varargin)
8080
filter.sub = opt.subjects;
8181

8282
if strcmp(filter.modality, 'func')
83-
filter.task = opt.taskName;
84-
if isempty(filter.task)
83+
if ~isfield(opt, 'taskName') || isempty(opt.taskName)
8584
filter.task = bids.query(BIDS, 'tasks', filter);
85+
else
86+
filter.task = opt.taskName;
8687
end
8788
end
8889

@@ -116,7 +117,9 @@ function bidsCopyInputFolder(varargin)
116117
if isfield(filter, 'desc')
117118
filter = rmfield(filter, 'desc');
118119
end
119-
filter = rmfield(filter, 'space');
120+
if isfield(filter, 'space')
121+
filter = rmfield(filter, 'space');
122+
end
120123
filter.suffix = {'regressors', 'timeseries', 'motion', 'outliers'};
121124

122125
bids.copy_to_derivative(BIDS, ...

tests/tests_cli/test_bidspm_copy_raw.m

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,113 @@ function test_copy_anat_only()
2727
assertEqual(numel(bids.query(BIDS, 'data')), 1);
2828

2929
end
30+
31+
function test_copy_no_task()
32+
33+
inputPath = fullfile(getMoaeDir(), 'inputs', 'raw');
34+
35+
outputPath = tempName();
36+
37+
bidspm(inputPath, outputPath, 'subject', ...
38+
'action', 'copy', ...
39+
'verbosity', 0);
40+
41+
BIDS = bids.layout(fullfile(outputPath, 'derivatives', 'bidspm-preproc'), ...
42+
'verbose', false, ...
43+
'use_schema', false);
44+
45+
assertEqual(numel(bids.query(BIDS, 'data')), 3);
46+
47+
end
48+
49+
function test_copy_filter_suffix()
50+
51+
inputPath = fullfile(getMoaeDir(), 'inputs', 'raw');
52+
53+
outputPath = tempName();
54+
55+
bidspm(inputPath, outputPath, 'subject', ...
56+
'action', 'copy', ...
57+
'bids_filter_file', struct('bold', struct('modality', 'func', ...
58+
'suffix', 'events')), ...
59+
'verbosity', 0);
60+
61+
BIDS = bids.layout(fullfile(outputPath, 'derivatives', 'bidspm-preproc'), ...
62+
'verbose', false, ...
63+
'use_schema', false);
64+
65+
assertEqual(numel(bids.query(BIDS, 'data')), 1);
66+
67+
end
68+
69+
function test_copy_filter_session()
70+
71+
inputPath = getTestDataDir('raw');
72+
73+
outputPath = tempName();
74+
75+
bidspm(inputPath, outputPath, 'subject', ...
76+
'action', 'copy', ...
77+
'participant_label', {'01', 'ctrl01'}, ...
78+
'task', {'vismotion'}, ...
79+
'bids_filter_file', struct('bold', struct('modality', 'func', ...
80+
'suffix', 'events', ...
81+
'ses', '01')), ...
82+
'verbosity', 0);
83+
84+
BIDS = bids.layout(fullfile(outputPath, 'derivatives', 'bidspm-preproc'), ...
85+
'verbose', false, ...
86+
'use_schema', false);
87+
88+
assertEqual(numel(bids.query(BIDS, 'data')), 8);
89+
90+
end
91+
92+
function test_copy_filter_anat()
93+
94+
inputPath = getTestDataDir('raw');
95+
96+
outputPath = tempName();
97+
98+
bidspm(inputPath, outputPath, 'subject', ...
99+
'action', 'copy', ...
100+
'participant_label', {'01', 'ctrl01'}, ...
101+
'task', {'vismotion'}, ...
102+
'bids_filter_file', struct('anat', struct('modality', 'anat', ...
103+
'suffix', 'T1w', ...
104+
'ses', '01')), ...
105+
'verbosity', 0);
106+
107+
BIDS = bids.layout(fullfile(outputPath, 'derivatives', 'bidspm-preproc'), ...
108+
'verbose', false, ...
109+
'use_schema', false);
110+
111+
assertEqual(numel(bids.query(BIDS, 'data')), 2);
112+
113+
end
114+
115+
function test_copy_several_filter()
116+
117+
inputPath = getTestDataDir('raw');
118+
119+
outputPath = tempName();
120+
121+
bidspm(inputPath, outputPath, 'subject', ...
122+
'action', 'copy', ...
123+
'participant_label', {'01', 'ctrl01'}, ...
124+
'task', {'vismotion'}, ...
125+
'bids_filter_file', struct('anat', struct('modality', 'anat', ...
126+
'suffix', 'T1w', ...
127+
'ses', '01'), ...
128+
'bold', struct('modality', 'func', ...
129+
'suffix', 'events', ...
130+
'ses', '01')), ...
131+
'verbosity', 0);
132+
133+
BIDS = bids.layout(fullfile(outputPath, 'derivatives', 'bidspm-preproc'), ...
134+
'verbose', false, ...
135+
'use_schema', false);
136+
137+
assertEqual(numel(bids.query(BIDS, 'data')), 10);
138+
139+
end

tests/tests_slow/tests_cli/test_bidspm_copy.m

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
initTestSuite;
1010
end
1111

12-
function test_copy_filter()
12+
function test_copy_simple_filter()
1313

1414
markTestAs('slow');
1515

@@ -32,10 +32,12 @@ function test_copy_filter()
3232
end
3333
copyfile(sourceFile{1}, destFile{1});
3434

35-
%% with simple filter file
35+
% simple filter file
3636
bids_filter_file = fullfile(tempName(), 'bids_filter_file.json');
3737
bids.util.jsonencode(bids_filter_file, ...
38-
struct('bold', struct('modality', 'func')));
38+
struct('bold', struct('modality', 'func', ...
39+
'extension', '.nii.gz', ...
40+
'desc', {{'preproc', 'brain'}})));
3941

4042
% filter takes precedence over predefined opt.query
4143
% so anat should not be copied
@@ -55,13 +57,45 @@ function test_copy_filter()
5557
'verbose', false, ...
5658
'use_schema', false);
5759

58-
assertEqual(numel(bids.query(BIDS, 'data')), 5);
60+
assertEqual(numel(bids.query(BIDS, 'data')), 4);
5961

60-
%% now with more complex filter as struct
62+
delete(destFile{1});
63+
64+
end
65+
66+
function test_copy_complex_filter()
67+
68+
markTestAs('slow');
69+
70+
inputPath = fullfile(getMoaeDir(), 'inputs', 'fmriprep');
71+
72+
% add dummy aroma file to input folder
73+
BIDS = bids.layout(inputPath, ...
74+
'verbose', false, ...
75+
'use_schema', false);
76+
sourceFile = bids.query(BIDS, 'data', ...
77+
'suffix', 'bold', ...
78+
'desc', 'preproc', ...
79+
'space', 'T1w');
80+
bf = bids.File(sourceFile{1});
81+
bf.entities.desc = 'smoothAROMAnonaggr';
82+
bf = bf.update;
83+
destFile = bids.internal.file_utils(sourceFile, 'filename', bf.filename);
84+
if exist(destFile{1}, 'file')
85+
delete(destFile{1});
86+
end
87+
copyfile(sourceFile{1}, destFile{1});
88+
89+
% more complex filter as struct
6190
bids_filter_file = struct('bold', struct('modality', 'func', ...
6291
'suffix', 'bold', ...
63-
'desc', {'smoothAROMAnonaggr'; ...
64-
'preproc'}));
92+
'desc', {{'smoothAROMAnonaggr'; ...
93+
'preproc'}}), ...
94+
'anat', struct('modality', 'anat', ...
95+
'suffix', 't1w', ...
96+
'desc', 'preproc'));
97+
98+
outputPath = tempName();
6599

66100
bidspm(inputPath, outputPath, 'subject', ...
67101
'action', 'copy', ...
@@ -74,7 +108,7 @@ function test_copy_filter()
74108
'verbose', false, ...
75109
'use_schema', false);
76110

77-
assertEqual(numel(bids.query(BIDS, 'data')), 6);
111+
assertEqual(numel(bids.query(BIDS, 'data')), 4);
78112

79113
delete(destFile{1});
80114

0 commit comments

Comments
 (0)