|
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,28 @@ 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 | 583 | apply_t1w_mask.inputs.in_mask = t1w_mask |
580 | 584 | workflow.connect(apply_t1w_mask, 'out_file', t1w_buffer, 't1w_brain') |
581 | 585 |
|
582 | 586 | if not t1w_preproc: |
| 587 | + # Ensure compatibility with T1w template |
| 588 | + conform_t1w_mask_wf = init_conform_derivative_wf( |
| 589 | + in_file=t1w_mask, name='conform_t1w_mask_wf' |
| 590 | + ) |
| 591 | + |
583 | 592 | LOGGER.info('ANAT Skipping skull-strip, INU-correction only') |
584 | 593 | t1w_n4_wf = init_anat_preproc_wf(name='t1w_n4_wf') |
585 | 594 | workflow.connect([ |
| 595 | + (t1w_validate, conform_t1w_mask_wf, [('out_file', 'inputnode.ref_file')]), |
| 596 | + (conform_t1w_mask_wf, t1w_buffer, [('outputnode.out_file', 't1w_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 |
593 | 605 |
|
594 | 606 | # T2w masking logic: |
595 | 607 | # |
@@ -701,21 +713,29 @@ def init_infant_anat_fit_wf( |
701 | 713 | 'A pre-computed T2w brain mask was provided as input and used throughout the ' |
702 | 714 | 'workflow.' |
703 | 715 | ) |
704 | | - t2w_buffer.inputs.t2w_mask = t2w_mask |
705 | 716 | 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')]), |
712 | 731 | (t2w_validate, t2w_n4_wf, [('out_file', 'inputnode.in_anat')]), |
713 | 732 | (t2w_n4_wf, t2w_buffer, [('outputnode.anat_preproc', 't2w_preproc')]), |
714 | 733 | (t2w_n4_wf, apply_t2w_mask, [('outputnode.anat_preproc', 'in_file')]), |
715 | 734 | ]) # fmt:skip |
716 | 735 | else: |
717 | 736 | LOGGER.info('ANAT Skipping T2w masking') |
718 | 737 | workflow.connect(t2w_validate, 'out_file', apply_t2w_mask, 'in_file') |
| 738 | + t2w_buffer.inputs.t2w_mask = t2w_mask |
719 | 739 |
|
720 | 740 | # Stage 3: Coregistration |
721 | 741 | t1w2t2w_xfm = precomputed.get('t1w2t2w_xfm') |
@@ -819,7 +839,19 @@ def init_infant_anat_fit_wf( |
819 | 839 |
|
820 | 840 | if anat_aseg: |
821 | 841 | LOGGER.info('ANAT Found precomputed anatomical segmentation') |
822 | | - aseg_buffer.inputs.anat_aseg = anat_aseg |
| 842 | + # Ensure compatibility with anatomical template |
| 843 | + if not anat_preproc: |
| 844 | + conform_aseg_wf = init_conform_derivative_wf( |
| 845 | + in_file=anat_aseg, |
| 846 | + name='conform_aseg_wf', |
| 847 | + ) |
| 848 | + |
| 849 | + workflow.connect([ |
| 850 | + (anat_buffer, conform_aseg_wf, [('anat_preproc', 'inputnode.ref_file')]), |
| 851 | + (conform_aseg_wf, aseg_buffer, [('outputnode.out_file', 'anat_aseg')]), |
| 852 | + ]) # fmt:skip |
| 853 | + else: |
| 854 | + aseg_buffer.inputs.anat_aseg = anat_aseg |
823 | 855 |
|
824 | 856 | if not (anat_dseg and anat_tpms): |
825 | 857 | LOGGER.info('ANAT Stage 4: Tissue segmentation') |
@@ -1714,27 +1746,46 @@ def init_infant_single_anat_fit_wf( |
1714 | 1746 | else: |
1715 | 1747 | LOGGER.info(f'ANAT Found {reference_anat} brain mask') |
1716 | 1748 | desc += 'A pre-computed brain mask was provided as input and used throughout the workflow.' |
1717 | | - anat_buffer.inputs.anat_mask = anat_mask |
1718 | 1749 | apply_mask.inputs.in_mask = anat_mask |
1719 | 1750 | workflow.connect(apply_mask, 'out_file', anat_buffer, 'anat_brain') |
1720 | 1751 |
|
1721 | 1752 | if not anat_preproc: |
| 1753 | + conform_anat_mask_wf = init_conform_derivative_wf( |
| 1754 | + in_file=anat_mask, |
| 1755 | + name='conform_anat_mask_wf', |
| 1756 | + ) |
| 1757 | + |
1722 | 1758 | LOGGER.info('ANAT Skipping skull-strip, INU-correction only') |
1723 | 1759 | anat_n4_wf = init_anat_preproc_wf(name='anat_n4_wf') |
1724 | 1760 | workflow.connect([ |
| 1761 | + (anat_validate, conform_anat_mask_wf, [('out_file', 'inputnode.ref_file')]), |
| 1762 | + (conform_anat_mask_wf, anat_buffer, [('outputnode.out_file', 'anat_mask')]), |
1725 | 1763 | (anat_validate, anat_n4_wf, [('out_file', 'inputnode.in_anat')]), |
1726 | 1764 | (anat_n4_wf, anat_buffer, [('outputnode.anat_preproc', 'anat_preproc')]), |
1727 | 1765 | (anat_n4_wf, apply_mask, [('outputnode.anat_preproc', 'in_file')]), |
1728 | 1766 | ]) # fmt:skip |
1729 | 1767 | else: |
1730 | 1768 | LOGGER.info(f'ANAT Skipping {reference_anat} masking') |
1731 | 1769 | workflow.connect(anat_validate, 'out_file', apply_mask, 'in_file') |
| 1770 | + anat_buffer.inputs.anat_mask = anat_mask |
1732 | 1771 |
|
1733 | 1772 | # Stage 3: Segmentation |
1734 | 1773 | seg_method = 'jlf' if config.execution.segmentation_atlases_dir else 'fast' |
1735 | 1774 | if anat_aseg: |
1736 | 1775 | LOGGER.info('ANAT Found precomputed anatomical segmentation') |
1737 | | - aseg_buffer.inputs.anat_aseg = anat_aseg |
| 1776 | + # Ensure compatibility with anatomical template |
| 1777 | + if not anat_preproc: |
| 1778 | + conform_aseg_wf = init_conform_derivative_wf( |
| 1779 | + in_file=anat_aseg, |
| 1780 | + name='conform_aseg_wf', |
| 1781 | + ) |
| 1782 | + |
| 1783 | + workflow.connect([ |
| 1784 | + (anat_buffer, conform_aseg_wf, [('anat_preproc', 'inputnode.ref_file')]), |
| 1785 | + (conform_aseg_wf, aseg_buffer, [('outputnode.out_file', 'anat_aseg')]), |
| 1786 | + ]) # fmt:skip |
| 1787 | + else: |
| 1788 | + aseg_buffer.inputs.anat_aseg = anat_aseg |
1738 | 1789 |
|
1739 | 1790 | if not (anat_dseg and anat_tpms): |
1740 | 1791 | LOGGER.info('ANAT Stage 3: Tissue segmentation') |
|
0 commit comments