Skip to content

Commit 05f0b3e

Browse files
committed
Generate bold ref once after template created
1 parent 1ba6f5a commit 05f0b3e

5 files changed

Lines changed: 30 additions & 6 deletions

File tree

src/rbc/bids/longitudinal/functional.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def resolve_longitudinal_func(
5151
)
5252

5353
return {
54-
"template": tpl_q.expect(tpl_df, suffix="T1w"),
54+
"template": tpl_q.expect(tpl_df, res="bold", suffix="T1w"),
5555
"anat_to_template_xfm": tpl_q.expect(
5656
tpl_df,
5757
suffix="xfm",

src/rbc/bids/longitudinal/template.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ class TemplateInputs(NamedTuple):
2121
sub: Subject label.
2222
sessions: Per-input session labels (parallel to ``files``).
2323
files: Per-session preprocessed T1w brain volumes.
24+
bold_ref: First BOLD volume for grid reference
2425
"""
2526

2627
sub: str
2728
sessions: list[str]
2829
files: list[Path]
30+
bold_ref: Path | None
2931

3032

3133
def discover_template_inputs(
@@ -56,6 +58,17 @@ def discover_template_inputs(
5658
# the mri_robust_template invocation.
5759
pl.col("space").is_null(),
5860
)
61+
bold_ref_rows = df.filter(
62+
pl.col("ses") != "longitudinal",
63+
pl.col("datatype") == "func",
64+
pl.col("suffix") == "bold",
65+
pl.col("space").is_null(),
66+
)
67+
bold_ref = (
68+
None
69+
if bold_ref_rows.is_empty()
70+
else Path(bold_ref_rows["root"][0]) / bold_ref_rows["path"][0]
71+
)
5972

6073
inputs: list[TemplateInputs] = []
6174
skipped: list[str] = []
@@ -68,7 +81,9 @@ def discover_template_inputs(
6881
files = [
6982
Path(row["root"]) / row["path"] for row in sub_group.iter_rows(named=True)
7083
]
71-
inputs.append(TemplateInputs(sub=sub, sessions=sessions, files=files))
84+
inputs.append(
85+
TemplateInputs(sub=sub, sessions=sessions, files=files, bold_ref=bold_ref)
86+
)
7287
return inputs, skipped
7388

7489

@@ -81,6 +96,8 @@ def export_template(tpl: Bids, outputs: LongitudinalTemplateOutputs) -> None:
8196
outputs: Results from the longitudinal template workflow.
8297
"""
8398
tpl.save(outputs.template, suffix=Suffix.T1W)
99+
if outputs.bold_template is not None:
100+
tpl.save(outputs.bold_template, res="bold", suffix=Suffix.T1W)
84101
for ses, xfm in zip(outputs.sessions, outputs.transforms, strict=True):
85102
ses_label = bids_safe_label(ses)
86103
tpl.save(

src/rbc/orchestration/longitudinal/template.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def process_subject(
4949
sub=inputs.sub,
5050
sessions=inputs.sessions,
5151
in_files=inputs.files,
52+
bold_ref=inputs.bold_ref,
5253
)
5354
tpl = pipe_ctx.bids(datatype=Datatype.ANAT).derive(ses="longitudinal")
5455
export_template(tpl, outputs)

src/rbc/workflows/longitudinal/functional.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from typing import TYPE_CHECKING, NamedTuple
1313

1414
from rbc.core.functional import apply_regression, apply_regression_bandpass
15-
from rbc.core.longitudinal.resampling import resample_template_to_bold
1615
from rbc.core.longitudinal.transform import (
1716
compose_transform,
1817
func_transform,
@@ -83,10 +82,8 @@ def longitudinal_process(
8382
:class:`FunctionalLongOutputs` with all inputs transformed to
8483
longitudinal template space and per-regressor regression outputs.
8584
"""
86-
template_resampled = resample_template_to_bold(bold_ref=sbref, template=template)
87-
8885
bold_to_tpl_xfm = compose_transform(
89-
ref=template_resampled,
86+
ref=template,
9087
bold_to_anat_itk=bold_to_anat_itk,
9188
anat_to_tpl_xfm=anat_to_template_xfm,
9289
)

src/rbc/workflows/longitudinal/template.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
fs_to_itk_xfm,
1515
generate_robust_template,
1616
)
17+
from rbc.core.longitudinal.resampling import resample_template_to_bold
1718

1819
if TYPE_CHECKING:
1920
from collections.abc import Sequence
@@ -27,11 +28,13 @@ class LongitudinalTemplateOutputs(NamedTuple):
2728
2829
Attributes:
2930
template: Robust within-subject template volume.
31+
bold_template: Within-subject template volume resampled to BOLD resolution.
3032
sessions: Session labels in the same order as ``transforms``.
3133
transforms: Per-session ITK-format session-to-template transforms.
3234
"""
3335

3436
template: Path
37+
bold_template: Path | None
3538
sessions: list[str]
3639
transforms: list[Path]
3740

@@ -40,13 +43,15 @@ def generate_subject_template(
4043
sub: str,
4144
sessions: Sequence[str],
4245
in_files: Sequence[Path],
46+
bold_ref: Path | None = None,
4347
) -> LongitudinalTemplateOutputs:
4448
"""Build a robust template and ITK transforms for one subject.
4549
4650
Args:
4751
sub: Subject label (without the ``sub-`` prefix).
4852
sessions: Session labels parallel to ``in_files``.
4953
in_files: Per-session preprocessed T1w volumes (e.g. brain-extracted).
54+
bold_ref: Reference bold volume to resample template for functional data.
5055
5156
Returns:
5257
:class:`LongitudinalTemplateOutputs` ready for BIDS export.
@@ -65,8 +70,12 @@ def generate_subject_template(
6570
in_xfms=robust.transforms,
6671
)
6772

73+
if bold_ref is not None:
74+
bold_ref = resample_template_to_bold(bold_ref, robust.template)
75+
6876
return LongitudinalTemplateOutputs(
6977
template=robust.template,
78+
bold_template=bold_ref,
7079
sessions=list(sessions),
7180
transforms=itk_xfms,
7281
)

0 commit comments

Comments
 (0)