Skip to content

Commit fb1ffdc

Browse files
committed
Merge pull request #285 from poldracklab/oesteban-patch-1
[HOTFIX] Fix ``UnboundLocalError`` in utils.bids
1 parent 4e97c8c commit fb1ffdc

File tree

1 file changed

+95
-17
lines changed

1 file changed

+95
-17
lines changed

niworkflows/utils/bids.py

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
99
"""
1010
from pathlib import Path
11-
from itertools import groupby
1211
import warnings
1312
import re
1413
import simplejson as json
@@ -163,22 +162,9 @@ def collect_data(dataset, participant_label, task=None, echo=None):
163162
subj_data = {modality: [x.filename for x in layout.get(**query)]
164163
for modality, query in queries.items()}
165164

166-
def _grp_echos(x):
167-
if '_echo-' not in x:
168-
return x
169-
echo = re.search("_echo-\\d*", x).group(0)
170-
return x.replace(echo, "_echo-?")
171-
172-
if subj_data["bold"]:
173-
bold_sess = subj_data["bold"]
174-
175-
if any(['_echo-' in bold for bold in bold_sess]):
176-
ses_uids = [list(bold) for _, bold in groupby(bold_sess, key=_grp_echos)]
177-
ses_uids = [x[0] if len(x) == 1 else x for x in ses_uids]
178-
else:
179-
ses_uids = bold_sess
180-
181-
subj_data.update({"bold": ses_uids})
165+
# Special case: multi-echo BOLD, grouping echos
166+
if any(['_echo-' in bold for bold in subj_data['bold']]):
167+
subj_data['bold'] = group_multiecho(subj_data['bold'])
182168

183169
return subj_data, layout
184170

@@ -241,3 +227,95 @@ def get_metadata_for_nifti(in_file):
241227
json.loads(json_file_path.read_text()))
242228

243229
return merged_param_dict
230+
231+
232+
def group_multiecho(bold_sess):
233+
"""
234+
Multiplexes multi-echo EPIs into arrays. Dual-echo is a special
235+
case of multi-echo, which is treated as single-echo data.
236+
237+
>>> bold_sess = ["sub-01_task-rest_echo-1_run-01_bold.nii.gz",
238+
... "sub-01_task-rest_echo-2_run-01_bold.nii.gz",
239+
... "sub-01_task-rest_echo-1_run-02_bold.nii.gz",
240+
... "sub-01_task-rest_echo-2_run-02_bold.nii.gz",
241+
... "sub-01_task-rest_echo-3_run-02_bold.nii.gz",
242+
... "sub-01_task-rest_run-03_bold.nii.gz"]
243+
>>> group_multiecho(bold_sess)
244+
['sub-01_task-rest_echo-1_run-01_bold.nii.gz',
245+
'sub-01_task-rest_echo-2_run-01_bold.nii.gz',
246+
['sub-01_task-rest_echo-1_run-02_bold.nii.gz',
247+
'sub-01_task-rest_echo-2_run-02_bold.nii.gz',
248+
'sub-01_task-rest_echo-3_run-02_bold.nii.gz'],
249+
'sub-01_task-rest_run-03_bold.nii.gz']
250+
251+
>>> bold_sess.insert(2, "sub-01_task-rest_echo-3_run-01_bold.nii.gz")
252+
>>> group_multiecho(bold_sess)
253+
[['sub-01_task-rest_echo-1_run-01_bold.nii.gz',
254+
'sub-01_task-rest_echo-2_run-01_bold.nii.gz',
255+
'sub-01_task-rest_echo-3_run-01_bold.nii.gz'],
256+
['sub-01_task-rest_echo-1_run-02_bold.nii.gz',
257+
'sub-01_task-rest_echo-2_run-02_bold.nii.gz',
258+
'sub-01_task-rest_echo-3_run-02_bold.nii.gz'],
259+
'sub-01_task-rest_run-03_bold.nii.gz']
260+
261+
>>> bold_sess += ["sub-01_task-beh_echo-1_run-01_bold.nii.gz",
262+
... "sub-01_task-beh_echo-2_run-01_bold.nii.gz",
263+
... "sub-01_task-beh_echo-1_run-02_bold.nii.gz",
264+
... "sub-01_task-beh_echo-2_run-02_bold.nii.gz",
265+
... "sub-01_task-beh_echo-3_run-02_bold.nii.gz",
266+
... "sub-01_task-beh_run-03_bold.nii.gz"]
267+
>>> group_multiecho(bold_sess)
268+
[['sub-01_task-rest_echo-1_run-01_bold.nii.gz',
269+
'sub-01_task-rest_echo-2_run-01_bold.nii.gz',
270+
'sub-01_task-rest_echo-3_run-01_bold.nii.gz'],
271+
['sub-01_task-rest_echo-1_run-02_bold.nii.gz',
272+
'sub-01_task-rest_echo-2_run-02_bold.nii.gz',
273+
'sub-01_task-rest_echo-3_run-02_bold.nii.gz'],
274+
'sub-01_task-rest_run-03_bold.nii.gz',
275+
'sub-01_task-beh_echo-1_run-01_bold.nii.gz',
276+
'sub-01_task-beh_echo-2_run-01_bold.nii.gz',
277+
['sub-01_task-beh_echo-1_run-02_bold.nii.gz',
278+
'sub-01_task-beh_echo-2_run-02_bold.nii.gz',
279+
'sub-01_task-beh_echo-3_run-02_bold.nii.gz'],
280+
'sub-01_task-beh_run-03_bold.nii.gz']
281+
282+
Some tests from https://neurostars.org/t/fmriprep-from\
283+
-singularity-unboundlocalerror/3299/7
284+
285+
>>> bold_sess = ['sub-01_task-AudLoc_echo-1_bold.nii',
286+
... 'sub-01_task-AudLoc_echo-2_bold.nii',
287+
... 'sub-01_task-FJT_echo-1_bold.nii',
288+
... 'sub-01_task-FJT_echo-2_bold.nii',
289+
... 'sub-01_task-LDT_echo-1_bold.nii',
290+
... 'sub-01_task-LDT_echo-2_bold.nii',
291+
... 'sub-01_task-MotLoc_echo-1_bold.nii',
292+
... 'sub-01_task-MotLoc_echo-2_bold.nii']
293+
>>> group_multiecho(bold_sess) == bold_sess
294+
True
295+
296+
>>> bold_sess += ['sub-01_task-MotLoc_echo-3_bold.nii']
297+
>>> groups = group_multiecho(bold_sess)
298+
>>> len(groups[:-1])
299+
6
300+
>>> [isinstance(g, list) for g in groups]
301+
[False, False, False, False, False, False, True]
302+
>>> len(groups[-1])
303+
3
304+
305+
306+
"""
307+
from itertools import groupby
308+
309+
def _grp_echos(x):
310+
if '_echo-' not in x:
311+
return x
312+
echo = re.search("_echo-\\d*", x).group(0)
313+
return x.replace(echo, "_echo-?")
314+
315+
ses_uids = []
316+
for _, bold in groupby(bold_sess, key=_grp_echos):
317+
bold = list(bold)
318+
# If single- or dual-echo, flatten list; keep list otherwise.
319+
action = getattr(ses_uids, 'append' if len(bold) > 2 else 'extend')
320+
action(bold)
321+
return ses_uids

0 commit comments

Comments
 (0)