Skip to content

Commit bf2e35b

Browse files
d-ni374Remi-Gau
andauthored
[FIX] small fixes in createDefaultStatsModel.m, getAcquisitionTime.m & bidsResults.m (#1248)
* changed condition to check compatibility of sliceOrder and acquisitionTime * fixed conditional statement defining bm.Nodes.GroupBy * Update function bidsResultsSubject: identification of run level contrasts * fixed spelling * update citation.cff * update citation.cff * add test getAcquisitionTime * adapt test data for bids stats model * extract regex * add tests * revert --------- Co-authored-by: Remi Gau <[email protected]>
1 parent e401f5f commit bf2e35b

File tree

9 files changed

+106
-23
lines changed

9 files changed

+106
-23
lines changed

CITATION.cff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ authors:
9393
affiliation: "University of Gent"
9494
orcid: "https://orcid.org/0000-0001-8279-6118"
9595

96+
- family-names: Huber
97+
given-names: Daniel
98+
affiliation: University of Innsbruck
99+
96100
- family-names: "Van Audenhaege"
97101
given-names: "Alice"
98102
affiliation: "Université catholique de Louvain"

src/bids_model/createDefaultStatsModel.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106

107107
if strcmp(levelsToUpdate{i}, 'subject')
108108
bm.Nodes{idx}.GroupBy = {'subject', 'contrast'};
109-
elseif strcmp(levelsToUpdate{i}, 'subject')
109+
elseif strcmp(levelsToUpdate{i}, 'dataset')
110110
bm.Nodes{idx}.GroupBy = {'contrast'};
111111
end
112112

src/preproc/utils/getAcquisitionTime.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
acquisitionTime = computeAcquisitionTime(sliceOrder, repetitionTime);
2020

21-
% ceil to avoid making this too brittle
22-
if any(sliceOrder > ceil(acquisitionTime * 100) / 100)
21+
% add small time buffer (0.01 s) to avoid making this too brittle
22+
if any(sliceOrder > acquisitionTime + 0.01)
2323
sliceOrder = bids.internal.create_unordered_list(num2str(sliceOrder));
2424
msg = sprintf(['Acquisition time cannot be < to any slice timing value:\n\n', ...
2525
'Current values:', ...
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function value = endsWithRunNumber(contrastName)
2+
%
3+
% USAGE::
4+
%
5+
% endsWithRunNumber(contrastName)
6+
%
7+
%
8+
% Returns true if the contrast name ends with an underscore
9+
% followed by some number.
10+
%
11+
12+
% (C) Copyright 2024 bidspm developers
13+
result = regexp(contrastName, '_[0-9]+\${0,1}$', 'match');
14+
value = ~isempty(result);
15+
return

src/workflows/stats/bidsResults.m

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -361,16 +361,14 @@
361361
%
362362
% Only necessary
363363
% if the user did not specify the run number in result.name
364-
% by adding an "_[0-9]*" to indicate the run number to get this contrast
364+
% by adding an "_[0-9]+" to indicate the run number to get this contrast
365365
% for example
366366
%
367367
% opt.result.name = 'listening_1'
368368
%
369369

370-
endsWithRunNumber = regexp(contrastName, '_[0-9]*\${0,1}$', 'match');
371-
if isempty(endsWithRunNumber)
372-
tmp.name = [contrastName '_[0-9]*'];
373-
else
370+
tmp.name = [contrastName '_[0-9]+'];
371+
if ~endsWithRunNumber(contrastName)
374372
tmp.name = contrastName;
375373
end
376374

@@ -392,21 +390,18 @@
392390

393391
contrastNb = getContrastNb(tmp, opt, SPM);
394392

395-
constrastsNamesList = {SPM.xCon(contrastNb).name}';
393+
contrastsNamesList = {SPM.xCon(contrastNb).name}';
396394

397-
for j = 1:numel(constrastsNamesList)
395+
for j = 1:numel(contrastsNamesList)
398396

399397
result = opt.results(iRes);
400398

401-
result.name = constrastsNamesList{j};
399+
result.name = contrastsNamesList{j};
402400

403-
if ~isRunLevel
404-
% skip contrast with name ending in _[0-9]* as they are run level
405-
% contrasts
406-
endsWithRunNumber = regexp(result.name, '_[0-9]*$', 'match');
407-
if ~isempty(endsWithRunNumber)
408-
continue
409-
end
401+
% skip contrast with name ending in _[0-9]+
402+
% as they are run level contrasts
403+
if ~isRunLevel && endsWithRunNumber(result.name)
404+
continue
410405
end
411406

412407
result.space = opt.space;

tests/data/models/model-default_smdl.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"Name": "default_rest_vislocalizer_vismotion_model",
2+
"Name": "default_vislocalizer_model",
33
"BIDSModelVersion": "1.0.0",
4-
"Description": "default BIDS stats model for rest/vislocalizer/vismotion task",
4+
"Description": "default BIDS stats model for vislocalizer task",
55
"Input": {
66
"task": [
77
"vislocalizer"
@@ -61,8 +61,8 @@
6161
},
6262
"Software": {
6363
"SPM": {
64-
"InclusiveMaskingThreshold": 0.8,
65-
"SerialCorrelation": "FAST"
64+
"SerialCorrelation": "FAST",
65+
"InclusiveMaskingThreshold": 0.8
6666
}
6767
}
6868
},
@@ -107,7 +107,7 @@
107107
"Level": "Dataset",
108108
"Name": "dataset",
109109
"GroupBy": [
110-
""
110+
"contrast"
111111
],
112112
"Model": {
113113
"X": [

tests/tests_bids_model/test_createDefaultStatsModel.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ function test_createDefaultStatsModel_basic()
1414

1515
BIDS = getLayout(opt);
1616

17+
% opt.dir.derivatives = pwd;
1718
opt.dir.derivatives = tempName();
1819
opt.space = {'IXI549Space'};
1920
opt.taskName = {'vislocalizer'};

tests/tests_preproc/utils/test_getAcquisitionTime.m

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,52 @@ function test_getAcquisitionTime_bug_967()
7777
getAcquisitionTime(sliceOrder, repetitionTime);
7878

7979
end
80+
81+
function test_openneuro_ds000224()
82+
% test a less brittle version of getAcquisitionTime
83+
84+
repetitionTime = 2.2;
85+
86+
sliceOrder = [
87+
1.105, ...
88+
0, ...
89+
1.1675, ...
90+
0.0625, ...
91+
1.2275, ...
92+
0.1225, ...
93+
1.29, ...
94+
0.185, ...
95+
1.35, ...
96+
0.245, ...
97+
1.4125, ...
98+
0.3075, ...
99+
1.4725, ...
100+
0.37, ...
101+
1.535, ...
102+
0.43, ...
103+
1.595, ...
104+
0.4925, ...
105+
1.6575, ...
106+
0.5525, ...
107+
1.7175, ...
108+
0.615, ...
109+
1.78, ...
110+
0.675, ...
111+
1.84, ...
112+
0.7375, ...
113+
1.9025, ...
114+
0.7975, ...
115+
1.965, ...
116+
0.86, ...
117+
2.025, ...
118+
0.92, ...
119+
2.0875, ...
120+
0.9825, ...
121+
2.1475, ...
122+
1.0425];
123+
124+
acquisitionTime = getAcquisitionTime(sliceOrder, repetitionTime);
125+
126+
assertElementsAlmostEqual(acquisitionTime, 2.1389, 'absolute', 1e-4);
127+
128+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function test_suite = test_endsWithRunNumber %#ok<*STOUT>
2+
% (C) Copyright 2022 bidspm developers
3+
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
4+
test_functions = localfunctions(); %#ok<*NASGU>
5+
catch % no problem; early Matlab versions can use initTestSuite fine
6+
end
7+
initTestSuite;
8+
end
9+
10+
function test_endsWithRunNumber_basic()
11+
12+
assertEqual(endsWithRunNumber('foo_1'), true);
13+
assertEqual(endsWithRunNumber('foo_1_'), false);
14+
assertEqual(endsWithRunNumber('foo_1_a'), false);
15+
assertEqual(endsWithRunNumber('foo_'), false);
16+
assertEqual(endsWithRunNumber('foo'), false);
17+
assertEqual(endsWithRunNumber('foo1'), false);
18+
19+
end

0 commit comments

Comments
 (0)