Skip to content

Commit f8e9813

Browse files
authored
Merge pull request #285 from poldracklab/oesteban-patch-1
[HOTFIX] Fix ``UnboundLocalError`` in utils.bids
2 parents 608660f + 79f9b91 commit f8e9813

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
@@ -167,22 +166,9 @@ def collect_data(dataset, participant_label, task=None, echo=None):
167166
subj_data = {modality: [x.filename for x in layout.get(**query)]
168167
for modality, query in queries.items()}
169168

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

187173
return subj_data, layout
188174

@@ -245,3 +231,95 @@ def get_metadata_for_nifti(in_file):
245231
json.loads(json_file_path.read_text()))
246232

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

0 commit comments

Comments
 (0)