Skip to content

Commit d2dd98a

Browse files
committed
Try fixing.
1 parent ad3c3c6 commit d2dd98a

File tree

2 files changed

+190
-1
lines changed

2 files changed

+190
-1
lines changed

src/fmripost_aroma/workflows/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,12 +428,12 @@ def init_single_run_wf(bold_file):
428428

429429
if ('bold_mni152nlin6asym' not in functional_cache) and ('bold_raw' in functional_cache):
430430
# Resample to MNI152NLin6Asym:res-2, for ICA-AROMA classification
431-
from fmriprep.workflows.bold.apply import init_bold_volumetric_resample_wf
432431
from fmriprep.workflows.bold.stc import init_bold_stc_wf
433432
from niworkflows.interfaces.header import ValidateImage
434433
from templateflow.api import get as get_template
435434

436435
from fmripost_aroma.interfaces.misc import ApplyTransforms
436+
from fmripost_aroma.workflows.resample import init_bold_volumetric_resample_wf
437437

438438
workflow.__desc__ += """\
439439
Raw BOLD series were resampled to MNI152NLin6Asym:res-2, for ICA-AROMA classification.
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
from __future__ import annotations
2+
3+
import nipype.interfaces.utility as niu
4+
import nipype.pipeline.engine as pe
5+
from fmriprep.interfaces.resampling import DistortionParameters, ResampleSeries
6+
from niworkflows.interfaces.nibabel import GenerateSamplingReference
7+
from niworkflows.interfaces.utility import KeySelect
8+
9+
10+
def init_bold_volumetric_resample_wf(
11+
*,
12+
metadata: dict,
13+
mem_gb: dict[str, float],
14+
jacobian: bool,
15+
fieldmap_id: str | None = None,
16+
omp_nthreads: int = 1,
17+
name: str = 'bold_volumetric_resample_wf',
18+
) -> pe.Workflow:
19+
"""Resample a BOLD series to a volumetric target space.
20+
21+
This workflow collates a sequence of transforms to resample a BOLD series
22+
in a single shot, including motion correction and fieldmap correction, if
23+
requested.
24+
25+
.. workflow::
26+
27+
from fmripost_aroma.workflows.bold.resampling import init_bold_volumetric_resample_wf
28+
29+
wf = init_bold_volumetric_resample_wf(
30+
metadata={
31+
'RepetitionTime': 2.0,
32+
'PhaseEncodingDirection': 'j-',
33+
'TotalReadoutTime': 0.03
34+
},
35+
mem_gb={'resampled': 1},
36+
jacobian=True,
37+
fieldmap_id='my_fieldmap',
38+
)
39+
40+
Parameters
41+
----------
42+
metadata
43+
BIDS metadata for BOLD file.
44+
fieldmap_id
45+
Fieldmap identifier, if fieldmap correction is to be applied.
46+
omp_nthreads
47+
Maximum number of threads an individual process may use.
48+
name
49+
Name of workflow (default: ``bold_volumetric_resample_wf``)
50+
51+
Inputs
52+
------
53+
bold_file
54+
BOLD series to resample.
55+
bold_ref_file
56+
Reference image to which BOLD series is aligned.
57+
target_ref_file
58+
Reference image defining the target space.
59+
target_mask
60+
Brain mask corresponding to ``target_ref_file``.
61+
This is used to define the field of view for the resampled BOLD series.
62+
motion_xfm
63+
List of affine transforms aligning each volume to ``bold_ref_file``.
64+
If undefined, no motion correction is performed.
65+
fmap
66+
Fieldmap image.
67+
fmap_id
68+
Fieldmap identifier, to select correct fieldmap in case there are multiple.
69+
boldref2anat_xfm
70+
Affine transform from ``bold_ref_file`` to the anatomical reference image.
71+
anat2std_xfm
72+
Affine transform from the anatomical reference image to standard space.
73+
Leave undefined to resample to anatomical reference space.
74+
75+
Outputs
76+
-------
77+
bold_file
78+
The ``bold_file`` input, resampled to ``target_ref_file`` space.
79+
resampling_reference
80+
An empty reference image with the correct affine and header for resampling
81+
further images into the BOLD series' space.
82+
83+
"""
84+
workflow = pe.Workflow(name=name)
85+
86+
inputnode = pe.Node(
87+
niu.IdentityInterface(
88+
fields=[
89+
'bold_file',
90+
'bold_ref_file',
91+
'target_ref_file',
92+
'target_mask',
93+
# HMC
94+
'motion_xfm',
95+
# SDC
96+
'fmap',
97+
'fmap_id',
98+
# Anatomical
99+
'boldref2anat_xfm',
100+
# Template
101+
'anat2std_xfm',
102+
# Entity for selecting target resolution
103+
'resolution',
104+
],
105+
),
106+
name='inputnode',
107+
)
108+
109+
outputnode = pe.Node(
110+
niu.IdentityInterface(fields=['bold_file', 'resampling_reference']),
111+
name='outputnode',
112+
)
113+
114+
gen_ref = pe.Node(GenerateSamplingReference(), name='gen_ref', mem_gb=0.3)
115+
116+
boldref2target = pe.Node(niu.Merge(2), name='boldref2target', run_without_submitting=True)
117+
bold2target = pe.Node(niu.Merge(2), name='bold2target', run_without_submitting=True)
118+
resample = pe.Node(
119+
ResampleSeries(jacobian=jacobian),
120+
name='resample',
121+
n_procs=omp_nthreads,
122+
mem_gb=mem_gb['resampled'],
123+
)
124+
125+
workflow.connect([
126+
(inputnode, gen_ref, [
127+
('bold_ref_file', 'moving_image'),
128+
('target_ref_file', 'fixed_image'),
129+
('target_mask', 'fov_mask'),
130+
(('resolution', _is_native), 'keep_native'),
131+
]),
132+
(inputnode, boldref2target, [
133+
('boldref2anat_xfm', 'in1'),
134+
('anat2std_xfm', 'in2'),
135+
]),
136+
(inputnode, bold2target, [('motion_xfm', 'in1')]),
137+
(inputnode, resample, [('bold_file', 'in_file')]),
138+
(gen_ref, resample, [('out_file', 'ref_file')]),
139+
(boldref2target, bold2target, [('out', 'in2')]),
140+
(bold2target, resample, [('out', 'transforms')]),
141+
(gen_ref, outputnode, [('out_file', 'resampling_reference')]),
142+
(resample, outputnode, [('out_file', 'bold_file')]),
143+
]) # fmt:skip
144+
145+
if not fieldmap_id:
146+
return workflow
147+
148+
fmap_select = pe.Node(
149+
KeySelect(fields=['fmap'], key=fieldmap_id),
150+
name='fmap_select',
151+
run_without_submitting=True,
152+
)
153+
distortion_params = pe.Node(
154+
DistortionParameters(metadata=metadata),
155+
name='distortion_params',
156+
run_without_submitting=True,
157+
)
158+
workflow.connect([
159+
(inputnode, fmap_select, [
160+
('fmap', 'fmap_ref'),
161+
('fmap_id', 'keys'),
162+
]),
163+
(inputnode, distortion_params, [('bold_file', 'in_file')]),
164+
# Inject fieldmap correction into resample node
165+
(fmap_select, resample, [('fmap', 'fieldmap')]),
166+
(distortion_params, resample, [
167+
('readout_time', 'ro_time'),
168+
('pe_direction', 'pe_dir'),
169+
]),
170+
]) # fmt:skip
171+
172+
return workflow
173+
174+
175+
def _gen_inverses(inlist: list) -> list[bool]:
176+
"""Create a list indicating the first transform should be inverted.
177+
178+
The input list is the collection of transforms that follow the
179+
inverted one.
180+
"""
181+
from niworkflows.utils.connections import listify
182+
183+
if not inlist:
184+
return [True]
185+
return [True] + [False] * len(listify(inlist))
186+
187+
188+
def _is_native(value):
189+
return value == 'native'

0 commit comments

Comments
 (0)