Skip to content

Commit 485ec2d

Browse files
Copilotakhanf
andauthored
Add --via-template option for multi-step template registration
- Add --via-template CLI option to snakebids.yml - Add via_template variable and validation to Snakefile - Add get_composite_warp, get_composite_warp_inv, get_affine_warped_for_qc helper functions to common.smk - Create viatemplatereg.smk with template-to-template registration rules - Update downstream rules in templatereg.smk, heatmaps.smk, regionprops.smk, preproc_mri.smk to use helper functions Agent-Logs-Url: https://github.com/khanlab/SPIMquant/sessions/9792c81e-e8e2-4bbf-805c-cfc28d084f2f Co-authored-by: akhanf <11492701+akhanf@users.noreply.github.com>
1 parent 57b430d commit 485ec2d

8 files changed

Lines changed: 453 additions & 17 deletions

File tree

spimquant/config/snakebids.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ parse_args:
6363
- MBMv3
6464
- turone
6565

66+
--via-template:
67+
help: "Intermediate template for multi-step registration. Subject is first registered to this template, then this template is registered to the final --template. Transforms are concatenated to produce a single subject-to-template composite warp. (default: %(default)s)"
68+
default: null
69+
choices:
70+
- ABAv3
71+
- DSURQE
72+
- gubra
73+
- MBMv3
74+
- turone
75+
6676
--atlas_segs:
6777
help: "Atlas segmentations to use with the chosen template (default: predefined list or all)"
6878
default: null

spimquant/workflow/Snakefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ stain_for_reg = None
5757

5858
template = config["templates"][config["template"]]
5959

60+
via_template = config.get("via_template", None)
61+
62+
if via_template is not None:
63+
if via_template == config["template"]:
64+
raise ValueError(
65+
f"--via-template ({via_template}) must be different from --template ({config['template']})"
66+
)
67+
if via_template not in config["templates"]:
68+
raise ValueError(
69+
f"--via-template ({via_template}) not found in configured templates: "
70+
f"{list(config['templates'].keys())}"
71+
)
72+
6073

6174
# first, check if there are any SPIM templates defined
6275
# for the stains we have
@@ -923,6 +936,11 @@ include: "rules/groupstats.smk"
923936
include: "rules/qc.smk"
924937

925938

939+
if via_template is not None:
940+
941+
include: "rules/viatemplatereg.smk"
942+
943+
926944
if config["register_to_mri"]:
927945

928946
include: "rules/preproc_mri.smk"

spimquant/workflow/rules/common.smk

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,80 @@ def get_regionprops_parquet(wildcards):
8686
suffix="regionprops.parquet",
8787
**inputs["spim"].wildcards,
8888
)
89+
90+
91+
def get_composite_warp(wildcards):
92+
"""Get the composite warp from subject to template space.
93+
94+
Returns the path to either the direct composite warp (no via-template)
95+
or the combined via-template composite warp if --via-template is configured.
96+
"""
97+
spim_wildcards = {k: getattr(wildcards, k) for k in inputs["spim"].wildcards.keys()}
98+
if via_template is None:
99+
return bids(
100+
root=root,
101+
datatype="xfm",
102+
from_="subject",
103+
to=wildcards.template,
104+
suffix="xfm.nii.gz",
105+
**spim_wildcards,
106+
)
107+
else:
108+
return bids(
109+
root=root,
110+
datatype="xfm",
111+
from_="subject",
112+
to=wildcards.template,
113+
via=via_template,
114+
suffix="xfm.nii.gz",
115+
**spim_wildcards,
116+
)
117+
118+
119+
def get_composite_warp_inv(wildcards):
120+
"""Get the inverse composite warp from template to subject space.
121+
122+
Returns the path to either the direct inverse composite warp (no via-template)
123+
or the combined via-template inverse composite warp if --via-template is configured.
124+
"""
125+
spim_wildcards = {k: getattr(wildcards, k) for k in inputs["spim"].wildcards.keys()}
126+
if via_template is None:
127+
return bids(
128+
root=root,
129+
datatype="xfm",
130+
from_=wildcards.template,
131+
to="subject",
132+
suffix="xfm.nii.gz",
133+
**spim_wildcards,
134+
)
135+
else:
136+
return bids(
137+
root=root,
138+
datatype="xfm",
139+
from_=wildcards.template,
140+
to="subject",
141+
via=via_template,
142+
suffix="xfm.nii.gz",
143+
**spim_wildcards,
144+
)
145+
146+
147+
def get_affine_warped_for_qc(wildcards):
148+
"""Get the affine-warped SPIM image for QC report.
149+
150+
Returns the affine-warped image in the appropriate space:
151+
- Without via-template: image is warped to the final template space
152+
- With via-template: image is warped to the intermediate (via) template space,
153+
since that is where the affine registration is performed.
154+
"""
155+
spim_wildcards = {k: getattr(wildcards, k) for k in inputs["spim"].wildcards.keys()}
156+
target_space = via_template if via_template is not None else wildcards.template
157+
return bids(
158+
root=root,
159+
datatype="xfm",
160+
space=target_space,
161+
stain=wildcards.stain,
162+
desc="affinewarped",
163+
suffix="SPIM.nii.gz",
164+
**spim_wildcards,
165+
)

