def t1w_preprocessing(name='t1w_preprocessing', settings=None): """T1w images preprocessing pipeline""" if settings is None: raise RuntimeError('Workflow settings are missing') workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['t1w']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['t1_seg', 't1_tpms', 'bias_corrected_t1', 't1_brain', 't1_mask', 't1_2_mni', 't1_2_mni_forward_transform', 't1_2_mni_reverse_transform']), name='outputnode') # 0. Align and merge if several T1w images are provided t1wmrg = pe.Node(IntraModalMerge(), name='MergeT1s') # 1. Reorient T1 arw = pe.Node(niu.Function(input_names=['in_file'], output_names=['out_file'], function=reorient), name='Reorient') # 2. T1 Bias Field Correction inu_n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='CorrectINU') # 3. Skull-stripping asw = skullstrip_wf() if settings.get('skull_strip_ants', False): asw = skullstrip_ants(settings=settings) # 4. Segmentation t1_seg = pe.Node(FASTRPT(generate_report=True, segments=True, no_bias=True, probability_maps=True), name='Segmentation') # 5. Spatial normalization (T1w to MNI registration) t1_2_mni = pe.Node( RobustMNINormalizationRPT( generate_report=True, num_threads=settings['ants_nthreads'], testing=settings.get('debug', False), template='mni_icbm152_nlin_asym_09c' ), name='T1_2_MNI_Registration' ) # should not be necesssary byt does not hurt - make sure the multiproc # scheduler knows the resource limits t1_2_mni.interface.num_threads = settings['ants_nthreads'] # Resample the brain mask and the tissue probability maps into mni space bmask_mni = pe.Node( ants.ApplyTransforms(dimension=3, default_value=0, interpolation='NearestNeighbor'), name='brain_mni_warp' ) bmask_mni.inputs.reference_image = op.join(get_mni_icbm152_nlin_asym_09c(), '1mm_T1.nii.gz') tpms_mni = pe.MapNode( ants.ApplyTransforms(dimension=3, default_value=0, interpolation='Linear'), iterfield=['input_image'], name='tpms_mni_warp' ) tpms_mni.inputs.reference_image = op.join(get_mni_icbm152_nlin_asym_09c(), '1mm_T1.nii.gz') ds_t1_seg_report = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='t1_seg', out_path_base='reports'), name='DS_T1_Seg_Report' ) ds_t1_2_mni_report = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='t1_2_mni', out_path_base='reports'), name='DS_T1_2_MNI_Report' ) workflow.connect([ (inputnode, t1wmrg, [('t1w', 'in_files')]), (t1wmrg, arw, [('out_avg', 'in_file')]), (arw, inu_n4, [('out_file', 'input_image')]), (inu_n4, asw, [('output_image', 'inputnode.in_file')]), (asw, t1_seg, [('outputnode.out_file', 'in_files')]), (inu_n4, t1_2_mni, [('output_image', 'moving_image')]), (asw, t1_2_mni, [('outputnode.out_mask', 'moving_mask')]), (t1_seg, outputnode, [('tissue_class_map', 't1_seg')]), (inu_n4, outputnode, [('output_image', 'bias_corrected_t1')]), (t1_seg, outputnode, [('probability_maps', 't1_tpms')]), (t1_2_mni, outputnode, [ ('warped_image', 't1_2_mni'), ('forward_transforms', 't1_2_mni_forward_transform'), ('reverse_transforms', 't1_2_mni_reverse_transform') ]), (asw, bmask_mni, [('outputnode.out_mask', 'input_image')]), (t1_2_mni, bmask_mni, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (t1_seg, tpms_mni, [('probability_maps', 'input_image')]), (t1_2_mni, tpms_mni, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (asw, outputnode, [('outputnode.out_file', 't1_brain'), ('outputnode.out_mask', 't1_mask')]), (inputnode, ds_t1_seg_report, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (t1_seg, ds_t1_seg_report, [('out_report', 'in_file')]), (inputnode, ds_t1_2_mni_report, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (t1_2_mni, ds_t1_2_mni_report, [('out_report', 'in_file')]) ]) if settings.get('skull_strip_ants', False): ds_t1_skull_strip_report = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='t1_skull_strip', out_path_base='reports'), name='DS_Report' ) workflow.connect([ (inputnode, ds_t1_skull_strip_report, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (asw, ds_t1_skull_strip_report, [('outputnode.out_report', 'in_file')]) ]) # Write corrected file in the designated output dir ds_t1_bias = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='preproc'), name='DerivT1_inu' ) ds_t1_seg = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='dtissue'), name='DerivT1_seg' ) ds_mask = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='brainmask'), name='DerivT1_mask' ) ds_t1_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='space-MNI152NLin2009cAsym_preproc'), name='DerivT1w_MNI' ) ds_t1_mni_aff = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='target-MNI152NLin2009cAsym_affine'), name='DerivT1w_MNI_affine' ) ds_bmask_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='space-MNI152NLin2009cAsym_brainmask'), name='DerivT1_Mask_MNI' ) ds_tpms_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='space-MNI152NLin2009cAsym_class-{extra_value}_probtissue'), name='DerivT1_TPMs_MNI' ) ds_tpms_mni.inputs.extra_values = ['CSF', 'GM', 'WM'] if settings.get('debug', False): workflow.connect([ (t1_2_mni, ds_t1_mni_aff, [('forward_transforms', 'in_file')]) ]) else: ds_t1_mni_warp = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='target-MNI152NLin2009cAsym_warp'), name='mni_warp') def _get_aff(inlist): return inlist[:-1] def _get_warp(inlist): return inlist[-1] workflow.connect([ (inputnode, ds_t1_mni_warp, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (t1_2_mni, ds_t1_mni_aff, [ (('forward_transforms', _get_aff), 'in_file')]), (t1_2_mni, ds_t1_mni_warp, [ (('forward_transforms', _get_warp), 'in_file')]) ]) workflow.connect([ (inputnode, ds_t1_bias, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_t1_seg, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_mask, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_t1_mni, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_t1_mni_aff, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_bmask_mni, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inputnode, ds_tpms_mni, [(('t1w', fix_multi_T1w_source_name), 'source_file')]), (inu_n4, ds_t1_bias, [('output_image', 'in_file')]), (t1_seg, ds_t1_seg, [('tissue_class_map', 'in_file')]), (asw, ds_mask, [('outputnode.out_mask', 'in_file')]), (t1_2_mni, ds_t1_mni, [('warped_image', 'in_file')]), (bmask_mni, ds_bmask_mni, [('output_image', 'in_file')]), (tpms_mni, ds_tpms_mni, [('output_image', 'in_file')]) ]) return workflow
def anat_qc_workflow(dataset, settings, name='anatMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images """ workflow = pe.Workflow(name=name) WFLOGGER.info( 'Building anatomical MRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') meta = pe.Node(ReadSidecarJSON(), name='metadata') # 1a. Reorient anatomical image to_ras = pe.Node(ConformImage(), name='conform') # 1b. Estimate bias n4itk = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='Bias') # 2. Skull-stripping (afni) asw = skullstrip_wf() # 3. Head mask (including nasial-cerebelum mask) hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = pe.Node(RobustMNINormalization( num_threads=settings.get('ants_nthreads', 6), template='mni_icbm152_nlin_asym_09c', testing=settings.get('testing', False), generate_report=True), name='SpatialNormalization') # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST(img_type=1, segments=True, out_basename='segment'), name='segmentation') # 7. Compute IQMs iqmswf = compute_iqms(settings) # Reports repwf = individual_reports(settings) # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, meta, [('in_file', 'in_file')]), (to_ras, n4itk, [('out_file', 'input_image')]), (meta, iqmswf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('run_id', 'inputnode.run_id')]), (n4itk, asw, [('output_image', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (n4itk, hmsk, [('output_image', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (n4itk, norm, [('output_image', 'moving_image')]), (asw, norm, [('outputnode.out_mask', 'moving_mask')]), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (norm, amw, [('reverse_transforms', 'inputnode.reverse_transforms'), ('reverse_invert_flags', 'inputnode.reverse_invert_flags') ]), (norm, iqmswf, [('reverse_transforms', 'inputnode.reverse_transforms'), ('reverse_invert_flags', 'inputnode.reverse_invert_flags')]), (norm, repwf, ([('out_report', 'inputnode.mni_report')])), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.orig')]), (n4itk, iqmswf, [('output_image', 'inputnode.inu_corrected'), ('bias_image', 'inputnode.in_inu')]), (asw, iqmswf, [('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (meta, iqmswf, [('out_dict', 'inputnode.metadata')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.orig')]), (n4itk, repwf, [('output_image', 'inputnode.inu_corrected')]), (asw, repwf, [('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.out_noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) return workflow
def anat_qc_workflow(name="anatMRIQC"): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images .. workflow:: import os.path as op from mriqc.workflows.anatomical import anat_qc_workflow from mriqc.testing import mock_config with mock_config(): wf = anat_qc_workflow() """ from niworkflows.anat.skullstrip import afni_wf as skullstrip_wf dataset = config.workflow.inputs.get( "T1w", []) + config.workflow.inputs.get("T2w", []) message = BUILDING_WORKFLOW.format(dataset=", ".join(dataset)) config.loggers.workflow.info(message) # Initialize workflow workflow = pe.Workflow(name=name) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=["in_file"]), name="inputnode") inputnode.iterables = [("in_file", dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=["out_json"]), name="outputnode") # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(check_dtype=False), name="conform") # 2. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=config.nipype.omp_nthreads, unifize=False) # 3. Head mask hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = spatial_normalization() # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node( fsl.FAST(segments=True, out_basename="segment"), name="segmentation", mem_gb=5, ) # 7. Compute IQMs iqmswf = compute_iqms() # Reports repwf = individual_reports() # Connect all nodes # fmt: off workflow.connect([ (inputnode, to_ras, [("in_file", "in_file")]), (inputnode, iqmswf, [("in_file", "inputnode.in_file")]), (inputnode, norm, [(("in_file", _get_mod), "inputnode.modality")]), (inputnode, segment, [(("in_file", _get_imgtype), "img_type")]), (to_ras, asw, [("out_file", "inputnode.in_file")]), (asw, segment, [("outputnode.out_file", "in_files")]), (asw, hmsk, [("outputnode.bias_corrected", "inputnode.in_file")]), (segment, hmsk, [("tissue_class_map", "inputnode.in_segm")]), (asw, norm, [("outputnode.bias_corrected", "inputnode.moving_image"), ("outputnode.out_mask", "inputnode.moving_mask")]), (norm, amw, [("outputnode.inverse_composite_transform", "inputnode.inverse_composite_transform")]), (norm, iqmswf, [("outputnode.inverse_composite_transform", "inputnode.inverse_composite_transform")]), (norm, repwf, ([("outputnode.out_report", "inputnode.mni_report")])), (to_ras, amw, [("out_file", "inputnode.in_file")]), (asw, amw, [("outputnode.out_mask", "inputnode.in_mask")]), (hmsk, amw, [("outputnode.out_file", "inputnode.head_mask")]), (to_ras, iqmswf, [("out_file", "inputnode.in_ras")]), (asw, iqmswf, [("outputnode.bias_corrected", "inputnode.inu_corrected"), ("outputnode.bias_image", "inputnode.in_inu"), ("outputnode.out_mask", "inputnode.brainmask")]), (amw, iqmswf, [("outputnode.air_mask", "inputnode.airmask"), ("outputnode.hat_mask", "inputnode.hatmask"), ("outputnode.art_mask", "inputnode.artmask"), ("outputnode.rot_mask", "inputnode.rotmask")]), (segment, iqmswf, [("tissue_class_map", "inputnode.segmentation"), ("partial_volume_files", "inputnode.pvms")]), (hmsk, iqmswf, [("outputnode.out_file", "inputnode.headmask")]), (to_ras, repwf, [("out_file", "inputnode.in_ras")]), (asw, repwf, [("outputnode.bias_corrected", "inputnode.inu_corrected"), ("outputnode.out_mask", "inputnode.brainmask")]), (hmsk, repwf, [("outputnode.out_file", "inputnode.headmask")]), (amw, repwf, [("outputnode.air_mask", "inputnode.airmask"), ("outputnode.art_mask", "inputnode.artmask"), ("outputnode.rot_mask", "inputnode.rotmask")]), (segment, repwf, [("tissue_class_map", "inputnode.segmentation")]), (iqmswf, repwf, [("outputnode.noisefit", "inputnode.noisefit")]), (iqmswf, repwf, [("outputnode.out_file", "inputnode.in_iqms")]), (iqmswf, outputnode, [("outputnode.out_file", "out_json")]), ]) # fmt: on # Upload metrics if not config.execution.no_sub: from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name="UploadMetrics") upldwf.inputs.url = config.execution.webapi_url upldwf.inputs.strict = config.execution.upload_strict if config.execution.webapi_port: upldwf.inputs.port = config.execution.webapi_port # fmt: off workflow.connect([ (iqmswf, upldwf, [("outputnode.out_file", "in_iqms")]), (upldwf, repwf, [("api_id", "inputnode.api_id")]), ]) # fmt: on return workflow
def anat_qc_workflow(dataset, settings, mod='T1w', name='anatMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images .. workflow:: import os.path as op from mriqc.workflows.anatomical import anat_qc_workflow datadir = op.abspath('data') wf = anat_qc_workflow([op.join(datadir, 'sub-001/anat/sub-001_T1w.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out'), 'ants_nthreads': 1, 'no_sub': True}) """ logging.getLogger('nipype.workflow').info( 'Building anatomical MRIQC workflow, datasets list: %s', [ str(Path(d).relative_to(settings['bids_dir'])) for d in sorted(dataset) ]) # Initialize workflow workflow = pe.Workflow(name="%s%s" % (name, mod)) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(check_dtype=False), name='conform') # 2. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=settings.get('ants_nthreads', 1), unifize=False) # 3. Head mask hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = spatial_normalization(settings) # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST(segments=True, out_basename='segment', img_type=int(mod[1])), name='segmentation', mem_gb=5) # 7. Compute IQMs iqmswf = compute_iqms(settings, modality=mod) # Reports repwf = individual_reports(settings) # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, iqmswf, [('in_file', 'inputnode.in_file')]), (to_ras, asw, [('out_file', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (asw, hmsk, [('outputnode.bias_corrected', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (asw, norm, [('outputnode.bias_corrected', 'inputnode.moving_image'), ('outputnode.out_mask', 'inputnode.moving_mask')]), (norm, amw, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, iqmswf, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, repwf, ([('outputnode.out_report', 'inputnode.mni_report')])), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.in_ras')]), (asw, iqmswf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.bias_image', 'inputnode.in_inu'), ('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.air_mask', 'inputnode.airmask'), ('outputnode.hat_mask', 'inputnode.hatmask'), ('outputnode.art_mask', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.in_ras')]), (asw, repwf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.air_mask', 'inputnode.airmask'), ('outputnode.art_mask', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) # Upload metrics if not settings.get('no_sub', False): from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name='UploadMetrics') upldwf.inputs.email = settings.get('email', '') upldwf.inputs.url = settings.get('webapi_url') if settings.get('webapi_port'): upldwf.inputs.port = settings.get('webapi_port') upldwf.inputs.strict = settings.get('upload_strict', False) workflow.connect([ (iqmswf, upldwf, [('outputnode.out_file', 'in_iqms')]), (upldwf, repwf, [('api_id', 'inputnode.api_id')]), ]) return workflow
def t1w_preprocessing(name='t1w_preprocessing', settings=None): """T1w images preprocessing pipeline""" if settings is None: raise RuntimeError('Workflow settings are missing') workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['t1w']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['t1_seg', 'bias_corrected_t1', 't1_brain', 't1_2_mni', 't1_2_mni_forward_transform', 't1_2_mni_reverse_transform', 't1_segmentation']), name='outputnode') # 1. Reorient T1 arw = pe.Node(fs.MRIConvert(out_type='niigz', out_orientation='RAS'), name='Reorient') # 2. T1 Bias Field Correction inu_n4 = pe.Node(ants.N4BiasFieldCorrection(dimension=3), name='Bias_Field_Correction') # 3. Skull-stripping asw = skullstrip_wf() if settings.get('skull_strip_ants', False): asw = skullstrip_ants(settings=settings) # 4. Segmentation t1_seg = pe.Node(fsl.FAST(no_bias=True, probability_maps=True), name='T1_Segmentation') # 5. T1w to MNI registration t1_2_mni = pe.Node(ants.Registration(), name='T1_2_MNI_Registration') t1_2_mni.inputs.collapse_output_transforms = False t1_2_mni.inputs.write_composite_transform = False t1_2_mni.inputs.output_transform_prefix = 'T1_to_MNI_' t1_2_mni.inputs.output_warped_image = 't1_to_mni.nii.gz' t1_2_mni.inputs.num_threads = 4 t1_2_mni.inputs.fixed_image = op.join(get_mni_template_ras(), 'MNI152_T1_1mm.nii.gz') t1_2_mni.inputs.fixed_image_mask = op.join( get_mni_template_ras(), 'MNI152_T1_1mm_brain_mask.nii.gz') # Hack to avoid re-running ANTs all the times grabber_interface = nio.JSONFileGrabber() setattr(grabber_interface, '_always_run', False) t1_2_mni_params = pe.Node(grabber_interface, name='t1_2_mni_params') t1_2_mni_params.inputs.in_file = ( pkgr.resource_filename('fmriprep', 'data/{}.json'.format( settings.get('ants_t1-mni_settings', 't1-mni_registration2'))) ) # Resampe the brain mask and the tissue probability maps into mni space bmask_mni = pe.Node(ants.ApplyTransforms( dimension=3, default_value=0, interpolation='NearestNeighbor'), name='brain_mni_warp') bmask_mni.inputs.reference_image = op.join(get_mni_template_ras(), 'MNI152_T1_1mm.nii.gz') tpms_mni = pe.MapNode(ants.ApplyTransforms(dimension=3, default_value=0, interpolation='Linear'), iterfield=['input_image'], name='tpms_mni_warp') tpms_mni.inputs.reference_image = op.join(get_mni_template_ras(), 'MNI152_T1_1mm.nii.gz') workflow.connect([ (inputnode, arw, [('t1w', 'in_file')]), (arw, inu_n4, [('out_file', 'input_image')]), (inu_n4, asw, [('output_image', 'inputnode.in_file')]), (asw, t1_seg, [('outputnode.out_file', 'in_files')]), (inu_n4, t1_2_mni, [('output_image', 'moving_image')]), (asw, t1_2_mni, [('outputnode.out_mask', 'moving_image_mask')]), (t1_seg, outputnode, [('tissue_class_map', 't1_seg')]), (inu_n4, outputnode, [('output_image', 'bias_corrected_t1')]), (t1_seg, outputnode, [('tissue_class_map', 't1_segmentation')]), (t1_2_mni, outputnode, [ ('warped_image', 't1_2_mni'), ('forward_transforms', 't1_2_mni_forward_transform'), ('reverse_transforms', 't1_2_mni_reverse_transform') ]), (asw, bmask_mni, [('outputnode.out_mask', 'input_image')]), (t1_2_mni, bmask_mni, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (t1_seg, tpms_mni, [('probability_maps', 'input_image')]), (t1_2_mni, tpms_mni, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (asw, outputnode, [ ('outputnode.out_file', 't1_brain')]), ]) # Connect reporting nodes t1_stripped_overlay = pe.Node(niu.Function( input_names=['in_file', 'overlay_file', 'out_file'], output_names=['out_file'], function=stripped_brain_overlay), name='PNG_T1_SkullStrip') t1_stripped_overlay.inputs.out_file = 't1_stripped_overlay.png' # The T1-to-MNI will be plotted using the segmentation. That's why we transform it first seg_2_mni = pe.Node(ants.ApplyTransforms( dimension=3, default_value=0, interpolation='NearestNeighbor'), name='T1_2_MNI_warp') seg_2_mni.inputs.reference_image = op.join(get_mni_template_ras(), 'MNI152_T1_1mm.nii.gz') t1_2_mni_overlay = pe.Node(niu.Function( input_names=['in_file', 'overlay_file', 'out_file'], output_names=['out_file'], function=stripped_brain_overlay), name='PNG_T1_to_MNI') t1_2_mni_overlay.inputs.out_file = 't1_to_mni_overlay.png' t1_2_mni_overlay.inputs.overlay_file = op.join(get_mni_template_ras(), 'MNI152_T1_1mm.nii.gz') datasink = pe.Node( interface=nio.DataSink( base_directory=op.join(settings['output_dir'], 'images')), name='datasink', parameterization=False ) workflow.connect([ (inu_n4, t1_stripped_overlay, [('output_image', 'overlay_file')]), (asw, t1_stripped_overlay, [('outputnode.out_mask', 'in_file')]), (t1_stripped_overlay, datasink, [('out_file', '@t1_stripped_overlay')]), (t1_seg, seg_2_mni, [('tissue_class_map', 'input_image')]), (t1_2_mni, seg_2_mni, [('forward_transforms', 'transforms'), ('forward_invert_flags', 'invert_transform_flags')]), (seg_2_mni, t1_2_mni_overlay, [('output_image', 'in_file')]), (t1_2_mni_overlay, datasink, [('out_file', '@t1_2_mni_overlay')]), ]) # Write corrected file in the designated output dir ds_t1_bias = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='inu'), name='DerivT1_inu') ds_t1_seg = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='inu_seg'), name='DerivT1_seg') ds_mask = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='bmask'), name='DerivT1_mask') ds_t1_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='mni'), name='DerivT1w_MNI') ds_t1_mni_aff = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='mni_affine'), name='DerivT1w_MNI_affine') ds_bmask_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='bmask_mni'), name='DerivT1_Mask_MNI') ds_tpms_mni = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='tpm_mni'), name='DerivT1_TPMs_MNI') if settings.get('debug', False): workflow.connect([ (t1_2_mni, ds_t1_mni_aff, [('forward_transforms', 'in_file')]) ]) else: ds_t1_mni_warp = pe.Node( DerivativesDataSink(base_directory=settings['output_dir'], suffix='mni_warp'), name='DerivT1w_MNI_warp') def _get_aff(inlist): return inlist[:-1] def _get_warp(inlist): return inlist[-1] workflow.connect([ (inputnode, ds_t1_mni_warp, [('t1w', 'source_file')]), (t1_2_mni, ds_t1_mni_aff, [ (('forward_transforms', _get_aff), 'in_file')]), (t1_2_mni, ds_t1_mni_warp, [ (('forward_transforms', _get_warp), 'in_file')]) ]) workflow.connect([ (inputnode, ds_t1_bias, [('t1w', 'source_file')]), (inputnode, ds_t1_seg, [('t1w', 'source_file')]), (inputnode, ds_mask, [('t1w', 'source_file')]), (inputnode, ds_t1_mni, [('t1w', 'source_file')]), (inputnode, ds_t1_mni_aff, [('t1w', 'source_file')]), (inputnode, ds_bmask_mni, [('t1w', 'source_file')]), (inputnode, ds_tpms_mni, [('t1w', 'source_file')]), (asw, ds_t1_bias, [('outputnode.out_file', 'in_file')]), (t1_seg, ds_t1_seg, [('tissue_class_map', 'in_file')]), (asw, ds_mask, [('outputnode.out_mask', 'in_file')]), (t1_2_mni, ds_t1_mni, [('warped_image', 'in_file')]), (bmask_mni, ds_bmask_mni, [('output_image', 'in_file')]), (tpms_mni, ds_tpms_mni, [('output_image', 'in_file')]) ]) # ANTs inputs connected here for clarity workflow.connect([ (t1_2_mni_params, t1_2_mni, [ ('metric', 'metric'), ('metric_weight', 'metric_weight'), ('dimension', 'dimension'), ('write_composite_transform', 'write_composite_transform'), ('radius_or_number_of_bins', 'radius_or_number_of_bins'), ('shrink_factors', 'shrink_factors'), ('smoothing_sigmas', 'smoothing_sigmas'), ('sigma_units', 'sigma_units'), ('output_transform_prefix', 'output_transform_prefix'), ('transforms', 'transforms'), ('transform_parameters', 'transform_parameters'), ('initial_moving_transform_com', 'initial_moving_transform_com'), ('number_of_iterations', 'number_of_iterations'), ('convergence_threshold', 'convergence_threshold'), ('convergence_window_size', 'convergence_window_size'), ('sampling_strategy', 'sampling_strategy'), ('sampling_percentage', 'sampling_percentage'), ('output_warped_image', 'output_warped_image'), ('use_histogram_matching', 'use_histogram_matching'), ('use_estimate_learning_rate_once', 'use_estimate_learning_rate_once'), ('collapse_output_transforms', 'collapse_output_transforms'), ('winsorize_lower_quantile', 'winsorize_lower_quantile'), ('winsorize_upper_quantile', 'winsorize_upper_quantile'), ]) ]) return workflow
def anat_qc_workflow(name='anatMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images .. workflow:: import os.path as op from mriqc.workflows.anatomical import anat_qc_workflow from mriqc.testing import mock_config with mock_config(): wf = anat_qc_workflow() """ from niworkflows.anat.skullstrip import afni_wf as skullstrip_wf dataset = config.workflow.inputs.get("T1w", []) \ + config.workflow.inputs.get("T2w", []) config.loggers.workflow.info(f"""\ Building anatomical MRIQC workflow for files: {', '.join(dataset)}.""") # Initialize workflow workflow = pe.Workflow(name=name) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(check_dtype=False), name='conform') # 2. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=config.nipype.omp_nthreads, unifize=False) # 3. Head mask hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = spatial_normalization() # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST(segments=True, out_basename='segment'), name='segmentation', mem_gb=5) # 7. Compute IQMs iqmswf = compute_iqms() # Reports repwf = individual_reports() # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, iqmswf, [('in_file', 'inputnode.in_file')]), (inputnode, norm, [(('in_file', _get_mod), 'inputnode.modality')]), (inputnode, segment, [(('in_file', _get_imgtype), 'img_type')]), (to_ras, asw, [('out_file', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (asw, hmsk, [('outputnode.bias_corrected', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (asw, norm, [('outputnode.bias_corrected', 'inputnode.moving_image'), ('outputnode.out_mask', 'inputnode.moving_mask')]), (norm, amw, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, iqmswf, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, repwf, ([('outputnode.out_report', 'inputnode.mni_report')])), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.in_ras')]), (asw, iqmswf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.bias_image', 'inputnode.in_inu'), ('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.air_mask', 'inputnode.airmask'), ('outputnode.hat_mask', 'inputnode.hatmask'), ('outputnode.art_mask', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.in_ras')]), (asw, repwf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.air_mask', 'inputnode.airmask'), ('outputnode.art_mask', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) # Upload metrics if not config.execution.no_sub: from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name='UploadMetrics') upldwf.inputs.url = config.execution.webapi_url upldwf.inputs.strict = config.execution.upload_strict if config.execution.webapi_port: upldwf.inputs.port = config.execution.webapi_port workflow.connect([ (iqmswf, upldwf, [('outputnode.out_file', 'in_iqms')]), (upldwf, repwf, [('api_id', 'inputnode.api_id')]), ]) return workflow
def anat_qc_workflow(name='MRIQC_Anat', settings=None): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images """ if settings is None: settings = {} workflow = pe.Workflow(name=name) deriv_dir = op.abspath(op.join(settings['output_dir'], 'derivatives')) if not op.exists(deriv_dir): os.makedirs(deriv_dir) # Define workflow, inputs and outputs inputnode = pe.Node(niu.IdentityInterface( fields=['bids_dir', 'subject_id', 'session_id', 'run_id']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 0. Get data datasource = pe.Node(niu.Function(input_names=[ 'bids_dir', 'data_type', 'subject_id', 'session_id', 'run_id' ], output_names=['anatomical_scan'], function=bids_getfile), name='datasource') datasource.inputs.data_type = 'anat' meta = pe.Node(ReadSidecarJSON(), name='metadata') # 1a. Reorient anatomical image arw = pe.Node(MRIConvert(out_type='niigz', out_orientation='LAS'), name='Reorient') # 1b. Estimate bias n4itk = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='Bias') # 2. Skull-stripping (afni) asw = skullstrip_wf() mask = pe.Node(fsl.ApplyMask(), name='MaskAnatomical') # 3. Head mask (including nasial-cerebelum mask) hmsk = headmsk_wf() # 4. Air mask (with and without artifacts) amw = airmsk_wf(settings=settings) # Brain tissue segmentation segment = pe.Node(fsl.FAST(img_type=1, segments=True, out_basename='segment'), name='segmentation') # AFNI check smoothing fwhm = pe.Node(afp.FWHMx(combine=True, detrend=True), name='smoothness') # fwhm.inputs.acf = True # add when AFNI >= 16 # Compute python-coded measures measures = pe.Node(StructuralQC(testing=settings.get('testing', False)), 'measures') # Link images that should be reported dsreport = pe.Node(nio.DataSink(base_directory=settings['report_dir'], parameterization=True), name='dsreport') dsreport.inputs.container = 'anat' dsreport.inputs.substitutions = [('_data', ''), ('background_fit', 'plot_bgfit')] dsreport.inputs.regexp_substitutions = [ ('_u?(sub-[\\w\\d]*)\\.([\\w\\d_]*)(?:\\.([\\w\\d_-]*))+', '\\1_ses-\\2_\\3'), ('anatomical_bgplotsub-[^/.]*_dvars_std', 'plot_dvars'), ('sub-[^/.]*_T1w_out_calc_thresh', 'mask'), ('sub-[^/.]*_T1w_out\\.', 'mosaic_t1w.') ] # Connect all nodes workflow.connect([ (inputnode, datasource, [('bids_dir', 'bids_dir'), ('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (datasource, arw, [('anatomical_scan', 'in_file')]), (datasource, meta, [('anatomical_scan', 'in_file')]), (arw, asw, [('out_file', 'inputnode.in_file')]), (arw, n4itk, [('out_file', 'input_image')]), # (asw, n4itk, [('outputnode.out_mask', 'mask_image')]), (n4itk, mask, [('output_image', 'in_file')]), (asw, mask, [('outputnode.out_mask', 'mask_file')]), (mask, segment, [('out_file', 'in_files')]), (n4itk, hmsk, [('output_image', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (n4itk, measures, [('output_image', 'in_noinu')]), (arw, measures, [('out_file', 'in_file')]), (arw, fwhm, [('out_file', 'in_file')]), (asw, fwhm, [('outputnode.out_mask', 'mask')]), (arw, amw, [('out_file', 'inputnode.in_file')]), (n4itk, amw, [('output_image', 'inputnode.in_noinu')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (amw, measures, [('outputnode.out_file', 'air_msk')]), (amw, measures, [('outputnode.artifact_msk', 'artifact_msk')]), (segment, measures, [('tissue_class_map', 'in_segm'), ('partial_volume_files', 'in_pvms')]), (n4itk, measures, [('bias_image', 'in_bias')]), (measures, dsreport, [('out_noisefit', '@anat_noiseplot')]), (arw, dsreport, [('out_file', '@anat_t1w')]), (asw, dsreport, [('outputnode.out_mask', '@anat_t1_mask')]) ]) # Format name out_name = pe.Node(niu.Function( input_names=['subid', 'sesid', 'runid', 'prefix', 'out_path'], output_names=['out_file'], function=bids_path), name='FormatName') out_name.inputs.out_path = deriv_dir out_name.inputs.prefix = 'anat' # Save to JSON file jfs_if = nio.JSONFileSink() setattr(jfs_if, '_always_run', settings.get('force_run', False)) datasink = pe.Node(jfs_if, name='datasink') datasink.inputs.qc_type = 'anat' workflow.connect([(inputnode, out_name, [('subject_id', 'subid'), ('session_id', 'sesid'), ('run_id', 'runid')]), (inputnode, datasink, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (fwhm, datasink, [(('fwhm', fwhm_dict), 'fwhm')]), (measures, datasink, [('summary', 'summary'), ('spacing', 'spacing'), ('size', 'size'), ('icvs', 'icvs'), ('rpve', 'rpve'), ('inu', 'inu'), ('snr', 'snr'), ('cnr', 'cnr'), ('fber', 'fber'), ('efc', 'efc'), ('qi1', 'qi1'), ('qi2', 'qi2'), ('cjv', 'cjv'), ('wm2max', 'wm2max')]), (out_name, datasink, [('out_file', 'out_file')]), (meta, datasink, [('out_dict', 'metadata')]), (datasink, outputnode, [('out_file', 'out_file')])]) return workflow
def dwi_qc_workflow(dataset, settings, mod='dwi', name='dwiMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from diffusion weighted images .. workflow:: import os.path as op from mriqc.workflows.diffusion import dwi_qc_workflow datadir = op.abspath('data') wf = dwi_qc_workflow([op.join(datadir, 'sub-001/anat/sub-001_T1w.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out'), 'ants_nthreads': 1, 'no_sub': True}) """ workflow = pe.Workflow(name=name+mod) WFLOGGER.info('Building diffusion weighted MRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file, in_bval']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(check_dtype=False), name='conform') # 2. Extract b0 images extb0 = pe.Node(ExtractB0, name='ExtractB0s') # 3. Eddy correction with fsl FLIRT flirt = pe.MapNode(fsl.FLIRT(out_matrix_file='affine_xfrm'), name='flirt') # 4. Average b0 images avgb0 = avgb0_wf() # 5. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=settings.get('ants_nthreads', 1), unifize=False) # 6. Head mask hmsk = headmsk_wf() # 7. Spatial Normalization, using ANTs norm = spatial_normalization(settings) # 8. Air mask (with and without artifacts) amw = airmsk_wf() # 9. Brain tissue segmentation segment = pe.Node(fsl.FAST(segments=True, out_basename='segment', img_type=int(mod[1])), name='segmentation', estimated_memory_gb=3) # 10. Compute IQMs iqmswf = compute_iqms(settings, modality=mod) # Reports repwf = individual_reports(settings) # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, iqmswf, [('in_file', 'inputnode.in_file')]), (inputnode, extb0, [('in_bval', 'in_bval')]), (to_ras, extb0, [('out_file', 'in_dwi')]), (extb0, flirt, [('ref_img', 'reference')]), (extb0, flirt, [('out_imgs', 'in_file')]), (flirt, avgb0, [('out_file', 'inputnode.in_files')]), (avgb0, asw, [('out_file', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (asw, hmsk, [('outputnode.bias_corrected', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (asw, norm, [('outputnode.bias_corrected', 'inputnode.moving_image'), ('outputnode.out_mask', 'inputnode.moving_mask')]), (norm, amw, [ ('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, iqmswf, [ ('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, repwf, ([ ('outputnode.out_report', 'inputnode.mni_report')])), (avgb0, amw, [('out_file', 'inputnode.in_file')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (avgb0, iqmswf, [('out_file', 'inputnode.in_ras')]), (asw, iqmswf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.bias_image', 'inputnode.in_inu'), ('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (avgb0, repwf, [('out_file', 'inputnode.in_ras')]), (asw, repwf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.out_noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) # Upload metrics if not settings.get('no_sub', False): from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name='UploadMetrics') upldwf.inputs.email = settings.get('email', '') upldwf.inputs.url = settings.get('webapi_url') if settings.get('webapi_port'): upldwf.inputs.port = settings.get('webapi_port') upldwf.inputs.strict = settings.get('upload_strict', False) workflow.connect([ (iqmswf, upldwf, [('outputnode.out_file', 'in_iqms')]), ]) return workflow
def anat_qc_workflow(dataset, settings, mod='T1w', name='anatMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images .. workflow:: import os.path as op from mriqc.workflows.anatomical import anat_qc_workflow datadir = op.abspath('data') wf = anat_qc_workflow([op.join(datadir, 'sub-001/anat/sub-001_T1w.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out'), 'ants_nthreads': 1, 'no_sub': True}) """ workflow = pe.Workflow(name=name+mod) WFLOGGER.info('Building anatomical MRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(check_dtype=False), name='conform') # 2. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=settings.get('ants_nthreads', 1), unifize=False) # 3. Head mask hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = spatial_normalization(settings) # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST(segments=True, out_basename='segment', img_type=int(mod[1])), name='segmentation', estimated_memory_gb=3) # 7. Compute IQMs iqmswf = compute_iqms(settings, modality=mod) # Reports repwf = individual_reports(settings) # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, iqmswf, [('in_file', 'inputnode.in_file')]), (to_ras, asw, [('out_file', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (asw, hmsk, [('outputnode.bias_corrected', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (asw, norm, [('outputnode.bias_corrected', 'inputnode.moving_image'), ('outputnode.out_mask', 'inputnode.moving_mask')]), (norm, amw, [ ('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, iqmswf, [ ('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, repwf, ([ ('outputnode.out_report', 'inputnode.mni_report')])), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.in_ras')]), (asw, iqmswf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.bias_image', 'inputnode.in_inu'), ('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.in_ras')]), (asw, repwf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask'), ('outputnode.rot_mask', 'inputnode.rotmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.out_noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) # Upload metrics if not settings.get('no_sub', False): from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name='UploadMetrics') upldwf.inputs.email = settings.get('email', '') upldwf.inputs.url = settings.get('webapi_url') if settings.get('webapi_port'): upldwf.inputs.port = settings.get('webapi_port') upldwf.inputs.strict = settings.get('upload_strict', False) workflow.connect([ (iqmswf, upldwf, [('outputnode.out_file', 'in_iqms')]), ]) return workflow
def anat_qc_workflow(name='MRIQC_Anat', settings=None): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images """ if settings is None: settings = {} workflow = pe.Workflow(name=name) deriv_dir = op.abspath('./derivatives') if 'work_dir' in settings.keys(): deriv_dir = op.abspath(op.join(settings['work_dir'], 'derivatives')) if not op.exists(deriv_dir): os.makedirs(deriv_dir) # Define workflow, inputs and outputs inputnode = pe.Node(niu.IdentityInterface( fields=['bids_root', 'subject_id', 'session_id', 'run_id']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 0. Get data datasource = pe.Node(niu.Function( input_names=['bids_root', 'data_type', 'subject_id', 'session_id', 'run_id'], output_names=['anatomical_scan'], function=bids_getfile), name='datasource') datasource.inputs.data_type = 'anat' # 1a. Reorient anatomical image arw = mri_reorient_wf() # 1b. Estimate bias n4itk = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='Bias') # 2. Skull-stripping (afni) asw = skullstrip_wf() mask = pe.Node(fsl.ApplyMask(), name='MaskAnatomical') # 3. Head mask (including nasial-cerebelum mask) hmsk = headmsk_wf() # 4. Air mask (with and without artifacts) amw = airmsk_wf(save_memory=settings.get('save_memory', False), ants_settings=settings.get('ants_settings', None)) # Brain tissue segmentation segment = pe.Node(fsl.FAST( img_type=1, segments=True, out_basename='segment'), name='segmentation') # AFNI check smoothing fwhm = pe.Node(afp.FWHMx(combine=True, detrend=True), name='smoothness') # fwhm.inputs.acf = True # add when AFNI >= 16 # Compute python-coded measures measures = pe.Node(StructuralQC(), 'measures') # Plot mosaic plot = pe.Node(PlotMosaic(), name='plot_mosaic') merg = pe.Node(niu.Merge(3), name='plot_metadata') # Connect all nodes workflow.connect([ (inputnode, datasource, [('bids_root', 'bids_root'), ('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (datasource, arw, [('anatomical_scan', 'inputnode.in_file')]), (arw, asw, [('outputnode.out_file', 'inputnode.in_file')]), (arw, n4itk, [('outputnode.out_file', 'input_image')]), # (asw, n4itk, [('outputnode.out_mask', 'mask_image')]), (n4itk, mask, [('output_image', 'in_file')]), (asw, mask, [('outputnode.out_mask', 'mask_file')]), (mask, segment, [('out_file', 'in_files')]), (n4itk, hmsk, [('output_image', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (n4itk, measures, [('output_image', 'in_noinu')]), (arw, measures, [('outputnode.out_file', 'in_file')]), (arw, fwhm, [('outputnode.out_file', 'in_file')]), (asw, fwhm, [('outputnode.out_mask', 'mask')]), (arw, amw, [('outputnode.out_file', 'inputnode.in_file')]), (n4itk, amw, [('output_image', 'inputnode.in_noinu')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (amw, measures, [('outputnode.out_file', 'air_msk')]), (amw, measures, [('outputnode.artifact_msk', 'artifact_msk')]), (segment, measures, [('tissue_class_map', 'in_segm'), ('partial_volume_files', 'in_pvms')]), (n4itk, measures, [('bias_image', 'in_bias')]), (arw, plot, [('outputnode.out_file', 'in_file')]), (inputnode, plot, [('subject_id', 'subject')]), (inputnode, merg, [('session_id', 'in1'), ('run_id', 'in2')]), (merg, plot, [('out', 'metadata')]) ]) if settings.get('mask_mosaic', False): workflow.connect(asw, 'outputnode.out_file', plot, 'in_mask') # Save mosaic to well-formed path mvplot = pe.Node(niu.Rename( format_string='anatomical_%(subject_id)s_%(session_id)s_%(run_id)s', keep_ext=True), name='rename_plot') dsplot = pe.Node(nio.DataSink( base_directory=settings['work_dir'], parameterization=False), name='ds_plot') workflow.connect([ (inputnode, mvplot, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (plot, mvplot, [('out_file', 'in_file')]), (mvplot, dsplot, [('out_file', '@mosaic')]) ]) # Save background-noise fitting plot mvbgplot = pe.Node(niu.Rename( format_string='anatomical_bgplot_%(subject_id)s_%(session_id)s_%(run_id)s', keep_ext=True), name='rename_bgplot') dsbgplot = pe.Node(nio.DataSink( base_directory=settings['work_dir'], parameterization=False), name='ds_bgplot') workflow.connect([ (inputnode, mvbgplot, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (measures, mvbgplot, [('out_noisefit', 'in_file')]), (mvbgplot, dsbgplot, [('out_file', '@bg_fitting')]) ]) # Format name out_name = pe.Node(niu.Function( input_names=['subid', 'sesid', 'runid', 'prefix', 'out_path'], output_names=['out_file'], function=bids_path), name='FormatName') out_name.inputs.out_path = deriv_dir out_name.inputs.prefix = 'anat' # Save to JSON file jfs_if = nio.JSONFileSink() setattr(jfs_if, '_always_run', settings.get('force_run', False)) datasink = pe.Node(jfs_if, name='datasink') datasink.inputs.qc_type = 'anat' workflow.connect([ (inputnode, out_name, [('subject_id', 'subid'), ('session_id', 'sesid'), ('run_id', 'runid')]), (inputnode, datasink, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (plot, datasink, [('out_file', 'mosaic_file')]), (fwhm, datasink, [(('fwhm', fwhm_dict), 'fwhm')]), (measures, datasink, [('summary', 'summary'), ('spacing', 'spacing'), ('size', 'size'), ('icvs', 'icvs'), ('rpve', 'rpve'), ('inu', 'inu'), ('snr', 'snr'), ('cnr', 'cnr'), ('fber', 'fber'), ('efc', 'efc'), ('qi1', 'qi1'), ('qi2', 'qi2'), ('cjv', 'cjv')]), (out_name, datasink, [('out_file', 'out_file')]), (datasink, outputnode, [('out_file', 'out_file')]) ]) return workflow
def anat_qc_workflow(dataset, settings, mod='T1w', name='anatMRIQC'): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images .. workflow:: import os.path as op from mriqc.workflows.anatomical import anat_qc_workflow datadir = op.abspath('data') wf = anat_qc_workflow([op.join(datadir, 'sub-001/anat/sub-001_T1w.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out'), 'ants_nthreads': 1}) """ workflow = pe.Workflow(name=name + mod) WFLOGGER.info( 'Building anatomical MRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) # Define workflow, inputs and outputs # 0. Get data inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') meta = pe.Node(ReadSidecarJSON(), name='metadata') # 1. Reorient anatomical image to_ras = pe.Node(ConformImage(), name='conform') # 2. Skull-stripping (afni) asw = skullstrip_wf(n4_nthreads=settings.get('ants_nthreads', 1)) # 3. Head mask hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = spatial_normalization(settings) # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST(segments=True, out_basename='segment', img_type=int(mod[1])), name='segmentation', estimated_memory_gb=3) # 7. Compute IQMs iqmswf = compute_iqms(settings, modality=mod) # Reports repwf = individual_reports(settings) # Upload metrics upldwf = upload_wf(settings) # Connect all nodes workflow.connect([ (inputnode, to_ras, [('in_file', 'in_file')]), (inputnode, meta, [('in_file', 'in_file')]), (meta, iqmswf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('acq_id', 'inputnode.acq_id'), ('rec_id', 'inputnode.rec_id'), ('run_id', 'inputnode.run_id')]), (to_ras, asw, [('out_file', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (asw, hmsk, [('outputnode.bias_corrected', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (asw, norm, [('outputnode.bias_corrected', 'inputnode.moving_image'), ('outputnode.out_mask', 'inputnode.moving_mask')]), (norm, amw, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, iqmswf, [('outputnode.inverse_composite_transform', 'inputnode.inverse_composite_transform')]), (norm, repwf, ([('outputnode.out_report', 'inputnode.mni_report')])), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.orig')]), (asw, iqmswf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.bias_image', 'inputnode.in_inu'), ('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (meta, iqmswf, [('out_dict', 'inputnode.metadata')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.orig')]), (asw, repwf, [('outputnode.bias_corrected', 'inputnode.inu_corrected'), ('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.out_noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, upldwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) return workflow
def anat_qc_workflow(name='MRIQC_Anat', settings=None): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images """ if settings is None: settings = {} workflow = pe.Workflow(name=name) # Define workflow, inputs and outputs inputnode = pe.Node(niu.IdentityInterface( fields=['bids_dir', 'subject_id', 'session_id', 'run_id']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 0. Get data datasource = pe.Node(niu.Function( input_names=['bids_dir', 'data_type', 'subject_id', 'session_id', 'run_id'], output_names=['anatomical_scan'], function=bids_getfile), name='datasource') datasource.inputs.data_type = 'anat' meta = pe.Node(ReadSidecarJSON(), name='metadata') # 1a. Reorient anatomical image to_ras = pe.Node(niu.Function(input_names=['in_file'], output_names=["out_file"], function=reorient), name='Reorient') # 1b. Estimate bias n4itk = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='Bias') # 2. Skull-stripping (afni) asw = skullstrip_wf() # 3. Head mask (including nasial-cerebelum mask) hmsk = headmsk_wf() # 4. Spatial Normalization, using ANTs norm = pe.Node(RobustMNINormalization( num_threads=settings.get('ants_nthreads', 6), template='mni_icbm152_nlin_asym_09c', testing=settings.get('testing', False)), name='SpatialNormalization') # 5. Air mask (with and without artifacts) amw = airmsk_wf() # 6. Brain tissue segmentation segment = pe.Node(fsl.FAST( img_type=1, segments=True, out_basename='segment'), name='segmentation') # 7. Compute IQMs iqmswf = compute_iqms(settings) # Reports repwf = individual_reports(settings) # Connect all nodes workflow.connect([ (inputnode, datasource, [('bids_dir', 'bids_dir'), ('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (inputnode, iqmswf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('run_id', 'inputnode.run_id')]), (inputnode, repwf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('run_id', 'inputnode.run_id')]), (datasource, to_ras, [('anatomical_scan', 'in_file')]), (datasource, meta, [('anatomical_scan', 'in_file')]), (to_ras, n4itk, [('out_file', 'input_image')]), (n4itk, asw, [('output_image', 'inputnode.in_file')]), (asw, segment, [('outputnode.out_file', 'in_files')]), (n4itk, hmsk, [('output_image', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (n4itk, norm, [('output_image', 'moving_image')]), (asw, norm, [('outputnode.out_mask', 'moving_mask')]), (to_ras, amw, [('out_file', 'inputnode.in_file')]), (norm, amw, [('reverse_transforms', 'inputnode.reverse_transforms'), ('reverse_invert_flags', 'inputnode.reverse_invert_flags')]), (norm, iqmswf, [('reverse_transforms', 'inputnode.reverse_transforms'), ('reverse_invert_flags', 'inputnode.reverse_invert_flags')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (to_ras, iqmswf, [('out_file', 'inputnode.orig')]), (n4itk, iqmswf, [('output_image', 'inputnode.inu_corrected'), ('bias_image', 'inputnode.in_inu')]), (asw, iqmswf, [('outputnode.out_mask', 'inputnode.brainmask')]), (amw, iqmswf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, iqmswf, [('tissue_class_map', 'inputnode.segmentation'), ('partial_volume_files', 'inputnode.pvms')]), (meta, iqmswf, [('out_dict', 'inputnode.metadata')]), (hmsk, iqmswf, [('outputnode.out_file', 'inputnode.headmask')]), (to_ras, repwf, [('out_file', 'inputnode.orig')]), (n4itk, repwf, [('output_image', 'inputnode.inu_corrected')]), (asw, repwf, [('outputnode.out_mask', 'inputnode.brainmask')]), (hmsk, repwf, [('outputnode.out_file', 'inputnode.headmask')]), (amw, repwf, [('outputnode.out_file', 'inputnode.airmask'), ('outputnode.artifact_msk', 'inputnode.artmask')]), (segment, repwf, [('tissue_class_map', 'inputnode.segmentation')]), (iqmswf, repwf, [('outputnode.out_noisefit', 'inputnode.noisefit')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (iqmswf, outputnode, [('outputnode.out_file', 'out_json')]) ]) return workflow
def anat_qc_workflow(name='MRIQC_Anat', settings=None): """ One-subject-one-session-one-run pipeline to extract the NR-IQMs from anatomical images """ if settings is None: settings = {} workflow = pe.Workflow(name=name) deriv_dir = op.abspath('./derivatives') if 'work_dir' in settings.keys(): deriv_dir = op.abspath(op.join(settings['work_dir'], 'derivatives')) if not op.exists(deriv_dir): os.makedirs(deriv_dir) # Define workflow, inputs and outputs inputnode = pe.Node(niu.IdentityInterface( fields=['bids_root', 'subject_id', 'session_id', 'run_id']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_json']), name='outputnode') # 0. Get data datasource = pe.Node(niu.Function(input_names=[ 'bids_root', 'data_type', 'subject_id', 'session_id', 'run_id' ], output_names=['anatomical_scan'], function=bids_getfile), name='datasource') datasource.inputs.data_type = 'anat' # 1a. Reorient anatomical image arw = mri_reorient_wf() # 1b. Estimate bias n4itk = pe.Node(ants.N4BiasFieldCorrection(dimension=3, save_bias=True), name='Bias') # 2. Skull-stripping (afni) asw = skullstrip_wf() mask = pe.Node(fsl.ApplyMask(), name='MaskAnatomical') # 3. Head mask (including nasial-cerebelum mask) hmsk = headmsk_wf() # 4. Air mask (with and without artifacts) amw = airmsk_wf(save_memory=settings.get('save_memory', False), ants_settings=settings.get('ants_settings', None)) # Brain tissue segmentation segment = pe.Node(fsl.FAST(img_type=1, segments=True, out_basename='segment'), name='segmentation') # AFNI check smoothing fwhm = pe.Node(afp.FWHMx(combine=True, detrend=True), name='smoothness') # fwhm.inputs.acf = True # add when AFNI >= 16 # Compute python-coded measures measures = pe.Node(StructuralQC(), 'measures') # Plot mosaic plot = pe.Node(PlotMosaic(), name='plot_mosaic') merg = pe.Node(niu.Merge(3), name='plot_metadata') # Connect all nodes workflow.connect([ (inputnode, datasource, [('bids_root', 'bids_root'), ('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (datasource, arw, [('anatomical_scan', 'inputnode.in_file')]), (arw, asw, [('outputnode.out_file', 'inputnode.in_file')]), (arw, n4itk, [('outputnode.out_file', 'input_image')]), # (asw, n4itk, [('outputnode.out_mask', 'mask_image')]), (n4itk, mask, [('output_image', 'in_file')]), (asw, mask, [('outputnode.out_mask', 'mask_file')]), (mask, segment, [('out_file', 'in_files')]), (n4itk, hmsk, [('output_image', 'inputnode.in_file')]), (segment, hmsk, [('tissue_class_map', 'inputnode.in_segm')]), (n4itk, measures, [('output_image', 'in_noinu')]), (arw, measures, [('outputnode.out_file', 'in_file')]), (arw, fwhm, [('outputnode.out_file', 'in_file')]), (asw, fwhm, [('outputnode.out_mask', 'mask')]), (arw, amw, [('outputnode.out_file', 'inputnode.in_file')]), (n4itk, amw, [('output_image', 'inputnode.in_noinu')]), (asw, amw, [('outputnode.out_mask', 'inputnode.in_mask')]), (hmsk, amw, [('outputnode.out_file', 'inputnode.head_mask')]), (amw, measures, [('outputnode.out_file', 'air_msk')]), (amw, measures, [('outputnode.artifact_msk', 'artifact_msk')]), (segment, measures, [('tissue_class_map', 'in_segm'), ('partial_volume_files', 'in_pvms')]), (n4itk, measures, [('bias_image', 'in_bias')]), (arw, plot, [('outputnode.out_file', 'in_file')]), (inputnode, plot, [('subject_id', 'subject')]), (inputnode, merg, [('session_id', 'in1'), ('run_id', 'in2')]), (merg, plot, [('out', 'metadata')]) ]) if settings.get('mask_mosaic', False): workflow.connect(asw, 'outputnode.out_file', plot, 'in_mask') # Save mosaic to well-formed path mvplot = pe.Node(niu.Rename( format_string='anatomical_%(subject_id)s_%(session_id)s_%(run_id)s', keep_ext=True), name='rename_plot') dsplot = pe.Node(nio.DataSink(base_directory=settings['work_dir'], parameterization=False), name='ds_plot') workflow.connect([(inputnode, mvplot, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (plot, mvplot, [('out_file', 'in_file')]), (mvplot, dsplot, [('out_file', '@mosaic')])]) # Save background-noise fitting plot mvbgplot = pe.Node(niu.Rename( format_string= 'anatomical_bgplot_%(subject_id)s_%(session_id)s_%(run_id)s', keep_ext=True), name='rename_bgplot') dsbgplot = pe.Node(nio.DataSink(base_directory=settings['work_dir'], parameterization=False), name='ds_bgplot') workflow.connect([(inputnode, mvbgplot, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (measures, mvbgplot, [('out_noisefit', 'in_file')]), (mvbgplot, dsbgplot, [('out_file', '@bg_fitting')])]) # Format name out_name = pe.Node(niu.Function( input_names=['subid', 'sesid', 'runid', 'prefix', 'out_path'], output_names=['out_file'], function=bids_path), name='FormatName') out_name.inputs.out_path = deriv_dir out_name.inputs.prefix = 'anat' # Save to JSON file jfs_if = nio.JSONFileSink() setattr(jfs_if, '_always_run', settings.get('force_run', False)) datasink = pe.Node(jfs_if, name='datasink') datasink.inputs.qc_type = 'anat' workflow.connect([(inputnode, out_name, [('subject_id', 'subid'), ('session_id', 'sesid'), ('run_id', 'runid')]), (inputnode, datasink, [('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (plot, datasink, [('out_file', 'mosaic_file')]), (fwhm, datasink, [(('fwhm', fwhm_dict), 'fwhm')]), (measures, datasink, [('summary', 'summary'), ('spacing', 'spacing'), ('size', 'size'), ('icvs', 'icvs'), ('rpve', 'rpve'), ('inu', 'inu'), ('snr', 'snr'), ('cnr', 'cnr'), ('fber', 'fber'), ('efc', 'efc'), ('qi1', 'qi1'), ('qi2', 'qi2'), ('cjv', 'cjv')]), (out_name, datasink, [('out_file', 'out_file')]), (datasink, outputnode, [('out_file', 'out_file')])]) return workflow