|
38 | 38 | from nibabies.interfaces import DerivativesDataSink
|
39 | 39 | from nibabies.workflows.anatomical.brain_extraction import init_infant_brain_extraction_wf
|
40 | 40 | from nibabies.workflows.anatomical.outputs import init_anat_reports_wf, init_coreg_report_wf
|
41 |
| -from nibabies.workflows.anatomical.preproc import init_anat_preproc_wf, init_csf_norm_wf |
| 41 | +from nibabies.workflows.anatomical.preproc import ( |
| 42 | + init_anat_preproc_wf, |
| 43 | + init_conform_derivative_wf, |
| 44 | + init_csf_norm_wf, |
| 45 | +) |
42 | 46 | from nibabies.workflows.anatomical.registration import (
|
43 | 47 | init_concat_registrations_wf,
|
44 | 48 | init_coregistration_wf,
|
@@ -172,11 +176,11 @@ def init_infant_anat_fit_wf(
|
172 | 176 |
|
173 | 177 | # Stage 2 - Anatomicals
|
174 | 178 | t1w_buffer = pe.Node(
|
175 |
| - niu.IdentityInterface(fields=['t1w_preproc', 't1w_maskt1w_brain']), |
| 179 | + niu.IdentityInterface(fields=['t1w_preproc', 't1w_mask', 't1w_brain']), |
176 | 180 | name='t1w_buffer',
|
177 | 181 | )
|
178 | 182 | t2w_buffer = pe.Node(
|
179 |
| - niu.IdentityInterface(fields=['t2w_preproc', 't2w_maskt2w_brain', 't2w_probmap']), |
| 183 | + niu.IdentityInterface(fields=['t2w_preproc', 't2w_mask', 't2w_brain', 't2w_probmap']), |
180 | 184 | name='t2w_buffer',
|
181 | 185 | )
|
182 | 186 | anat_buffer = pe.Node(
|
@@ -323,6 +327,7 @@ def init_infant_anat_fit_wf(
|
323 | 327 |
|
324 | 328 | t1w_preproc = precomputed.get('t1w_preproc')
|
325 | 329 | t2w_preproc = precomputed.get('t2w_preproc')
|
| 330 | + anat_preproc = precomputed.get(f'{anat}_preproc') |
326 | 331 |
|
327 | 332 | # Stage 1: Conform & valid T1w/T2w images
|
328 | 333 | # Note: Since stage 1 & 2 are tightly knit together, it may be more intuitive
|
@@ -575,21 +580,29 @@ def init_infant_anat_fit_wf(
|
575 | 580 | 'A pre-computed T1w brain mask was provided as input and used throughout the '
|
576 | 581 | 'workflow.'
|
577 | 582 | )
|
578 |
| - t1w_buffer.inputs.t1w_mask = t1w_mask |
579 |
| - apply_t1w_mask.inputs.in_mask = t1w_mask |
580 | 583 | workflow.connect(apply_t1w_mask, 'out_file', t1w_buffer, 't1w_brain')
|
581 | 584 |
|
582 | 585 | if not t1w_preproc:
|
| 586 | + # Ensure compatibility with T1w template |
| 587 | + conform_t1w_mask_wf = init_conform_derivative_wf( |
| 588 | + in_file=t1w_mask, name='conform_t1w_mask_wf' |
| 589 | + ) |
| 590 | + |
583 | 591 | LOGGER.info('ANAT Skipping skull-strip, INU-correction only')
|
584 | 592 | t1w_n4_wf = init_anat_preproc_wf(name='t1w_n4_wf')
|
585 | 593 | workflow.connect([
|
| 594 | + (t1w_validate, conform_t1w_mask_wf, [('out_file', 'inputnode.ref_file')]), |
| 595 | + (conform_t1w_mask_wf, t1w_buffer, [('outputnode.out_file', 't1w_mask')]), |
| 596 | + (conform_t1w_mask_wf, apply_t1w_mask, [('outputnode.out_file', 'in_mask')]), |
586 | 597 | (t1w_validate, t1w_n4_wf, [('out_file', 'inputnode.in_anat')]),
|
587 | 598 | (t1w_n4_wf, t1w_buffer, [('outputnode.anat_preproc', 't1w_preproc')]),
|
588 | 599 | (t1w_n4_wf, apply_t1w_mask, [('outputnode.anat_preproc', 'in_file')]),
|
589 | 600 | ]) # fmt:skip
|
590 | 601 | else:
|
591 | 602 | LOGGER.info('ANAT Skipping T1w masking')
|
592 | 603 | workflow.connect(t1w_validate, 'out_file', apply_t1w_mask, 'in_file')
|
| 604 | + t1w_buffer.inputs.t1w_mask = t1w_mask |
| 605 | + apply_t1w_mask.inputs.in_mask = t1w_mask |
593 | 606 |
|
594 | 607 | # T2w masking logic:
|
595 | 608 | #
|
@@ -701,21 +714,30 @@ def init_infant_anat_fit_wf(
|
701 | 714 | 'A pre-computed T2w brain mask was provided as input and used throughout the '
|
702 | 715 | 'workflow.'
|
703 | 716 | )
|
704 |
| - t2w_buffer.inputs.t2w_mask = t2w_mask |
705 |
| - apply_t2w_mask.inputs.in_mask = t2w_mask |
706 | 717 | workflow.connect(apply_t2w_mask, 'out_file', t2w_buffer, 't2w_brain')
|
707 | 718 |
|
708 | 719 | if not t2w_preproc:
|
| 720 | + # Ensure compatibility with T2w template |
| 721 | + conform_t2w_mask_wf = init_conform_derivative_wf( |
| 722 | + in_file=t2w_mask, |
| 723 | + name='conform_t2w_mask_wf', |
| 724 | + ) |
| 725 | + |
709 | 726 | LOGGER.info('ANAT Skipping skull-strip, INU-correction only')
|
710 | 727 | t2w_n4_wf = init_anat_preproc_wf(name='t2w_n4_wf')
|
711 | 728 | workflow.connect([
|
| 729 | + (t2w_validate, conform_t2w_mask_wf, [('out_file', 'inputnode.ref_file')]), |
| 730 | + (conform_t2w_mask_wf, t2w_buffer, [('outputnode.out_file', 't2w_mask')]), |
| 731 | + (conform_t2w_mask_wf, apply_t2w_mask, [('outputnode.out_file', 'in_mask')]), |
712 | 732 | (t2w_validate, t2w_n4_wf, [('out_file', 'inputnode.in_anat')]),
|
713 | 733 | (t2w_n4_wf, t2w_buffer, [('outputnode.anat_preproc', 't2w_preproc')]),
|
714 | 734 | (t2w_n4_wf, apply_t2w_mask, [('outputnode.anat_preproc', 'in_file')]),
|
715 | 735 | ]) # fmt:skip
|
716 | 736 | else:
|
717 | 737 | LOGGER.info('ANAT Skipping T2w masking')
|
718 | 738 | workflow.connect(t2w_validate, 'out_file', apply_t2w_mask, 'in_file')
|
| 739 | + t2w_buffer.inputs.t2w_mask = t2w_mask |
| 740 | + apply_t2w_mask.inputs.in_mask = t2w_mask |
719 | 741 |
|
720 | 742 | # Stage 3: Coregistration
|
721 | 743 | t1w2t2w_xfm = precomputed.get('t1w2t2w_xfm')
|
@@ -819,7 +841,19 @@ def init_infant_anat_fit_wf(
|
819 | 841 |
|
820 | 842 | if anat_aseg:
|
821 | 843 | LOGGER.info('ANAT Found precomputed anatomical segmentation')
|
822 |
| - aseg_buffer.inputs.anat_aseg = anat_aseg |
| 844 | + # Ensure compatibility with anatomical template |
| 845 | + if not anat_preproc: |
| 846 | + conform_aseg_wf = init_conform_derivative_wf( |
| 847 | + in_file=anat_aseg, |
| 848 | + name='conform_aseg_wf', |
| 849 | + ) |
| 850 | + |
| 851 | + workflow.connect([ |
| 852 | + (anat_buffer, conform_aseg_wf, [('anat_preproc', 'inputnode.ref_file')]), |
| 853 | + (conform_aseg_wf, aseg_buffer, [('outputnode.out_file', 'anat_aseg')]), |
| 854 | + ]) # fmt:skip |
| 855 | + else: |
| 856 | + aseg_buffer.inputs.anat_aseg = anat_aseg |
823 | 857 |
|
824 | 858 | if not (anat_dseg and anat_tpms):
|
825 | 859 | LOGGER.info('ANAT Stage 4: Tissue segmentation')
|
@@ -1714,27 +1748,47 @@ def init_infant_single_anat_fit_wf(
|
1714 | 1748 | else:
|
1715 | 1749 | LOGGER.info(f'ANAT Found {reference_anat} brain mask')
|
1716 | 1750 | desc += 'A pre-computed brain mask was provided as input and used throughout the workflow.'
|
1717 |
| - anat_buffer.inputs.anat_mask = anat_mask |
1718 |
| - apply_mask.inputs.in_mask = anat_mask |
1719 | 1751 | workflow.connect(apply_mask, 'out_file', anat_buffer, 'anat_brain')
|
1720 | 1752 |
|
1721 | 1753 | if not anat_preproc:
|
| 1754 | + conform_anat_mask_wf = init_conform_derivative_wf( |
| 1755 | + in_file=anat_mask, |
| 1756 | + name='conform_anat_mask_wf', |
| 1757 | + ) |
| 1758 | + |
1722 | 1759 | LOGGER.info('ANAT Skipping skull-strip, INU-correction only')
|
1723 | 1760 | anat_n4_wf = init_anat_preproc_wf(name='anat_n4_wf')
|
1724 | 1761 | workflow.connect([
|
| 1762 | + (anat_validate, conform_anat_mask_wf, [('out_file', 'inputnode.ref_file')]), |
| 1763 | + (conform_anat_mask_wf, anat_buffer, [('outputnode.out_file', 'anat_mask')]), |
| 1764 | + (conform_anat_mask_wf, apply_mask, [('outputnode.out_file', 'in_mask')]), |
1725 | 1765 | (anat_validate, anat_n4_wf, [('out_file', 'inputnode.in_anat')]),
|
1726 | 1766 | (anat_n4_wf, anat_buffer, [('outputnode.anat_preproc', 'anat_preproc')]),
|
1727 | 1767 | (anat_n4_wf, apply_mask, [('outputnode.anat_preproc', 'in_file')]),
|
1728 | 1768 | ]) # fmt:skip
|
1729 | 1769 | else:
|
1730 | 1770 | LOGGER.info(f'ANAT Skipping {reference_anat} masking')
|
1731 | 1771 | workflow.connect(anat_validate, 'out_file', apply_mask, 'in_file')
|
| 1772 | + anat_buffer.inputs.anat_mask = anat_mask |
| 1773 | + apply_mask.inputs.in_mask = anat_mask |
1732 | 1774 |
|
1733 | 1775 | # Stage 3: Segmentation
|
1734 | 1776 | seg_method = 'jlf' if config.execution.segmentation_atlases_dir else 'fast'
|
1735 | 1777 | if anat_aseg:
|
1736 | 1778 | LOGGER.info('ANAT Found precomputed anatomical segmentation')
|
1737 |
| - aseg_buffer.inputs.anat_aseg = anat_aseg |
| 1779 | + # Ensure compatibility with anatomical template |
| 1780 | + if not anat_preproc: |
| 1781 | + conform_aseg_wf = init_conform_derivative_wf( |
| 1782 | + in_file=anat_aseg, |
| 1783 | + name='conform_aseg_wf', |
| 1784 | + ) |
| 1785 | + |
| 1786 | + workflow.connect([ |
| 1787 | + (anat_buffer, conform_aseg_wf, [('anat_preproc', 'inputnode.ref_file')]), |
| 1788 | + (conform_aseg_wf, aseg_buffer, [('outputnode.out_file', 'anat_aseg')]), |
| 1789 | + ]) # fmt:skip |
| 1790 | + else: |
| 1791 | + aseg_buffer.inputs.anat_aseg = anat_aseg |
1738 | 1792 |
|
1739 | 1793 | if not (anat_dseg and anat_tpms):
|
1740 | 1794 | LOGGER.info('ANAT Stage 3: Tissue segmentation')
|
|
0 commit comments