From 10bbef80176431f4eedc7f08b07ff64f45fe863e Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 20 Sep 2024 17:29:32 -0400 Subject: [PATCH 1/2] DBG: Ensure anatomical preproc is not skullstripped --- nibabies/workflows/anatomical/fit.py | 36 +++++++++++++--------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/nibabies/workflows/anatomical/fit.py b/nibabies/workflows/anatomical/fit.py index cfc62717..2b83e501 100644 --- a/nibabies/workflows/anatomical/fit.py +++ b/nibabies/workflows/anatomical/fit.py @@ -554,7 +554,7 @@ def init_infant_anat_fit_wf( workflow.connect([ (t1w_buffer, ds_t1w_mask_wf, [('t1w_mask', 'inputnode.mask_file')]), ]) # fmt:skip - else: + else: # T1w mask derivative has been found LOGGER.info('ANAT Found T1w brain mask') if reference_anat == 'T1w': desc += ( @@ -563,7 +563,7 @@ def init_infant_anat_fit_wf( ) t1w_buffer.inputs.t1w_mask = t1w_mask apply_t1w_mask.inputs.in_mask = t1w_mask - workflow.connect(t1w_validate, 'out_file', apply_t1w_mask, 'in_file') + workflow.connect(apply_t1w_mask, 'out_file', t1w_buffer, 't1w_brain') if not t1w_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') @@ -574,15 +574,16 @@ def init_infant_anat_fit_wf( name='t1w_n4_only_wf', ) workflow.connect([ - (apply_t1w_mask, t1w_n4_only_wf, [('out_file', 'inputnode.in_files')]), + (t1w_validate, t1w_n4_only_wf, [('out_file', 'inputnode.in_files')]), (t1w_n4_only_wf, t1w_buffer, [ (('outputnode.bias_corrected', pop_file), 't1w_preproc'), - (('outputnode.out_file', pop_file), 't1w_brain'), ]), + (t1w_n4_only_wf, apply_t1w_mask, [ + (('outputnode.out_file', pop_file), 'in_file')]), ]) # fmt:skip else: LOGGER.info('ANAT Skipping T1w masking') - workflow.connect(apply_t1w_mask, 'out_file', t1w_buffer, 't1w_brain') + workflow.connect(t1w_validate, 'out_file', apply_t1w_mask, 'in_file') # T2w masking logic: # @@ -709,14 +710,12 @@ def init_infant_anat_fit_wf( LOGGER.info('ANAT Found T2w brain mask') if reference_anat == 'T2w': desc += ( - 'A pre-computed T1w brain mask was provided as input and used throughout the ' + 'A pre-computed T2w brain mask was provided as input and used throughout the ' 'workflow.' ) t2w_buffer.inputs.t2w_mask = t2w_mask apply_t2w_mask.inputs.in_mask = t2w_mask - workflow.connect([ - (t2w_validate, apply_t2w_mask, [('out_file', 'in_file')]), - ]) # fmt:skip + workflow.connect(apply_t2w_mask, 'out_file', t2w_buffer, 't2w_brain') if not t2w_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') @@ -727,15 +726,16 @@ def init_infant_anat_fit_wf( name='t2w_n4_only_wf', ) workflow.connect([ - (apply_t2w_mask, t2w_n4_only_wf, [('out_file', 'inputnode.in_files')]), + (t2w_validate, t2w_n4_only_wf, [('out_file', 'inputnode.in_files')]), (t2w_n4_only_wf, t2w_buffer, [ (('outputnode.bias_corrected', pop_file), 't2w_preproc'), - (('outputnode.out_file', pop_file), 't2w_brain'), ]), + (t2w_n4_only_wf, apply_t2w_mask, [ + (('outputnode.out_file', pop_file), 'in_file')]), ]) # fmt:skip else: LOGGER.info('ANAT Skipping T2w masking') - workflow.connect(apply_t2w_mask, 'out_file', t2w_buffer, 't2w_brain') + workflow.connect(t2w_validate, 'out_file', apply_t2w_mask, 'in_file') # Stage 3: Coregistration t1w2t2w_xfm = precomputed.get('t1w2t2w_xfm') @@ -1643,9 +1643,7 @@ def init_infant_single_anat_fit_wf( desc += 'A pre-computed brain mask was provided as input and used throughout the workflow.' anat_buffer.inputs.anat_mask = anat_mask apply_mask.inputs.in_mask = anat_mask - workflow.connect([ - (anat_validate, apply_mask, [('out_file', 'in_file')]), - ]) # fmt:skip + workflow.connect(apply_mask, 'out_file', anat_buffer, 'anat_brain') if not anat_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') @@ -1656,15 +1654,15 @@ def init_infant_single_anat_fit_wf( name='n4_only_wf', ) workflow.connect([ - (apply_mask, n4_only_wf, [('out_file', 'inputnode.in_files')]), + (anat_validate, n4_only_wf, [('out_file', 'inputnode.in_files')]), (n4_only_wf, anat_buffer, [ (('outputnode.bias_corrected', pop_file), 'anat_preproc'), - (('outputnode.out_file', pop_file), 'anat_brain'), ]), + (n4_only_wf, apply_mask, [(('outputnode.out_file', pop_file), 'in_file')]), ]) # fmt:skip else: - LOGGER.info('ANAT Skipping T2w masking') - workflow.connect(apply_mask, 'out_file', anat_buffer, 'anat_brain') + LOGGER.info(f'ANAT Skipping {reference_anat} masking') + workflow.connect(anat_validate, 'out_file', apply_mask, 'in_file') # Stage 3: Segmentation seg_method = 'jlf' if config.execution.segmentation_atlases_dir else 'fast' From 10549c3c08d1deb33c0e7180ccb6bb8ca034cf32 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Sat, 21 Sep 2024 16:37:42 -0400 Subject: [PATCH 2/2] RF: Ensure clipping of anatomical template, simplify workflow --- nibabies/workflows/anatomical/fit.py | 47 ++++++------------------ nibabies/workflows/anatomical/preproc.py | 10 +---- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/nibabies/workflows/anatomical/fit.py b/nibabies/workflows/anatomical/fit.py index 2b83e501..a887b942 100644 --- a/nibabies/workflows/anatomical/fit.py +++ b/nibabies/workflows/anatomical/fit.py @@ -567,19 +567,11 @@ def init_infant_anat_fit_wf( if not t1w_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') - t1w_n4_only_wf = init_n4_only_wf( - omp_nthreads=omp_nthreads, - atropos_use_random_seed=not skull_strip_fixed_seed, - bids_suffix='T1w', - name='t1w_n4_only_wf', - ) + t1w_n4_wf = init_anat_preproc_wf(name='t1w_n4_wf') workflow.connect([ - (t1w_validate, t1w_n4_only_wf, [('out_file', 'inputnode.in_files')]), - (t1w_n4_only_wf, t1w_buffer, [ - (('outputnode.bias_corrected', pop_file), 't1w_preproc'), - ]), - (t1w_n4_only_wf, apply_t1w_mask, [ - (('outputnode.out_file', pop_file), 'in_file')]), + (t1w_validate, t1w_n4_wf, [('out_file', 'inputnode.in_anat')]), + (t1w_n4_wf, t1w_buffer, [('outputnode.anat_preproc', 't1w_preproc')]), + (t1w_n4_wf, apply_t1w_mask, [('outputnode.anat_preproc', 'in_file')]), ]) # fmt:skip else: LOGGER.info('ANAT Skipping T1w masking') @@ -719,19 +711,11 @@ def init_infant_anat_fit_wf( if not t2w_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') - t2w_n4_only_wf = init_n4_only_wf( - omp_nthreads=omp_nthreads, - atropos_use_random_seed=not skull_strip_fixed_seed, - bids_suffix='T2w', - name='t2w_n4_only_wf', - ) + t2w_n4_wf = init_anat_preproc_wf(name='t2w_n4_wf') workflow.connect([ - (t2w_validate, t2w_n4_only_wf, [('out_file', 'inputnode.in_files')]), - (t2w_n4_only_wf, t2w_buffer, [ - (('outputnode.bias_corrected', pop_file), 't2w_preproc'), - ]), - (t2w_n4_only_wf, apply_t2w_mask, [ - (('outputnode.out_file', pop_file), 'in_file')]), + (t2w_validate, t2w_n4_wf, [('out_file', 'inputnode.in_anat')]), + (t2w_n4_wf, t2w_buffer, [('outputnode.anat_preproc', 't2w_preproc')]), + (t2w_n4_wf, apply_t2w_mask, [('outputnode.anat_preproc', 'in_file')]), ]) # fmt:skip else: LOGGER.info('ANAT Skipping T2w masking') @@ -1647,18 +1631,11 @@ def init_infant_single_anat_fit_wf( if not anat_preproc: LOGGER.info('ANAT Skipping skull-strip, INU-correction only') - n4_only_wf = init_n4_only_wf( - omp_nthreads=omp_nthreads, - atropos_use_random_seed=not skull_strip_fixed_seed, - bids_suffix=reference_anat, - name='n4_only_wf', - ) + anat_n4_wf = init_anat_preproc_wf(name='anat_n4_wf') workflow.connect([ - (anat_validate, n4_only_wf, [('out_file', 'inputnode.in_files')]), - (n4_only_wf, anat_buffer, [ - (('outputnode.bias_corrected', pop_file), 'anat_preproc'), - ]), - (n4_only_wf, apply_mask, [(('outputnode.out_file', pop_file), 'in_file')]), + (anat_validate, anat_n4_wf, [('out_file', 'inputnode.in_anat')]), + (anat_n4_wf, anat_buffer, [('outputnode.anat_preproc', 'anat_preproc')]), + (anat_n4_wf, apply_mask, [('outputnode.anat_preproc', 'in_file')]), ]) # fmt:skip else: LOGGER.info(f'ANAT Skipping {reference_anat} masking') diff --git a/nibabies/workflows/anatomical/preproc.py b/nibabies/workflows/anatomical/preproc.py index 4e0f9daf..7cbc08aa 100644 --- a/nibabies/workflows/anatomical/preproc.py +++ b/nibabies/workflows/anatomical/preproc.py @@ -12,11 +12,9 @@ def init_anat_preproc_wf( This workflow accepts T1w/T2w images as inputs (either raw or a merged template) and performs: - Intensity clipping - - Denoising - N4 Bias Field Correction - The outputs of this workflow will be used to either create the brainmask, - or reconstruct the cortical surfaces. + The outputs of this workflow will be a structural reference used for subsequent processing. Inputs ------ @@ -45,7 +43,6 @@ def init_anat_preproc_wf( # validate image validate = pe.Node(ValidateImage(), name='anat_validate', run_without_submitting=True) clip = pe.Node(IntensityClip(p_min=10.0, p_max=99.5), name='clip') - # denoise = pe.Node(DenoiseImage(dimension=3, noise_model="Rician"), name="denoise") n4_correct = pe.Node( N4BiasFieldCorrection( dimension=3, @@ -61,14 +58,11 @@ def init_anat_preproc_wf( ) final_clip = pe.Node(IntensityClip(p_min=5.0, p_max=99.5), name='final_clip') - # fmt:off wf.connect([ (inputnode, validate, [('in_anat', 'in_file')]), (validate, clip, [('out_file', 'in_file')]), (clip, n4_correct, [('out_file', 'input_image')]), - # (denoise, n4_correct, [("output_image", "input_image")]), (n4_correct, final_clip, [('output_image', 'in_file')]), (final_clip, outputnode, [('out_file', 'anat_preproc')]), - ]) - # fmt:on + ]) # fmt:skip return wf