spimquant/workflow/rules/heatmaps.smk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ rule deform_fieldfrac_nii_to_template_nii:
9090
**inputs["spim"].wildcards,
9191
),
9292
ref=rules.import_template_anat.output.anat,
93-
xfm_composite=rules.compose_subject_to_template_warp.output.xfm_composite,
93+
xfm_composite=get_composite_warp,
9494
output:
9595
nii=bids(
9696
root=root,

spimquant/workflow/rules/preproc_mri.smk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ rule warp_mri_to_template_via_spim:
709709
),
710710
ref=rules.import_template_anat.output.anat,
711711
xfm_composite_mri_to_spim=rules.compose_mri_to_spim_warp.output.xfm_composite,
712-
xfm_composite_spim_to_template=rules.compose_subject_to_template_warp.output.xfm_composite,
712+
xfm_composite_spim_to_template=get_composite_warp,
713713
output:
714714
warped=bids(
715715
root=root,

spimquant/workflow/rules/regionprops.smk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ rule transform_regionprops_to_template:
4646
suffix="regionprops.parquet",
4747
**inputs["spim"].wildcards,
4848
),
49-
xfm_composite_inv=rules.compose_subject_to_template_warp.output.xfm_composite_inv,
49+
xfm_composite_inv=get_composite_warp_inv,
5050
params:
5151
coord_column_names=config["coord_column_names"],
5252
output:

spimquant/workflow/rules/templatereg.smk

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ rule affine_zarr_to_template_ome_zarr:
471471

472472
rule deform_zarr_to_template_nii:
473473
input:
474-
xfm_composite=rules.compose_subject_to_template_warp.output.xfm_composite,
474+
xfm_composite=get_composite_warp,
475475
ref_nii=get_template_for_reg,
476476
params:
477477
ome_zarr=inputs["spim"].path,
@@ -500,7 +500,7 @@ rule deform_zarr_to_template_nii:
500500
rule deform_to_template_nii_zoomed:
501501
input:
502502
ome_zarr=inputs["spim"].path,
503-
xfm_composite=rules.compose_subject_to_template_warp.output.xfm_composite,
503+
xfm_composite=get_composite_warp,
504504
ref_nii=get_template_for_reg,
505505
params:
506506
flo_opts={}, #any additional flo znimg options
@@ -544,7 +544,7 @@ rule deform_spim_nii_to_template_nii:
544544
**inputs["spim"].wildcards,
545545
),
546546
ref=rules.import_template_anat.output.anat,
547-
xfm_composite=rules.compose_subject_to_template_warp.output.xfm_composite,
547+
xfm_composite=get_composite_warp,
548548
output:
549549
spim=bids(
550550
root=root,
@@ -585,7 +585,7 @@ rule deform_template_dseg_to_subject_nii:
585585
**inputs["spim"].wildcards,
586586
),
587587
dseg=bids(root=root, template="{template}", seg="{seg}", suffix="dseg.nii.gz"),
588-
xfm_composite_inv=rules.compose_subject_to_template_warp.output.xfm_composite_inv,
588+
xfm_composite_inv=get_composite_warp_inv,
589589
output:
590590
dseg=bids(
591591
root=root,
@@ -679,15 +679,7 @@ rule registration_qc_report:
679679
suffix="SPIM.nii.gz",
680680
**inputs["spim"].wildcards,
681681
),
682-
warped_affine=bids(
683-
root=root,
684-
datatype="xfm",
685-
space="{template}",
686-
stain="{stain}",
687-
desc="affinewarped",
688-
suffix="SPIM.nii.gz",
689-
**inputs["spim"].wildcards,
690-
),
682+
warped_affine=get_affine_warped_for_qc,
691683
warped_deform=bids(
692684
root=root,
693685
datatype="micr",
@@ -697,7 +689,7 @@ rule registration_qc_report:
697689
suffix="SPIM.nii.gz",
698690
**inputs["spim"].wildcards,
699691
),
700-
warp=rules.compose_subject_to_template_warp.output.xfm_composite,
692+
warp=get_composite_warp,
701693
dseg=lambda wildcards: bids(
702694
root=root,
703695
template=wildcards.template,

0 commit comments

Comments
 (0)