Skip to content

Commit ee1f006

Browse files
tsalomattcieslak
andauthored
Clean up intramodal template workflows and add boilerplate text (#1095)
* Remove unused workflows. Remove init_qsiprep_intramodal_template_wf, nonlinear_alignment_iteration, and init_nonlinear_alignment_wf from qsiprep.workflows.dwi.intramodal_template. If we ever decide to enable these, we can pull them from the history. * Remove duplicate _list_squeeze function. * Remove unused mem_gb arg from init_intramodal_template_wf. * Restructure intramodal template section. There were unnecessary if statements, separation of workflow connections, etc. * Reorder parameters. * Add boilerplate for intramodal template. * Run ruff. * Use consistent connection format. * Fix mistake and clean up init_b0_hmc_wf. * Fix comment. * Work on review. * more informative boilerplate --------- Co-authored-by: mattcieslak <mattcieslak@gmail.com>
1 parent 06df85a commit ee1f006

5 files changed

Lines changed: 209 additions & 444 deletions

File tree

qsiprep/cli/parser.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,10 +669,15 @@ def _bids_filter(value, parser):
669669
action='store',
670670
default=0,
671671
type=int,
672-
help='Number of iterations for finding the midpoint image '
673-
'from the b0 templates from all groups. Has no effect if there '
674-
'is only one group. If 0, all b0 templates are directly registered '
675-
'to the t1w image.',
672+
help=(
673+
'Number of iterations for finding the midpoint image '
674+
'from the b0 templates from all DWI runs and sessions. '
675+
'Has no effect if there is only one group. '
676+
'If 0, all b0 templates are directly registered to the t1w image. '
677+
'Enabling the intramodal template method when there are multiple runs/sessions '
678+
'results in a single DWI reference image, which makes it possible to '
679+
'directly compare AC-PC-space preprocessed DWI data across groups.'
680+
),
676681
)
677682
g_coreg.add_argument(
678683
'--intramodal-template-transform',

qsiprep/data/reports-spec.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ sections:
3030
subtitle: Spatial normalization of the anatomical reference
3131

3232
- bids: {datatype: figures, desc: intramodalcoreg, suffix: [T1w, T2w]}
33-
caption: Coregistration between the intramodal DWI template to the anatomical reference image.
33+
caption: Coregistration of the intramodal DWI template to the anatomical reference image.
3434
static: false
35-
subtitle: Coregistration of the Intramodal to anatomical templates
35+
subtitle: Coregistration of the intramodal to anatomical templates
3636

3737
- name: <em>B<sub>0</sub></em> field mapping
3838
ordering: session,acquisition,run,fmapid
@@ -239,7 +239,7 @@ sections:
239239
caption: |
240240
b=0 reference image warped to the across-scan/session intramodal template.
241241
static: false
242-
subtitle: Alignment of dMRI to Intramodal Template
242+
subtitle: Alignment of dMRI to intramodal template
243243

244244
- bids: {datatype: figures, desc: acpc, suffix: dwi}
245245
caption: |

qsiprep/workflows/base.py

Lines changed: 74 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -418,25 +418,34 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
418418
else:
419419
make_intramodal_template = True
420420

421-
anat_source_file = fix_multi_source_name(
422-
subject_data[info_modality],
423-
include_session=config.workflow.subject_anatomical_reference == 'sessionwise',
424-
anatomical_contrast=config.workflow.anat_modality,
425-
)
426-
intramodal_template_wf = init_intramodal_template_wf(
427-
t1w_source_file=anat_source_file,
428-
inputs_list=sorted(outputs_to_files.keys()),
429-
transform=config.workflow.intramodal_template_transform,
430-
num_iterations=config.workflow.intramodal_template_iters or 2,
431-
name='intramodal_template_wf',
432-
)
433-
# TemplateQC and the per-group orig->intramodal transform export exist only
434-
# for linear templates: mvtc2 exposes no per-input aligned images, and its
435-
# per-group transform is an [affine, warp] pair that does not fit a
436-
# single-file .mat sink.
437-
intramodal_linear = config.workflow.intramodal_template_transform in ('Rigid', 'Affine')
438-
439421
if make_intramodal_template:
422+
anat_source_file = fix_multi_source_name(
423+
subject_data[info_modality],
424+
include_session=config.workflow.subject_anatomical_reference == 'sessionwise',
425+
anatomical_contrast=config.workflow.anat_modality,
426+
)
427+
428+
intramodal_template_wf = init_intramodal_template_wf(
429+
inputs_list=sorted(outputs_to_files.keys()),
430+
t1w_source_file=anat_source_file,
431+
transform=config.workflow.intramodal_template_transform,
432+
num_iterations=config.workflow.intramodal_template_iters or 2,
433+
name='intramodal_template_wf',
434+
)
435+
workflow.connect([
436+
(anat_preproc_wf, intramodal_template_wf, [
437+
('outputnode.t1_preproc', 'inputnode.t1_preproc'),
438+
('outputnode.t1_brain', 'inputnode.t1_brain'),
439+
('outputnode.t1_mask', 'inputnode.t1_mask'),
440+
('outputnode.t1_seg', 'inputnode.t1_seg'),
441+
('outputnode.t1_aseg', 'inputnode.t1_aseg'),
442+
('outputnode.t1_aparc', 'inputnode.t1_aparc'),
443+
('outputnode.t1_2_mni_forward_transform', 'inputnode.t1_2_mni_forward_transform'),
444+
('outputnode.t1_2_mni_reverse_transform', 'inputnode.t1_2_mni_reverse_transform'),
445+
('outputnode.dwi_sampling_grid', 'inputnode.dwi_sampling_grid'),
446+
]),
447+
]) # fmt:skip
448+
440449
ds_intramodal_template = pe.Node(
441450
DerivativesDataSink(
442451
source_file=anat_source_file,
@@ -451,6 +460,15 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
451460
name='ds_intramodal_template',
452461
run_without_submitting=True,
453462
)
463+
workflow.connect([
464+
(intramodal_template_wf, ds_intramodal_template, [
465+
# The ACPC-resampled template, NOT outputnode.intramodal_template:
466+
# that one is in the template's own midpoint space, and tagging
467+
# it space-ACPC would mislabel it.
468+
('outputnode.intramodal_template_acpc', 'in_file'),
469+
]),
470+
]) # fmt:skip
471+
454472
# Without this the intramodal space is a dead end: nothing can be mapped
455473
# into or out of it after the fact.
456474
ds_intramodal_to_acpc = pe.Node(
@@ -466,6 +484,17 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
466484
name='ds_intramodal_to_acpc',
467485
run_without_submitting=True,
468486
)
487+
workflow.connect([
488+
(intramodal_template_wf, ds_intramodal_to_acpc, [
489+
('outputnode.intramodal_template_to_t1_affine', 'in_file'),
490+
]),
491+
]) # fmt:skip
492+
493+
# TemplateQC and the per-group orig->intramodal transform export exist only
494+
# for linear templates: mvtc2 exposes no per-input aligned images, and its
495+
# per-group transform is an [affine, warp] pair that does not fit a
496+
# single-file .mat sink.
497+
intramodal_linear = config.workflow.intramodal_template_transform in ('Rigid', 'Affine')
469498
if intramodal_linear:
470499
ds_template_qc = pe.Node(
471500
DerivativesDataSink(
@@ -479,6 +508,12 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
479508
name='ds_template_qc',
480509
run_without_submitting=True,
481510
)
511+
workflow.connect([
512+
(intramodal_template_wf, ds_template_qc, [
513+
('outputnode.template_qc_file', 'in_file'),
514+
]),
515+
]) # fmt:skip
516+
482517
ds_template_agreement = pe.Node(
483518
DerivativesDataSink(
484519
source_file=anat_source_file,
@@ -494,44 +529,11 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
494529
run_without_submitting=True,
495530
)
496531
workflow.connect([
497-
(intramodal_template_wf, ds_template_qc, [
498-
('outputnode.template_qc_file', 'in_file'),
499-
]),
500532
(intramodal_template_wf, ds_template_agreement, [
501533
('outputnode.template_agreement_map', 'in_file'),
502534
]),
503535
]) # fmt:skip
504536

505-
workflow.connect([
506-
(intramodal_template_wf, ds_intramodal_to_acpc, [
507-
('outputnode.intramodal_template_to_t1_affine', 'in_file'),
508-
]),
509-
]) # fmt:skip
510-
511-
workflow.connect([
512-
(intramodal_template_wf, ds_intramodal_template, [
513-
# The ACPC-resampled template, NOT outputnode.intramodal_template:
514-
# that one is in the template's own midpoint space, and tagging
515-
# it space-ACPC would mislabel it.
516-
('outputnode.intramodal_template_acpc', 'in_file'),
517-
]),
518-
]) # fmt:skip
519-
520-
if make_intramodal_template:
521-
workflow.connect([
522-
(anat_preproc_wf, intramodal_template_wf, [
523-
('outputnode.t1_preproc', 'inputnode.t1_preproc'),
524-
('outputnode.t1_brain', 'inputnode.t1_brain'),
525-
('outputnode.t1_mask', 'inputnode.t1_mask'),
526-
('outputnode.t1_seg', 'inputnode.t1_seg'),
527-
('outputnode.t1_aseg', 'inputnode.t1_aseg'),
528-
('outputnode.t1_aparc', 'inputnode.t1_aparc'),
529-
('outputnode.t1_2_mni_forward_transform', 'inputnode.t1_2_mni_forward_transform'),
530-
('outputnode.t1_2_mni_reverse_transform', 'inputnode.t1_2_mni_reverse_transform'),
531-
('outputnode.dwi_sampling_grid', 'inputnode.dwi_sampling_grid'),
532-
]),
533-
]) # fmt:skip
534-
535537
# create a processing pipeline for the dwis in each session
536538
for output_fname, dwi_info in outputs_to_files.items():
537539
source_file = get_source_file(dwi_info['dwi_series'], output_fname, suffix='_dwi')
@@ -600,28 +602,6 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
600602
if make_intramodal_template:
601603
input_name = f'inputnode.{output_wfname}_b0_template'
602604
output_name = f'outputnode.{output_wfname}_transform'
603-
if intramodal_linear:
604-
# Per-group hop into the template space. Paired with
605-
# from-intramodal_to-ACPC above, this closes the round trip:
606-
# BIDS b=0 -> intramodal -> ACPC -> MNI, and back.
607-
ds_orig_to_intramodal = pe.Node(
608-
DerivativesDataSink(
609-
source_file=source_file,
610-
base_directory=config.execution.output_dir,
611-
datatype='anat',
612-
mode='image',
613-
extension='.mat',
614-
**{'from': 'orig', 'to': 'intramodal'},
615-
suffix='xfm',
616-
),
617-
name=f'ds_orig_to_intramodal_{output_wfname}',
618-
run_without_submitting=True,
619-
)
620-
workflow.connect([
621-
(intramodal_template_wf, ds_orig_to_intramodal, [
622-
(output_name, 'in_file'),
623-
]),
624-
]) # fmt:skip
625605

626606
workflow.connect([
627607
(dwi_preproc_wf, intramodal_template_wf, [
@@ -645,6 +625,27 @@ def init_single_subject_wf(subject_id: str, session_ids: list):
645625
]),
646626
]) # fmt:skip
647627

628+
if intramodal_linear:
629+
# Per-group hop into the template space. Paired with
630+
# from-intramodal_to-ACPC above, this closes the round trip:
631+
# BIDS b=0 -> intramodal -> ACPC -> MNI, and back.
632+
ds_orig_to_intramodal = pe.Node(
633+
DerivativesDataSink(
634+
source_file=source_file,
635+
base_directory=config.execution.output_dir,
636+
datatype='anat',
637+
mode='image',
638+
extension='.mat',
639+
**{'from': 'orig', 'to': 'intramodal'},
640+
suffix='xfm',
641+
),
642+
name=f'ds_orig_to_intramodal_{output_wfname}',
643+
run_without_submitting=True,
644+
)
645+
workflow.connect([
646+
(intramodal_template_wf, ds_orig_to_intramodal, [(output_name, 'in_file')]),
647+
]) # fmt:skip
648+
648649
if merging_distortion_groups:
649650
image_name = f'inputnode.{output_wfname}_image'
650651
bval_name = f'inputnode.{output_wfname}_bval'

0 commit comments

Comments
 (0)