Skip to content

Commit

Permalink
Treat anatomical data differently in data collection (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo authored Sep 23, 2024
1 parent fbf0540 commit 2f1aade
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 29 deletions.
35 changes: 22 additions & 13 deletions src/fmripost_aroma/data/io_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
".nii"
]
},
"confounds": {
"bold_confounds": {
"datatype": "func",
"echo": null,
"part": [
Expand All @@ -79,12 +79,27 @@
".tsv"
]
},
"anat_mni152nlin6asym": {
"datatype": "anat",
"echo": null,
"part": [
"mag",
null
],
"res": "2",
"space": "MNI152NLin6Asym",
"desc": "preproc",
"suffix": [
"T1w",
"T2w"
],
"extension": [
".nii.gz",
".nii"
]
},
"anat_dseg": {
"datatype": "anat",
"task": null,
"acquisition": null,
"run": null,
"part": null,
"space": null,
"res": null,
"den": null,
Expand All @@ -97,9 +112,8 @@
}
},
"transforms": {
"hmc": {
"bold_hmc": {
"datatype": "func",
"part": null,
"from": "orig",
"to": "boldref",
"mode": "image",
Expand All @@ -108,7 +122,6 @@
},
"boldref2anat": {
"datatype": "func",
"part": null,
"from": "boldref",
"to": ["anat", "T1w", "T2w"],
"mode": "image",
Expand All @@ -117,18 +130,14 @@
},
"boldref2fmap": {
"datatype": "func",
"part": null,
"from": "boldref",
"from": "orig",
"mode": "image",
"suffix": "xfm",
"extension": ".txt"
},
"anat2mni152nlin6asym": {
"datatype": "anat",
"task": null,
"acquisition": null,
"run": null,
"part": null,
"from": ["anat", "T1w", "T2w"],
"to": "MNI152NLin6Asym",
"space": null,
Expand Down
8 changes: 4 additions & 4 deletions src/fmripost_aroma/tests/test_utils_bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ def test_collect_derivatives_minimal(minimal_ignore_list):
# TODO: Add bold_mask_native to the dataset
# 'bold_mask_native': 'sub-01_task-mixedgamblestask_run-01_desc-brain_mask.nii.gz',
'bold_mask_native': None,
'confounds': None,
'hmc': (
'bold_confounds': None,
'bold_hmc': (
'sub-01_task-mixedgamblestask_run-01_from-orig_to-boldref_mode-image_desc-hmc_xfm.txt'
),
'boldref2anat': (
Expand Down Expand Up @@ -123,8 +123,8 @@ def test_collect_derivatives_full(full_ignore_list):
'mask.nii.gz'
),
'bold_mask_native': None,
'confounds': 'sub-01_task-mixedgamblestask_run-01_desc-confounds_timeseries.tsv',
'hmc': (
'bold_confounds': 'sub-01_task-mixedgamblestask_run-01_desc-confounds_timeseries.tsv',
'bold_hmc': (
'sub-01_task-mixedgamblestask_run-01_from-orig_to-boldref_mode-image_desc-hmc_xfm.txt'
),
'boldref2anat': (
Expand Down
34 changes: 27 additions & 7 deletions src/fmripost_aroma/utils/bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,43 @@ def collect_derivatives(
)

for k, q in spec['derivatives'].items():
# Combine entities with query. Query values override file entities.
query = {**entities, **q}
if k.startswith('anat'):
# Allow anatomical derivatives at session level or subject level
query = {**{'session': [entities.get('session'), None]}, **q}
else:
# Combine entities with query. Query values override file entities.
query = {**entities, **q}

item = layout.get(return_type='filename', **query)
if not item:
derivs_cache[k] = None
elif not allow_multiple and len(item) > 1 and k.startswith('anat'):
# Anatomical derivatives are allowed to have multiple files (e.g., T1w and T2w)
# but we just grab the first one
derivs_cache[k] = item[0]
elif not allow_multiple and len(item) > 1:
raise ValueError(f'Multiple files found for {k}: {item}')
else:
derivs_cache[k] = item[0] if len(item) == 1 else item

for k, q in spec['transforms'].items():
# Combine entities with query. Query values override file entities.
# TODO: Drop functional entities (task, run, etc.) from anat transforms.
query = {**entities, **q}
if k.startswith('anat'):
# Allow anatomical derivatives at session level or subject level
query = {**{'session': [entities.get('session'), None]}, **q}
else:
# Combine entities with query. Query values override file entities.
query = {**entities, **q}

if k == 'boldref2fmap':
query['to'] = fieldmap_id

item = layout.get(return_type='filename', **query)
if not item:
derivs_cache[k] = None
elif not allow_multiple and len(item) > 1 and k.startswith('anat'):
# Anatomical derivatives are allowed to have multiple files (e.g., T1w and T2w)
# but we just grab the first one
derivs_cache[k] = item[0]
elif not allow_multiple and len(item) > 1:
raise ValueError(f'Multiple files found for {k}: {item}')
else:
Expand Down Expand Up @@ -178,8 +195,11 @@ def collect_derivatives(

spaces_found, anat2outputspaces_xfm = [], []
for space in spaces.references:
# First try to find processed BOLD+mask files in the requested space
anat2space_query = {**entities, **spec['transforms']['anat2mni152nlin6asym']}
# Now try to find transform to the requested space
anat2space_query = {
**{'session': [entities.get('session'), None]},
**spec['transforms']['anat2mni152nlin6asym'],
}
anat2space_query['to'] = space.space
item = layout.get(return_type='filename', **anat2space_query)
anat2outputspaces_xfm.append(item[0] if item else None)
Expand Down
10 changes: 5 additions & 5 deletions src/fmripost_aroma/workflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def init_single_run_wf(bold_file):
),
)

if not functional_cache['confounds']:
if not functional_cache['bold_confounds']:
if config.workflow.dummy_scans is None:
raise ValueError(
'No confounds detected. '
Expand Down Expand Up @@ -357,17 +357,17 @@ def init_single_run_wf(bold_file):
if config.workflow.dummy_scans is not None:
skip_vols = config.workflow.dummy_scans
else:
if not functional_cache['confounds']:
if not functional_cache['bold_confounds']:
raise ValueError(
'No confounds detected. '
'Automatical dummy scan detection cannot be performed. '
'Please set the `--dummy-scans` flag explicitly.'
)
skip_vols = get_nss(functional_cache['confounds'])
skip_vols = get_nss(functional_cache['bold_confounds'])

# Run ICA-AROMA
ica_aroma_wf = init_ica_aroma_wf(bold_file=bold_file, metadata=bold_metadata, mem_gb=mem_gb)
ica_aroma_wf.inputs.inputnode.confounds = functional_cache['confounds']
ica_aroma_wf.inputs.inputnode.confounds = functional_cache['bold_confounds']
ica_aroma_wf.inputs.inputnode.skip_vols = skip_vols

mni6_buffer = pe.Node(niu.IdentityInterface(fields=['bold', 'bold_mask']), name='mni6_buffer')
Expand Down Expand Up @@ -427,7 +427,7 @@ def init_single_run_wf(bold_file):
jacobian='fmap-jacobian' not in config.workflow.ignore,
name='bold_MNI6_wf',
)
bold_MNI6_wf.inputs.inputnode.motion_xfm = functional_cache['hmc']
bold_MNI6_wf.inputs.inputnode.motion_xfm = functional_cache['bold_hmc']
bold_MNI6_wf.inputs.inputnode.boldref2fmap_xfm = functional_cache['boldref2fmap']
bold_MNI6_wf.inputs.inputnode.boldref2anat_xfm = functional_cache['boldref2anat']
bold_MNI6_wf.inputs.inputnode.anat2std_xfm = functional_cache['anat2mni152nlin6asym']
Expand Down

0 comments on commit 2f1aade

Please sign in to comment.