def init_tsnr_wf(name="tsnr"): """ create a workflow to calculate the temporal signal-to-noise ratio of a functional image :param name: workflow name (Default value = "tsnr") """ workflow = pe.Workflow(name=name) # only input is the bold image inputnode = pe.Node(niu.IdentityInterface(fields=["bold_file"]), name="inputnode") # output is an image file for display in the qualitycheck web page outputnode = pe.Node(niu.IdentityInterface(fields=["report_file"]), name="outputnode") # actually calculate the tsnr image tsnr = pe.Node(interface=nac.TSNR(), name="compute_tsnr") # plot the resulting image as a mosaic mosaic_stddev = pe.Node(interface=viz.PlotMosaic( out_file="plot_func_stddev_mosaic2_stddev.svg", cmap="viridis"), name="plot_mosaic") workflow.connect([(inputnode, tsnr, [("bold_file", "in_file")]), (tsnr, mosaic_stddev, [("tsnr_file", "in_file")]), (mosaic_stddev, outputnode, [("out_file", "report_file") ])]) return workflow
def create_moco_pipeline(name='motion_correction'): # initiate workflow moco = Workflow(name='motion_correction') # set fsl output fsl.FSLCommand.set_default_output_type('NIFTI_GZ') # inputnode inputnode = Node(util.IdentityInterface(fields=['epi']), name='inputnode') # outputnode outputnode = Node(util.IdentityInterface(fields=[ 'epi_moco', 'par_moco', 'mat_moco', 'rms_moco', 'epi_mean', 'rotplot', 'transplot', 'dispplots', 'tsnr_file' ]), name='outputnode') # mcflirt motion correction to 1st volume mcflirt = Node(fsl.MCFLIRT(save_mats=True, save_plots=True, save_rms=True, ref_vol=1, out_file='rest_realigned.nii.gz'), name='mcflirt') # plot motion parameters rotplotter = Node(fsl.PlotMotionParams(in_source='fsl', plot_type='rotations', out_file='rotation_plot.png'), name='rotplotter') transplotter = Node(fsl.PlotMotionParams(in_source='fsl', plot_type='translations', out_file='translation_plot.png'), name='transplotter') dispplotter = MapNode(interface=fsl.PlotMotionParams( in_source='fsl', plot_type='displacement', ), name='dispplotter', iterfield=['in_file']) dispplotter.iterables = ('plot_type', ['displacement']) # calculate tmean tmean = Node(fsl.maths.MeanImage(dimension='T', out_file='rest_realigned_mean.nii.gz'), name='tmean') # calculate tsnr tsnr = Node(confounds.TSNR(), name='tsnr') # create connections moco.connect([(inputnode, mcflirt, [('epi', 'in_file')]), (mcflirt, tmean, [('out_file', 'in_file')]), (mcflirt, rotplotter, [('par_file', 'in_file')]), (mcflirt, transplotter, [('par_file', 'in_file')]), (mcflirt, dispplotter, [('rms_files', 'in_file')]), (tmean, outputnode, [('out_file', 'epi_mean')]), (mcflirt, outputnode, [('out_file', 'epi_moco'), ('par_file', 'par_moco'), ('mat_file', 'mat_moco'), ('rms_files', 'rms_moco')]), (rotplotter, outputnode, [('out_file', 'rotplot')]), (transplotter, outputnode, [('out_file', 'transplot')]), (dispplotter, outputnode, [('out_file', 'dispplots')]), (mcflirt, tsnr, [('out_file', 'in_file')]), (tsnr, outputnode, [('tsnr_file', 'tsnr_file')])]) return moco
def init_atlasbasedconnectivity_wf( workdir: str | Path, feature=None, atlas_files=None, atlas_spaces=None, memcalc=MemoryCalculator.default(), ): """ create workflow for brainatlas """ if feature is not None: name = f"{format_workflow(feature.name)}_wf" else: name = "atlasbasedconnectivity_wf" workflow = pe.Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface(fields=[ "tags", "vals", "metadata", "bold", "mask", "repetition_time", "atlas_names", "atlas_files", "atlas_spaces", ]), name="inputnode", ) outputnode = pe.Node(niu.IdentityInterface(fields=["resultdicts"]), name="outputnode") min_region_coverage = 1 if feature is not None: inputnode.inputs.atlas_names = feature.atlases if hasattr(feature, "min_region_coverage"): min_region_coverage = feature.min_region_coverage if atlas_files is not None: inputnode.inputs.atlas_files = atlas_files if atlas_spaces is not None: inputnode.inputs.atlas_spaces = atlas_spaces # make_resultdicts = pe.Node( MakeResultdicts( tagkeys=["feature", "atlas"], imagekeys=[ "timeseries", "covariance_matrix", "correlation_matrix" ], metadatakeys=[ "sources", "sampling_frequency", "mean_atlas_tsnr", "coverage", ], nobroadcastkeys=["mean_atlas_tsnr", "coverage"], ), name="make_resultdicts", ) if feature is not None: make_resultdicts.inputs.feature = feature.name workflow.connect(inputnode, "tags", make_resultdicts, "tags") workflow.connect(inputnode, "vals", make_resultdicts, "vals") workflow.connect(inputnode, "metadata", make_resultdicts, "metadata") workflow.connect(inputnode, "atlas_names", make_resultdicts, "atlas") workflow.connect(inputnode, "repetition_time", make_resultdicts, "sampling_frequency") workflow.connect(make_resultdicts, "resultdicts", outputnode, "resultdicts") # resultdict_datasink = pe.Node(ResultdictDatasink(base_directory=workdir), name="resultdict_datasink") workflow.connect(make_resultdicts, "resultdicts", resultdict_datasink, "indicts") # reference_dict = dict(reference_space=constants.reference_space, reference_res=constants.reference_res) resample = pe.MapNode( Resample(interpolation="MultiLabel", **reference_dict), name="resample", iterfield=["input_image", "input_space"], mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "atlas_files", resample, "input_image") workflow.connect(inputnode, "atlas_spaces", resample, "input_space") # connectivitymeasure = pe.MapNode( ConnectivityMeasure(background_label=0, min_region_coverage=min_region_coverage), name="connectivitymeasure", iterfield=["atlas_file"], mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "bold", connectivitymeasure, "in_file") workflow.connect(inputnode, "mask", connectivitymeasure, "mask_file") workflow.connect(resample, "output_image", connectivitymeasure, "atlas_file") workflow.connect(connectivitymeasure, "time_series", make_resultdicts, "timeseries") workflow.connect(connectivitymeasure, "covariance", make_resultdicts, "covariance_matrix") workflow.connect(connectivitymeasure, "correlation", make_resultdicts, "correlation_matrix") workflow.connect(connectivitymeasure, "region_coverage", make_resultdicts, "coverage") # tsnr = pe.Node(interface=nac.TSNR(), name="tsnr", mem_gb=memcalc.series_std_gb) workflow.connect(inputnode, "bold", tsnr, "in_file") calcmean = pe.MapNode( CalcMean(), iterfield="parcellation", name="calcmean", mem_gb=memcalc.series_std_gb, ) workflow.connect(resample, "output_image", calcmean, "parcellation") workflow.connect(inputnode, "mask", calcmean, "mask") workflow.connect(tsnr, "tsnr_file", calcmean, "in_file") workflow.connect(calcmean, "mean", make_resultdicts, "mean_atlas_tsnr") return workflow
def init_dualregression_wf(workdir=None, feature=None, map_files=None, map_spaces=None, memcalc=MemoryCalculator()): """ create a workflow to calculate dual regression for ICA seeds """ if feature is not None: name = f"{formatlikebids(feature.name)}_wf" else: name = "dualregression_wf" workflow = pe.Workflow(name=name) # input inputnode = pe.Node( niu.IdentityInterface(fields=[ "tags", "vals", "metadata", "bold", "mask", "confounds_selected", "map_names", "map_files", "map_spaces", ]), name="inputnode", ) outputnode = pe.Node(niu.IdentityInterface(fields=["resultdicts"]), name="outputnode") if feature is not None: inputnode.inputs.map_names = feature.maps if map_files is not None: inputnode.inputs.map_files = map_files if map_spaces is not None: inputnode.inputs.map_spaces = map_spaces # statmaps = ["effect", "variance", "z", "dof", "mask"] make_resultdicts_a = pe.Node( MakeResultdicts(tagkeys=["feature", "map"], imagekeys=["design_matrix", "contrast_matrix"]), name="make_resultdicts_a", ) if feature is not None: make_resultdicts_a.inputs.feature = feature.name workflow.connect(inputnode, "tags", make_resultdicts_a, "tags") workflow.connect(inputnode, "vals", make_resultdicts_a, "vals") workflow.connect(inputnode, "metadata", make_resultdicts_a, "metadata") workflow.connect(inputnode, "map_names", make_resultdicts_a, "map") make_resultdicts_b = pe.Node( MakeResultdicts( tagkeys=["feature", "map", "component"], imagekeys=statmaps, metadatakeys=["sources", "mean_t_s_n_r"], ), name="make_resultdicts_b", ) if feature is not None: make_resultdicts_b.inputs.feature = feature.name workflow.connect(inputnode, "tags", make_resultdicts_b, "tags") workflow.connect(inputnode, "vals", make_resultdicts_b, "vals") workflow.connect(inputnode, "metadata", make_resultdicts_b, "metadata") workflow.connect(inputnode, "map_names", make_resultdicts_b, "map") workflow.connect(inputnode, "mask", make_resultdicts_b, "mask") workflow.connect(make_resultdicts_b, "resultdicts", outputnode, "resultdicts") # merge_resultdicts = pe.Node(niu.Merge(2), name="merge_resultdicts") workflow.connect(make_resultdicts_a, "resultdicts", merge_resultdicts, "in1") workflow.connect(make_resultdicts_b, "resultdicts", merge_resultdicts, "in2") resultdict_datasink = pe.Node(ResultdictDatasink(base_directory=workdir), name="resultdict_datasink") workflow.connect(merge_resultdicts, "out", resultdict_datasink, "indicts") # reference_dict = dict(reference_space=constants.reference_space, reference_res=constants.reference_res) resample = pe.MapNode( Resample(interpolation="LanczosWindowedSinc", **reference_dict), name="resample", iterfield=["input_image", "input_space"], n_procs=config.nipype.omp_nthreads, mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "map_files", resample, "input_image") workflow.connect(inputnode, "map_spaces", resample, "input_space") # Delete zero voxels for the maps applymask = pe.MapNode( fsl.ApplyMask(), name="applymask", iterfield="in_file", mem_gb=memcalc.volume_std_gb, ) workflow.connect(inputnode, "mask", applymask, "mask_file") workflow.connect(resample, "output_image", applymask, "in_file") # first step, calculate spatial regression of ICA components on to the # bold file spatialglm = pe.MapNode( fsl.GLM(out_file="beta", demean=True), name="spatialglm", iterfield="design", mem_gb=memcalc.series_std_gb * 5, ) workflow.connect(applymask, "out_file", spatialglm, "design") workflow.connect(inputnode, "bold", spatialglm, "in_file") workflow.connect(inputnode, "mask", spatialglm, "mask") # second step, calculate the temporal regression of the time series # from the first step on to the bold file contrasts = pe.MapNode( niu.Function( input_names=["map_timeseries_file", "confounds_file"], output_names=[ "out_with_header", "out_no_header", "map_component_names" ], function=_contrasts, ), iterfield="map_timeseries_file", name="contrasts", ) workflow.connect(spatialglm, "out_file", contrasts, "map_timeseries_file") workflow.connect(inputnode, "confounds_selected", contrasts, "confounds_file") workflow.connect(contrasts, "out_with_header", make_resultdicts_a, "contrast_matrix") workflow.connect(contrasts, "map_component_names", make_resultdicts_b, "component") design = pe.MapNode(MergeColumns(2), iterfield=["in1", "column_names1"], name="design") workflow.connect(spatialglm, "out_file", design, "in1") workflow.connect(contrasts, "map_component_names", design, "column_names1") workflow.connect(inputnode, "confounds_selected", design, "in2") workflow.connect(design, "out_with_header", make_resultdicts_a, "design_matrix") fillna = pe.MapNode(FillNA(), iterfield="in_tsv", name="fillna") workflow.connect(design, "out_no_header", fillna, "in_tsv") temporalglm = pe.MapNode( fsl.GLM( out_file="beta.nii.gz", out_cope="cope.nii.gz", out_varcb_name="varcope.nii.gz", out_z_name="zstat.nii.gz", demean=True, ), name="temporalglm", iterfield=["design", "contrasts"], mem_gb=memcalc.series_std_gb * 5, ) workflow.connect(inputnode, "bold", temporalglm, "in_file") workflow.connect(inputnode, "mask", temporalglm, "mask") workflow.connect(fillna, "out_no_header", temporalglm, "design") workflow.connect(contrasts, "out_no_header", temporalglm, "contrasts") # make dof volume makedofvolume = pe.MapNode( MakeDofVolume(), iterfield=["design"], name="makedofvolume", ) workflow.connect(inputnode, "bold", makedofvolume, "bold_file") workflow.connect(fillna, "out_no_header", makedofvolume, "design") for glmattr, resultattr in (("cope", "effect"), ("varcb", "variance"), ("z", "z")): split = pe.MapNode(fsl.Split(dimension="t"), iterfield="in_file", name=f"split{resultattr}images") workflow.connect(temporalglm, f"out_{glmattr}", split, "in_file") workflow.connect(split, "out_files", make_resultdicts_b, resultattr) workflow.connect(makedofvolume, "out_file", make_resultdicts_b, "dof") # tsnr = pe.Node(nac.TSNR(), name="tsnr", mem_gb=memcalc.series_std_gb) workflow.connect(inputnode, "bold", tsnr, "in_file") maxintensity = pe.MapNode(MaxIntensity(), iterfield="in_file", name="maxintensity", mem_gb=memcalc.series_std_gb) workflow.connect(resample, "output_image", maxintensity, "in_file") calcmean = pe.MapNode(CalcMean(), iterfield="parcellation", name="calcmean", mem_gb=memcalc.series_std_gb) workflow.connect(maxintensity, "out_file", calcmean, "parcellation") workflow.connect(tsnr, "tsnr_file", calcmean, "in_file") workflow.connect(calcmean, "mean", make_resultdicts_b, "mean_t_s_n_r") return workflow
def fmri_qc_workflow(name='fMRIQC', settings=None): """ The fMRI qc workflow """ 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) # Read FD radius, or default it fd_radius = settings.get('fd_radius', 50.) # Define workflow, inputs and outputs inputnode = pe.Node(niu.IdentityInterface(fields=[ 'bids_dir', 'subject_id', 'session_id', 'run_id', 'site_name', 'start_idx', 'stop_idx' ]), name='inputnode') get_idx = pe.Node(niu.Function( input_names=['in_file', 'start_idx', 'stop_idx'], function=fmri_getidx, output_names=['start_idx', 'stop_idx']), name='get_idx') outputnode = pe.Node(niu.IdentityInterface(fields=[ 'qc', 'mosaic', 'out_group', 'out_movpar', 'out_dvars', 'out_fd' ]), name='outputnode') # 0. Get data datasource = pe.Node(niu.Function(input_names=[ 'bids_dir', 'data_type', 'subject_id', 'session_id', 'run_id' ], output_names=['out_file'], function=bids_getfile), name='datasource') datasource.inputs.data_type = 'func' # Workflow -------------------------------------------------------- # 1. HMC: head motion correct hmcwf = hmc_mcflirt() if settings.get('hmc_afni', False): hmcwf = hmc_afni( st_correct=settings.get('correct_slice_timing', False)) hmcwf.inputs.inputnode.fd_radius = fd_radius mean = pe.Node( afp.TStat( # 2. Compute mean fmri options='-mean', outputtype='NIFTI_GZ'), name='mean') bmw = fmri_bmsk_workflow( # 3. Compute brain mask use_bet=settings.get('use_bet', False)) # Compute TSNR using nipype implementation tsnr = pe.Node(nac.TSNR(), name='compute_tsnr') # Compute DVARS dvnode = pe.Node(nac.ComputeDVARS(remove_zerovariance=True, save_plot=True, save_all=True, figdpi=200, figformat='pdf'), name='ComputeDVARS') fdnode = pe.Node(nac.FramewiseDisplacement(normalize=True, save_plot=True, radius=fd_radius, figdpi=200), name='ComputeFD') # AFNI quality measures fwhm = pe.Node(afp.FWHMx(combine=True, detrend=True), name='smoothness') # fwhm.inputs.acf = True # add when AFNI >= 16 outliers = pe.Node(afp.OutlierCount(fraction=True, out_file='ouliers.out'), name='outliers') quality = pe.Node(afp.QualityIndex(automask=True), out_file='quality.out', name='quality') measures = pe.Node(FunctionalQC(), name='measures') # Link images that should be reported dsreport = pe.Node(nio.DataSink(base_directory=settings['report_dir'], parameterization=True), name='dsreport') dsreport.inputs.container = 'func' dsreport.inputs.substitutions = [ ('_data', ''), ('fd_power_2012', 'plot_fd'), ('tsnr.nii.gz', 'mosaic_TSNR.nii.gz'), ('mean.nii.gz', 'mosaic_TSNR_mean.nii.gz'), ('stdev.nii.gz', 'mosaic_TSNR_stdev.nii.gz') ] dsreport.inputs.regexp_substitutions = [ ('_u?(sub-[\\w\\d]*)\\.([\\w\\d_]*)(?:\\.([\\w\\d_-]*))+', '\\1_ses-\\2_\\3'), ('sub-[^/.]*_dvars_std', 'plot_dvars'), ('sub-[^/.]*_mask', 'mask'), ('sub-[^/.]*_mcf_tstat', 'mosaic_epi_mean') ] workflow.connect([ (inputnode, datasource, [('bids_dir', 'bids_dir'), ('subject_id', 'subject_id'), ('session_id', 'session_id'), ('run_id', 'run_id')]), (inputnode, get_idx, [('start_idx', 'start_idx'), ('stop_idx', 'stop_idx')]), (datasource, get_idx, [('out_file', 'in_file')]), (datasource, hmcwf, [('out_file', 'inputnode.in_file')]), (get_idx, hmcwf, [('start_idx', 'inputnode.start_idx'), ('stop_idx', 'inputnode.stop_idx')]), (hmcwf, bmw, [('outputnode.out_file', 'inputnode.in_file')]), (hmcwf, mean, [('outputnode.out_file', 'in_file')]), (hmcwf, tsnr, [('outputnode.out_file', 'in_file')]), (hmcwf, fdnode, [('outputnode.out_movpar', 'in_plots')]), (mean, fwhm, [('out_file', 'in_file')]), (bmw, fwhm, [('outputnode.out_file', 'mask')]), (hmcwf, outliers, [('outputnode.out_file', 'in_file')]), (bmw, outliers, [('outputnode.out_file', 'mask')]), (hmcwf, quality, [('outputnode.out_file', 'in_file')]), (hmcwf, dvnode, [('outputnode.out_file', 'in_file')]), (bmw, dvnode, [('outputnode.out_file', 'in_mask')]), (mean, measures, [('out_file', 'in_epi')]), (hmcwf, measures, [('outputnode.out_file', 'in_hmc')]), (bmw, measures, [('outputnode.out_file', 'in_mask')]), (tsnr, measures, [('tsnr_file', 'in_tsnr')]), (dvnode, measures, [('out_all', 'in_dvars')]), (fdnode, measures, [('out_file', 'in_fd')]), (fdnode, outputnode, [('out_file', 'out_fd')]), (dvnode, outputnode, [('out_all', 'out_dvars')]), (hmcwf, outputnode, [('outputnode.out_movpar', 'out_movpar')]), (mean, dsreport, [('out_file', '@meanepi')]), (tsnr, dsreport, [('tsnr_file', '@tsnr'), ('stddev_file', '@tsnr_std'), ('mean_file', '@tsnr_mean')]), (bmw, dsreport, [('outputnode.out_file', '@mask')]), (fdnode, dsreport, [('out_figure', '@fdplot')]), (dvnode, dsreport, [('fig_std', '@dvars')]), ]) # 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 = 'func' # Save to JSON file datasink = pe.Node(nio.JSONFileSink(), name='datasink') datasink.inputs.qc_type = 'func' 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')]), (outliers, datasink, [(('out_file', _parse_tout), 'outlier')]), (quality, datasink, [(('out_file', _parse_tqual), 'quality')]), (measures, datasink, [('summary', 'summary'), ('spacing', 'spacing'), ('size', 'size'), ('fber', 'fber'), ('efc', 'efc'), ('snr', 'snr'), ('gsr', 'gsr'), ('m_tsnr', 'm_tsnr'), ('fd', 'fd'), ('dvars', 'dvars'), ('gcor', 'gcor')]), (out_name, datasink, [('out_file', 'out_file')]), (datasink, outputnode, [('out_file', 'out_file')]) ]) return workflow
def init_seedbasedconnectivity_wf(workdir=None, feature=None, seed_files=None, seed_spaces=None, memcalc=MemoryCalculator()): """ create workflow to calculate seed connectivity maps """ if feature is not None: name = f"{formatlikebids(feature.name)}_wf" else: name = "seedbasedconnectivity_wf" workflow = pe.Workflow(name=name) # input inputnode = pe.Node( niu.IdentityInterface(fields=[ "tags", "vals", "metadata", "bold", "mask", "confounds_selected", "seed_names", "seed_files", "seed_spaces", ]), name="inputnode", ) outputnode = pe.Node(niu.IdentityInterface(fields=["resultdicts"]), name="outputnode") min_seed_coverage = 1 if feature is not None: inputnode.inputs.seed_names = feature.seeds if hasattr(feature, "min_seed_coverage"): min_seed_coverage = feature.min_seed_coverage if seed_files is not None: inputnode.inputs.seed_files = seed_files if seed_spaces is not None: inputnode.inputs.seed_spaces = seed_spaces # statmaps = ["effect", "variance", "z", "dof", "mask"] make_resultdicts = pe.Node( MakeResultdicts( tagkeys=["feature", "seed"], imagekeys=[*statmaps, "design_matrix", "contrast_matrix"], metadatakeys=["mean_t_s_n_r", "coverage"], ), name="make_resultdicts", ) if feature is not None: make_resultdicts.inputs.feature = feature.name workflow.connect(inputnode, "tags", make_resultdicts, "tags") workflow.connect(inputnode, "vals", make_resultdicts, "vals") workflow.connect(inputnode, "metadata", make_resultdicts, "metadata") workflow.connect(inputnode, "mask", make_resultdicts, "mask") workflow.connect(make_resultdicts, "resultdicts", outputnode, "resultdicts") # resultdict_datasink = pe.Node(ResultdictDatasink(base_directory=workdir), name="resultdict_datasink") workflow.connect(make_resultdicts, "resultdicts", resultdict_datasink, "indicts") # reference_dict = dict(reference_space=constants.reference_space, reference_res=constants.reference_res) resample = pe.MapNode( Resample(interpolation="MultiLabel", **reference_dict), name="resample", iterfield=["input_image", "input_space"], n_procs=config.nipype.omp_nthreads, mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "seed_files", resample, "input_image") workflow.connect(inputnode, "seed_spaces", resample, "input_space") # Delete zero voxels for the seeds maskseeds = pe.Node( MaskCoverage(keys=["names"], min_coverage=min_seed_coverage), name="maskseeds", mem_gb=memcalc.volume_std_gb, ) workflow.connect(inputnode, "mask", maskseeds, "mask_file") workflow.connect(inputnode, "seed_names", maskseeds, "names") workflow.connect(resample, "output_image", maskseeds, "in_files") workflow.connect(maskseeds, "names", make_resultdicts, "seed") workflow.connect(maskseeds, "coverage", make_resultdicts, "coverage") # calculate the mean time series of the region defined by each mask meants = pe.MapNode( fsl.ImageMeants(), name="meants", iterfield="mask", mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "bold", meants, "in_file") workflow.connect(maskseeds, "out_files", meants, "mask") # design = pe.MapNode(MergeColumns(2), iterfield=["in1", "column_names1"], name="design") workflow.connect(meants, "out_file", design, "in1") workflow.connect(maskseeds, "names", design, "column_names1") workflow.connect(inputnode, "confounds_selected", design, "in2") workflow.connect(design, "out_with_header", make_resultdicts, "design_matrix") contrasts = pe.MapNode( niu.Function( input_names=["design_file"], output_names=["out_with_header", "out_no_header"], function=_contrasts, ), iterfield="design_file", name="contrasts", ) workflow.connect(design, "out_with_header", contrasts, "design_file") workflow.connect(contrasts, "out_with_header", make_resultdicts, "contrast_matrix") fillna = pe.MapNode(FillNA(), iterfield="in_tsv", name="fillna") workflow.connect(design, "out_no_header", fillna, "in_tsv") # calculate the regression of the mean time series # onto the functional image. # the result is the seed connectivity map glm = pe.MapNode( fsl.GLM( out_file="beta.nii.gz", out_cope="cope.nii.gz", out_varcb_name="varcope.nii.gz", out_z_name="zstat.nii.gz", demean=True, ), name="glm", iterfield=["design", "contrasts"], mem_gb=memcalc.series_std_gb * 5, ) workflow.connect(inputnode, "bold", glm, "in_file") workflow.connect(inputnode, "mask", glm, "mask") workflow.connect(fillna, "out_no_header", glm, "design") workflow.connect(contrasts, "out_no_header", glm, "contrasts") # make dof volume makedofvolume = pe.MapNode(MakeDofVolume(), iterfield=["design"], name="makedofvolume") workflow.connect(inputnode, "bold", makedofvolume, "bold_file") workflow.connect(fillna, "out_no_header", makedofvolume, "design") workflow.connect(glm, "out_cope", make_resultdicts, "effect") workflow.connect(glm, "out_varcb", make_resultdicts, "variance") workflow.connect(glm, "out_z", make_resultdicts, "z") workflow.connect(makedofvolume, "out_file", make_resultdicts, "dof") # tsnr = pe.Node(nac.TSNR(), name="tsnr", mem_gb=memcalc.series_std_gb) workflow.connect(inputnode, "bold", tsnr, "in_file") calcmean = pe.MapNode(CalcMean(), iterfield="mask", name="calcmean", mem_gb=memcalc.series_std_gb) workflow.connect(maskseeds, "out_files", calcmean, "mask") workflow.connect(tsnr, "tsnr_file", calcmean, "in_file") workflow.connect(calcmean, "mean", make_resultdicts, "mean_t_s_n_r") return workflow
def fmri_qc_workflow(dataset, settings, name='funcMRIQC'): """ The fMRI qc workflow .. workflow:: import os.path as op from mriqc.workflows.functional import fmri_qc_workflow datadir = op.abspath('data') wf = fmri_qc_workflow([op.join(datadir, 'sub-001/func/sub-001_task-rest_bold.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out'), 'no_sub': True}) """ workflow = pe.Workflow(name=name) biggest_file_gb = settings.get("biggest_file_size_gb", 1) # Define workflow, inputs and outputs # 0. Get data, put it in RAS orientation inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') WFLOGGER.info('Building fMRI QC workflow, datasets list: %s', [str(Path(d).relative_to(settings['bids_dir'])) for d in sorted(dataset)]) inputnode.iterables = [('in_file', dataset)] outputnode = pe.Node(niu.IdentityInterface( fields=['qc', 'mosaic', 'out_group', 'out_dvars', 'out_fd']), name='outputnode') non_steady_state_detector = pe.Node(nac.NonSteadyStateDetector(), name="non_steady_state_detector") sanitize = pe.Node(niutils.SanitizeImage(), name="sanitize", mem_gb=biggest_file_gb * 4.0) sanitize.inputs.max_32bit = settings.get("float32", DEFAULTS['float32']) # Workflow -------------------------------------------------------- # 1. HMC: head motion correct if settings.get('hmc_fsl', False): hmcwf = hmc_mcflirt(settings) else: hmcwf = hmc_afni(settings, st_correct=settings.get('correct_slice_timing', False), despike=settings.get('despike', False), deoblique=settings.get('deoblique', False), start_idx=settings.get('start_idx', None), stop_idx=settings.get('stop_idx', None)) # Set HMC settings hmcwf.inputs.inputnode.fd_radius = settings.get('fd_radius', DEFAULT_FD_RADIUS) mean = pe.Node(afni.TStat( # 2. Compute mean fmri options='-mean', outputtype='NIFTI_GZ'), name='mean', mem_gb=biggest_file_gb * 1.5) skullstrip_epi = fmri_bmsk_workflow(use_bet=True) # EPI to MNI registration ema = epi_mni_align(settings) # Compute TSNR using nipype implementation tsnr = pe.Node(nac.TSNR(), name='compute_tsnr', mem_gb=biggest_file_gb * 2.5) # 7. Compute IQMs iqmswf = compute_iqms(settings) # Reports repwf = individual_reports(settings) workflow.connect([ (inputnode, iqmswf, [('in_file', 'inputnode.in_file')]), (inputnode, sanitize, [('in_file', 'in_file')]), (inputnode, non_steady_state_detector, [('in_file', 'in_file')]), (non_steady_state_detector, sanitize, [('n_volumes_to_discard', 'n_volumes_to_discard')]), (sanitize, hmcwf, [('out_file', 'inputnode.in_file')]), (mean, skullstrip_epi, [('out_file', 'inputnode.in_file')]), (hmcwf, mean, [('outputnode.out_file', 'in_file')]), (hmcwf, tsnr, [('outputnode.out_file', 'in_file')]), (mean, ema, [('out_file', 'inputnode.epi_mean')]), (skullstrip_epi, ema, [('outputnode.out_file', 'inputnode.epi_mask')]), (sanitize, iqmswf, [('out_file', 'inputnode.in_ras')]), (mean, iqmswf, [('out_file', 'inputnode.epi_mean')]), (hmcwf, iqmswf, [('outputnode.out_file', 'inputnode.hmc_epi'), ('outputnode.out_fd', 'inputnode.hmc_fd')]), (skullstrip_epi, iqmswf, [('outputnode.out_file', 'inputnode.brainmask')]), (tsnr, iqmswf, [('tsnr_file', 'inputnode.in_tsnr')]), (sanitize, repwf, [('out_file', 'inputnode.in_ras')]), (mean, repwf, [('out_file', 'inputnode.epi_mean')]), (tsnr, repwf, [('stddev_file', 'inputnode.in_stddev')]), (skullstrip_epi, repwf, [('outputnode.out_file', 'inputnode.brainmask')]), (hmcwf, repwf, [('outputnode.out_fd', 'inputnode.hmc_fd'), ('outputnode.out_file', 'inputnode.hmc_epi')]), (ema, repwf, [('outputnode.epi_parc', 'inputnode.epi_parc'), ('outputnode.report', 'inputnode.mni_report')]), (non_steady_state_detector, iqmswf, [('n_volumes_to_discard', 'inputnode.exclude_index')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms'), ('outputnode.out_dvars', 'inputnode.in_dvars'), ('outputnode.outliers', 'inputnode.outliers')]), (hmcwf, outputnode, [('outputnode.out_fd', 'out_fd')]), ]) if settings.get('fft_spikes_detector', False): workflow.connect([ (iqmswf, repwf, [('outputnode.out_spikes', 'inputnode.in_spikes'), ('outputnode.out_fft', 'inputnode.in_fft')]), ]) if settings.get('ica', False): melodic = pe.Node(nws.MELODICRPT(no_bet=True, no_mask=True, no_mm=True, compress_report=False, generate_report=True), name="ICA", mem_gb=max(biggest_file_gb * 5, 8)) workflow.connect([ (sanitize, melodic, [('out_file', 'in_files')]), (skullstrip_epi, melodic, [('outputnode.out_file', 'report_mask')]), (melodic, repwf, [('out_report', 'inputnode.ica_report')]) ]) # Upload metrics if not settings.get('no_sub', False): from ..interfaces.webapi import UploadIQMs upldwf = pe.Node(UploadIQMs(), name='UploadMetrics') upldwf.inputs.url = settings.get('webapi_url') if settings.get('webapi_port'): upldwf.inputs.port = settings.get('webapi_port') upldwf.inputs.email = settings.get('email') upldwf.inputs.strict = settings.get('upload_strict', False) workflow.connect([ (iqmswf, upldwf, [('outputnode.out_file', 'in_iqms')]), ]) return workflow
def create_resting_preproc(name='restpreproc', base_dir=None): """Create a "resting" time series preprocessing workflow The noise removal is based on Behzadi et al. (2007) Parameters ---------- name : name of workflow (default: restpreproc) Inputs:: inputspec.func : functional run (filename or list of filenames) Outputs:: outputspec.noise_mask_file : voxels used for PCA to derive noise components outputspec.filtered_file : bandpass filtered and noise-reduced time series Example ------- >>> TR = 3.0 >>> wf = create_resting_preproc() >>> wf.inputs.inputspec.func = 'f3.nii' >>> wf.inputs.inputspec.num_noise_components = 6 >>> wf.inputs.inputspec.highpass_sigma = 100/(2*TR) >>> wf.inputs.inputspec.lowpass_sigma = 12.5/(2*TR) >>> wf.run() # doctest: +SKIP """ restpreproc = pe.Workflow(name=name, base_dir=base_dir) # Define nodes inputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'func', 'num_noise_components', 'highpass_sigma', 'lowpass_sigma' ]), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'noise_mask_file', 'filtered_file', ]), name='outputspec') slicetimer = pe.Node(fsl.SliceTimer(), name='slicetimer') realigner = create_realign_flow() tsnr = pe.Node(confounds.TSNR(regress_poly=2), name='tsnr') getthresh = pe.Node(interface=fsl.ImageStats(op_string='-p 98'), name='getthreshold') threshold_stddev = pe.Node(fsl.Threshold(), name='threshold') compcor = pe.Node(confounds.ACompCor( components_file="noise_components.txt", pre_filter=False), name='compcor') remove_noise = pe.Node(fsl.FilterRegressor(filter_all=True), name='remove_noise') bandpass_filter = pe.Node(fsl.TemporalFilter(), name='bandpass_filter') # Define connections restpreproc.connect(inputnode, 'func', slicetimer, 'in_file') restpreproc.connect(slicetimer, 'slice_time_corrected_file', realigner, 'inputspec.func') restpreproc.connect(realigner, 'outputspec.realigned_file', tsnr, 'in_file') restpreproc.connect(tsnr, 'stddev_file', threshold_stddev, 'in_file') restpreproc.connect(tsnr, 'stddev_file', getthresh, 'in_file') restpreproc.connect(getthresh, 'out_stat', threshold_stddev, 'thresh') restpreproc.connect(realigner, 'outputspec.realigned_file', compcor, 'realigned_file') restpreproc.connect(threshold_stddev, 'out_file', compcor, 'mask_files') restpreproc.connect(inputnode, 'num_noise_components', compcor, 'num_components') restpreproc.connect(tsnr, 'detrended_file', remove_noise, 'in_file') restpreproc.connect(compcor, 'components_file', remove_noise, 'design_file') restpreproc.connect(inputnode, 'highpass_sigma', bandpass_filter, 'highpass_sigma') restpreproc.connect(inputnode, 'lowpass_sigma', bandpass_filter, 'lowpass_sigma') restpreproc.connect(remove_noise, 'out_file', bandpass_filter, 'in_file') restpreproc.connect(threshold_stddev, 'out_file', outputnode, 'noise_mask_file') restpreproc.connect(bandpass_filter, 'out_file', outputnode, 'filtered_file') return restpreproc
'in_file2') preproc_wf.connect(maskfunc2, 'out_file', outputspec, 'susan_sm{0}_files'.format(kernel)) # Temporal smoothing for SUSAN-smoothed data # FSL bandpass fsl_bandpass = pe.MapNode(fsl.ImageMaths(suffix='_tempfilt'), iterfield=['in_file'], name='fsl_bp_susan_sm{0}_'.format(kernel)) preproc_wf.connect(determine_bp_sigmas, ('out_sigmas', highpass_operand), fsl_bandpass, 'op_string') preproc_wf.connect(maskfunc2, 'out_file', fsl_bandpass, 'in_file') preproc_wf.connect(fsl_bandpass, 'out_file', outputspec, 'fsl_bp_susan_sm{0}_files'.format(kernel)) tsnr = pe.MapNode(conf.TSNR(), iterfield=['in_file'], name='fsl_bp_susan_sm{0}_tsnr_'.format(kernel)) preproc_wf.connect(fsl_bandpass, 'out_file', tsnr, 'in_file') preproc_wf.connect(tsnr, 'tsnr_file', outputspec, 'fsl_bp_susan_sm{0}_tsnr_files'.format(kernel)) # AFNI bandpass afni_detrend = pe.MapNode(afni.Detrend(outputtype='NIFTI_GZ', args='-polort 4'), iterfield=['in_file'], name='afni_bp_susan_sm{0}_'.format(kernel)) preproc_wf.connect(maskfunc2, 'out_file', afni_detrend, 'in_file') preproc_wf.connect(afni_detrend, 'out_file', outputspec, 'afni_bp_susan_sm{0}_files'.format(kernel))
despike=Node(afni.Despike(),name='despike') despike.inputs.outputtype='NIFTI' #Outputs: out_file #Slice timing corrected (gets timing from header) st_corr=Node(spm.SliceTiming(),name='slicetiming_correction') st_corr.inputs.ref_slice=1 #Outputs: timecorrected_files #Realignment using SPM <--- Maybe just estimate and apply all transforms at the end? realign=Node(spm.Realign(),name='realign') realign.inputs.register_to_mean=False realign.inputs.quality=1.0 #Outputs: realignment_parameters, reliced epi images (motion corrected) tsnr = Node(confounds.TSNR(),name = 'tsnr') tsnr.inputs.regress_poly = 2 #Note: This removes linear + constant drifts from the epi time series. Compcor removes from the wm / csf tsnr.inputs.mean_file = 'mean.nii' tsnr.inputs.stddev_file = 'stdev.nii' tsnr.inputs.tsnr_file = 'tsnr.nii' #Outputs: detrended_file, mean_file, stddev_file, tsnr_file smooth=Node(spm.Smooth(),name='smooth') smooth.inputs.fwhm=fwhm ####Anatomical preprocessing#### #dcmstack - Convert dicoms to nii (with embeded metadata)
def init_func_report_wf(workdir=None, name="func_report_wf", memcalc=MemoryCalculator()): """ """ workflow = pe.Workflow(name=name) # only input is the bold image inputnode = pe.Node( niu.IdentityInterface(fields=[ *func_in_attrs_from_anat_preproc_wf, *in_attrs_from_func_preproc_wf, *in_attrs_from_filt_wf, "metadata", ]), name="inputnode", ) # output is an image file for display in the qualitycheck web page outputnode = pe.Node(niu.IdentityInterface(fields=["metadata"]), name="outputnode") # EPI->mni epi_norm_rpt = pe.Node( PlotRegistration(template=config.workflow.spaces.get_spaces()[0]), name="epi_norm_rpt", mem_gb=0.1, ) workflow.connect([( inputnode, epi_norm_rpt, [("bold_std_ref", "in_file"), ("bold_mask_std", "mask_file")], )]) # calculate the tsnr image tsnr = pe.Node(interface=nac.TSNR(), name="compute_tsnr", mem_gb=memcalc.series_std_gb) workflow.connect([(inputnode, tsnr, [("bold_std", "in_file")])]) # plot the tsnr image tsnr_rpt = pe.Node(interface=PlotEpi(), name="tsnr_rpt", mem_gb=memcalc.min_gb) workflow.connect([ (inputnode, tsnr_rpt, [("bold_mask_std", "mask_file")]), (tsnr, tsnr_rpt, [("tsnr_file", "in_file")]), ]) # reportnode mergereport = pe.Node( interface=niu.Merge(2), name="mergereport", run_without_submitting=True, ) workflow.connect(epi_norm_rpt, "out_report", mergereport, "in1") workflow.connect(tsnr_rpt, "out_report", mergereport, "in2") reportnode = pe.Node(interface=MakeResultdicts(keys=["desc", "report"]), name="reportnode") reportnode.inputs.desc = ["epi_norm_rpt", "tsnr_rpt"] workflow.connect(inputnode, "metadata", reportnode, "basedict") workflow.connect(mergereport, "out", reportnode, "report") # metrics resampleifneeded = pe.Node( interface=ResampleIfNeeded(method="nearest"), name="resampleifneeded", mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "std_dseg", resampleifneeded, "in_file") workflow.connect(inputnode, "bold_std", resampleifneeded, "ref_file") reportmetadata = pe.Node(interface=BoldFileReportMetadata(), name="reportmetadata", mem_gb=memcalc.series_std_gb) workflow.connect(inputnode, "metadata", reportmetadata, "basedict") workflow.connect(inputnode, "out3", reportmetadata, "confounds") workflow.connect(tsnr, "tsnr_file", reportmetadata, "tsnr_file") workflow.connect(inputnode, "aroma_metadata", reportmetadata, "aroma_metadata") workflow.connect(resampleifneeded, "out_file", reportmetadata, "dseg") workflow.connect(reportmetadata, "outdict", outputnode, "metadata") assert workdir is not None make_reportnode_datasink(workflow, workdir) return workflow
def generate_plots(tedana_dir, out_dir=None): # TEDPCA comptable_file = op.join(tedana_dir, 'comp_table_pca.txt') comptable = pd.read_csv(comptable_file, sep='\t') fig, ax = plot_spectra(comptable) fig.savefig(op.join(out_dir, 'tedpca_metrics.png'), dpi=400) # TEDICA comptable_file = op.join(tedana_dir, 'comp_table_ica.txt') comptable = pd.read_csv(comptable_file, sep='\t') fig, ax = plot_spectra(comptable) fig.savefig(op.join(out_dir, 'tedica_metrics.png'), dpi=400) # T2* f = op.join(tedana_dir, 't2sv.nii') m = compute_epi_mask(f).get_data() fig, ax = plot_image(f, vmin=0, vmax=100) fig.savefig(op.join(out_dir, 't2s.png'), dpi=400) # S0 f = op.join(tedana_dir, 's0v.nii') fig, ax = plot_image(f) fig.savefig(op.join(out_dir, 's0.png'), dpi=400) # OC f = op.join(tedana_dir, 'ts_OC.nii') # OC TSNR tsnr = nac.TSNR() tsnr.inputs.in_file = f res = tsnr.run() fig, ax = plot_image(res.outputs.tsnr_file) fig.savefig(op.join(out_dir, 'optcom_tsnr.png'), dpi=400) # OC Carpet fig, ax = plt.subplots(figsize=(16, 6)) plots.plot_carpet(f, m, subplot=ax) fig.savefig(op.join(out_dir, 'optcom_carpet.png'), dpi=400) # MEDN f = op.join(tedana_dir, 'dn_ts_OC.nii') img = nib.load(f) # MEDN TSNR tsnr = nac.TSNR() tsnr.inputs.in_file = f res = tsnr.run() fig, ax = plot_image(res.outputs.tsnr_file) fig.savefig(op.join(out_dir, 'medn_tsnr.png'), dpi=400) # MEDN STD data = img.get_data() data = np.std(data, axis=-1) img2 = nib.Nifti1Image(data, img.affine) fig, ax = plot_image(img2) fig.savefig(op.join(out_dir, 'medn_std.png'), dpi=400) # MEDN Mean data = img.get_data() data = np.mean(data, axis=-1) img2 = nib.Nifti1Image(data, img.affine) fig, ax = plot_anatomical(img2) fig.savefig(op.join(out_dir, 'medn_mean.png'), dpi=400) # MEDN Carpet fig, ax = plt.subplots(figsize=(16, 6)) plots.plot_carpet(f, m, subplot=ax) fig.savefig(op.join(out_dir, 'medn_carpet.png'), dpi=400) # Cleanup remove(res.outputs.mean_file) remove(res.outputs.stddev_file) remove(res.outputs.tsnr_file)
#Generic datagrabber module that wraps around glob in an io_S3DataGrabber = pe.Node(io.S3DataGrabber(outfields=["outfiles"]), name='io_S3DataGrabber') io_S3DataGrabber.inputs.bucket = 'openneuro' io_S3DataGrabber.inputs.sort_filelist = True io_S3DataGrabber.inputs.template = 'sub-01/func/sub-01_task-simon_run-1_bold.nii.gz' io_S3DataGrabber.inputs.anon = True io_S3DataGrabber.inputs.bucket_path = 'ds000101/ds000101_R2.0.0/uncompressed/' io_S3DataGrabber.inputs.local_directory = '/tmp' #Wraps command **slicetimer** fsl_SliceTimer = pe.Node(interface=fsl.SliceTimer(), name='fsl_SliceTimer') #Computes the time-course SNR for a time series confounds_TSNR = pe.Node(interface=confounds.TSNR(), name='confounds_TSNR') confounds_TSNR.inputs.regress_poly = 3 #Wraps command **fslstats** fsl_ImageStats = pe.Node(interface=fsl.ImageStats(), name='fsl_ImageStats') fsl_ImageStats.inputs.op_string = '-p 98' #Wraps command **fslmaths** fsl_Threshold = pe.Node(interface=fsl.Threshold(), name='fsl_Threshold') fsl_Threshold.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. confounds_ACompCor = pe.Node(interface=confounds.ACompCor(), name='confounds_ACompCor') confounds_ACompCor.inputs.num_components = 2
epi_s1_stack = Node(dcmstack.DcmStack(), name='epi_s1_stack') epi_s1_stack.inputs.embed_meta = True epi_s1_stack.inputs.out_format = 'epi1' epi_s1_stack.inputs.out_ext = '.nii' epi_s2_stack = Node(dcmstack.DcmStack(), name='epi_s2_stack') epi_s2_stack.inputs.embed_meta = True epi_s2_stack.inputs.out_format = 'epi2' epi_s2_stack.inputs.out_ext = '.nii' st_corr = Node(spm.SliceTiming(), name='slicetiming_correction') realign = Node(spm.Realign(), name='realign') realign.inputs.register_to_mean = True tsnr = MapNode(confounds.TSNR(), iterfield='in_file', name='tsnr') tsnr.inputs.mean_file = 'mean.nii' tsnr.inputs.stddev_file = 'stddev.nii' tsnr.inputs.tsnr_file = 'tsnr.nii' despike = MapNode(afni.Despike(), iterfield='in_file', name='despike') despike.inputs.outputtype = 'NIFTI' seg = Node(spm.Segment(), name='seg') seg.inputs.csf_output_type = [False, False, True] #Output native CSF seg seg.inputs.gm_output_type = [False, False, True] #Output native gm seg seg.inputs.wm_output_type = [False, False, True] #Output native wm seg coreg2epi = MapNode(spm.Coregister(), iterfield='target', name='coreg2epi') #Warps to MNI space using a 3mm template image
struct='%s/anatomy/highres001_brain.nii.gz') DataFromOpenNeuro.inputs.template_args = dict(func=[['subj_id', 'run_num']], struct=[['subj_id']]) #Wraps command **slicetimer** SliceTimer = pe.MapNode(interface=fsl.SliceTimer(), name='SliceTimer', iterfield=['in_file']) #Wraps command **mcflirt** MotionCorrection = pe.MapNode(interface=fsl.MCFLIRT(), name='MotionCorrection', iterfield=['in_file']) #Computes the time-course SNR for a time series TSNR = pe.MapNode(interface=confounds.TSNR(), name='TSNR', iterfield=['in_file']) TSNR.inputs.regress_poly = 3 #Wraps command **fslstats** ComputeLowTsnr = pe.MapNode(interface=fsl.ImageStats(), name='ComputeLowTsnr', iterfield=['in_file']) ComputeLowTsnr.inputs.op_string = '-p 98' #Wraps command **fslmaths** Threshold = pe.MapNode(interface=fsl.Threshold(), name='Threshold', iterfield=['thresh', 'in_file']) Threshold.inputs.args = '-bin'
def fmri_qc_workflow(dataset, settings, name='funcMRIQC'): """ The fMRI qc workflow .. workflow:: import os.path as op from mriqc.workflows.functional import fmri_qc_workflow datadir = op.abspath('data') wf = fmri_qc_workflow([op.join(datadir, 'sub-001/func/sub-001_task-rest_bold.nii.gz')], settings={'bids_dir': datadir, 'output_dir': op.abspath('out')}) """ workflow = pe.Workflow(name=name) biggest_file_gb = settings.get("biggest_file_size_gb", 1) # Define workflow, inputs and outputs # 0. Get data, put it in RAS orientation inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') WFLOGGER.info( 'Building fMRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) inputnode.iterables = [('in_file', dataset)] meta = pe.Node(ReadSidecarJSON(), name='metadata') outputnode = pe.Node(niu.IdentityInterface( fields=['qc', 'mosaic', 'out_group', 'out_dvars', 'out_fd']), name='outputnode') reorient_and_discard = pe.Node(niu.Function( input_names=['in_file', 'float32'], output_names=['exclude_index', 'out_file'], function=reorient_and_discard_non_steady), name='reorient_and_discard') reorient_and_discard.inputs.float32 = settings.get("float32", DEFAULTS['float32']) reorient_and_discard.interface.estimated_memory_gb = 4.0 * biggest_file_gb # Workflow -------------------------------------------------------- # 1. HMC: head motion correct if settings.get('hmc_fsl', False): hmcwf = hmc_mcflirt(settings) else: hmcwf = hmc_afni(settings, st_correct=settings.get('correct_slice_timing', False), despike=settings.get('despike', False), deoblique=settings.get('deoblique', False), start_idx=settings.get('start_idx', None), stop_idx=settings.get('stop_idx', None)) # Set HMC settings hmcwf.inputs.inputnode.fd_radius = settings.get('fd_radius', DEFAULT_FD_RADIUS) mean = pe.Node( afni.TStat( # 2. Compute mean fmri options='-mean', outputtype='NIFTI_GZ'), name='mean') mean.interface.estimated_memory_gb = biggest_file_gb * 1.5 skullstrip_epi = fmri_bmsk_workflow(use_bet=True) # EPI to MNI registration ema = epi_mni_align(settings) # Compute TSNR using nipype implementation tsnr = pe.Node(nac.TSNR(), name='compute_tsnr') tsnr.interface.estimated_memory_gb = biggest_file_gb * 4.5 # 7. Compute IQMs iqmswf = compute_iqms(settings) # Reports repwf = individual_reports(settings) # Upload metrics upldwf = upload_wf(settings) workflow.connect([ (inputnode, meta, [('in_file', 'in_file')]), (inputnode, reorient_and_discard, [('in_file', 'in_file')]), (reorient_and_discard, hmcwf, [('out_file', 'inputnode.in_file')]), (mean, skullstrip_epi, [('out_file', 'inputnode.in_file')]), (hmcwf, mean, [('outputnode.out_file', 'in_file')]), (hmcwf, tsnr, [('outputnode.out_file', 'in_file')]), (mean, ema, [('out_file', 'inputnode.epi_mean')]), (skullstrip_epi, ema, [('outputnode.out_file', 'inputnode.epi_mask')]), (meta, iqmswf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('task_id', 'inputnode.task_id'), ('acq_id', 'inputnode.acq_id'), ('rec_id', 'inputnode.rec_id'), ('run_id', 'inputnode.run_id'), ('out_dict', 'inputnode.metadata')]), (reorient_and_discard, iqmswf, [('out_file', 'inputnode.orig')]), (mean, iqmswf, [('out_file', 'inputnode.epi_mean')]), (hmcwf, iqmswf, [('outputnode.out_file', 'inputnode.hmc_epi'), ('outputnode.out_fd', 'inputnode.hmc_fd')]), (skullstrip_epi, iqmswf, [('outputnode.out_file', 'inputnode.brainmask')]), (tsnr, iqmswf, [('tsnr_file', 'inputnode.in_tsnr')]), (reorient_and_discard, repwf, [('out_file', 'inputnode.orig')]), (mean, repwf, [('out_file', 'inputnode.epi_mean')]), (tsnr, repwf, [('stddev_file', 'inputnode.in_stddev')]), (skullstrip_epi, repwf, [('outputnode.out_file', 'inputnode.brainmask') ]), (hmcwf, repwf, [('outputnode.out_fd', 'inputnode.hmc_fd'), ('outputnode.out_file', 'inputnode.hmc_epi')]), (ema, repwf, [('outputnode.epi_parc', 'inputnode.epi_parc'), ('outputnode.report', 'inputnode.mni_report')]), (reorient_and_discard, repwf, [('exclude_index', 'inputnode.exclude_index')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms'), ('outputnode.out_dvars', 'inputnode.in_dvars'), ('outputnode.outliers', 'inputnode.outliers')]), (iqmswf, upldwf, [('outputnode.out_file', 'inputnode.in_iqms')]), (hmcwf, outputnode, [('outputnode.out_fd', 'out_fd')]), ]) if settings.get('fft_spikes_detector', False): workflow.connect([ (iqmswf, repwf, [('outputnode.out_spikes', 'inputnode.in_spikes'), ('outputnode.out_fft', 'inputnode.in_fft')]), ]) if settings.get('ica', False): melodic = pe.Node(nws.MELODICRPT(no_bet=True, no_mask=True, no_mm=True, generate_report=True), name="ICA") melodic.interface.estimated_memory_gb = biggest_file_gb * 5 workflow.connect([ (reorient_and_discard, melodic, [('out_file', 'in_files')]), (skullstrip_epi, melodic, [('outputnode.out_file', 'report_mask') ]), (melodic, repwf, [('out_report', 'inputnode.ica_report')]) ]) return workflow
name='NodeName_30f69e0') NodeHash_30f69e0.inputs.bucket = 'openneuro' NodeHash_30f69e0.inputs.sort_filelist = True NodeHash_30f69e0.inputs.template = 'sub-01/func/sub-01_task-simon_run-1_bold.nii.gz' NodeHash_30f69e0.inputs.anon = True NodeHash_30f69e0.inputs.bucket_path = 'ds000101/ds000101_R2.0.0/uncompressed/' NodeHash_30f69e0.inputs.local_directory = '/tmp' #Wraps command **slicetimer** NodeHash_1d000c0 = pe.Node(interface=fsl.SliceTimer(), name='NodeName_1d000c0') #Wraps command **mcflirt** NodeHash_22f2e80 = pe.Node(interface=fsl.MCFLIRT(), name='NodeName_22f2e80') #Computes the time-course SNR for a time series NodeHash_50c02c0 = pe.Node(interface=confounds.TSNR(), name='NodeName_50c02c0') NodeHash_50c02c0.inputs.regress_poly = 3 #Wraps command **fslstats** NodeHash_3ac27f0 = pe.Node(interface=fsl.ImageStats(), name='NodeName_3ac27f0') NodeHash_3ac27f0.inputs.op_string = '-p 98' #Wraps command **fslmaths** NodeHash_30f6760 = pe.Node(interface=fsl.Threshold(), name='NodeName_30f6760') NodeHash_30f6760.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. NodeHash_325da10 = pe.Node(interface=confounds.ACompCor(), name='NodeName_325da10') NodeHash_325da10.inputs.num_components = 2
my_io_S3DataGrabber.inputs.anon = True my_io_S3DataGrabber.inputs.bucket_path = 'ds000101/ds000101_R2.0.0/uncompressed/' my_io_S3DataGrabber.inputs.local_directory = '/tmp' #Wraps command **slicetimer** my_fsl_SliceTimer = pe.Node(interface=fsl.SliceTimer(), name='my_fsl_SliceTimer', iterfield=['']) #Wraps command **mcflirt** my_fsl_MCFLIRT = pe.Node(interface=fsl.MCFLIRT(), name='my_fsl_MCFLIRT', iterfield=['']) #Computes the time-course SNR for a time series my_confounds_TSNR = pe.Node(interface=confounds.TSNR(), name='my_confounds_TSNR', iterfield=['']) my_confounds_TSNR.inputs.regress_poly = 3 #Wraps command **fslstats** my_fsl_ImageStats = pe.Node(interface=fsl.ImageStats(), name='my_fsl_ImageStats', iterfield=['']) my_fsl_ImageStats.inputs.op_string = '-p 98' #Wraps command **fslmaths** my_fsl_Threshold = pe.Node(interface=fsl.Threshold(), name='my_fsl_Threshold', iterfield=['']) my_fsl_Threshold.inputs.args = '-bin'
def fmri_qc_workflow(dataset, settings, name='funcMRIQC'): """ The fMRI qc workflow """ workflow = pe.Workflow(name=name) # Define workflow, inputs and outputs # 0. Get data, put it in RAS orientation inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') WFLOGGER.info('Building fMRI QC workflow, datasets list: %s', sorted([d.replace(settings['bids_dir'] + '/', '') for d in dataset])) inputnode.iterables = [('in_file', dataset)] meta = pe.Node(ReadSidecarJSON(), name='metadata') outputnode = pe.Node(niu.IdentityInterface( fields=['qc', 'mosaic', 'out_group', 'out_dvars', 'out_fd']), name='outputnode') reorient_and_discard = pe.Node(niu.Function(input_names=['in_file'], output_names=['exclude_index', 'out_file'], function=reorient_and_discard_non_steady), name='reorient_and_discard') # Workflow -------------------------------------------------------- # 1. HMC: head motion correct hmcwf = hmc_mcflirt() if settings.get('hmc_afni', False): hmcwf = hmc_afni(st_correct=settings.get('correct_slice_timing', False), despike=settings.get('despike', False), deoblique=settings.get('deoblique', False)) # Set HMC settings hmcwf.inputs.inputnode.fd_radius = settings.get('fd_radius', DEFAULT_FD_RADIUS) if settings.get('start_idx'): hmcwf.inputs.inputnode.start_idx = settings['start_idx'] if settings.get('stop_idx'): hmcwf.inputs.inputnode.stop_idx = settings['stop_idx'] mean = pe.Node(afni.TStat( # 2. Compute mean fmri options='-mean', outputtype='NIFTI_GZ'), name='mean') bmw = fmri_bmsk_workflow( # 3. Compute brain mask use_bet=settings.get('use_bet', False)) # EPI to MNI registration ema = epi_mni_align(ants_nthreads=settings['ants_nthreads'], testing=settings.get('testing', False)) # Compute TSNR using nipype implementation tsnr = pe.Node(nac.TSNR(), name='compute_tsnr') # 7. Compute IQMs iqmswf = compute_iqms(settings) # Reports repwf = individual_reports(settings) workflow.connect([ (inputnode, meta, [('in_file', 'in_file')]), (inputnode, reorient_and_discard, [('in_file', 'in_file')]), (reorient_and_discard, hmcwf, [('out_file', 'inputnode.in_file')]), (hmcwf, bmw, [('outputnode.out_file', 'inputnode.in_file')]), (hmcwf, mean, [('outputnode.out_file', 'in_file')]), (hmcwf, tsnr, [('outputnode.out_file', 'in_file')]), (mean, ema, [('out_file', 'inputnode.epi_mean')]), (bmw, ema, [('outputnode.out_file', 'inputnode.epi_mask')]), (meta, iqmswf, [('subject_id', 'inputnode.subject_id'), ('session_id', 'inputnode.session_id'), ('task_id', 'inputnode.task_id'), ('run_id', 'inputnode.run_id'), ('out_dict', 'inputnode.metadata')]), (reorient_and_discard, iqmswf, [('out_file', 'inputnode.orig')]), (mean, iqmswf, [('out_file', 'inputnode.epi_mean')]), (hmcwf, iqmswf, [('outputnode.out_file', 'inputnode.hmc_epi'), ('outputnode.out_fd', 'inputnode.hmc_fd')]), (bmw, iqmswf, [('outputnode.out_file', 'inputnode.brainmask')]), (tsnr, iqmswf, [('tsnr_file', 'inputnode.in_tsnr')]), (reorient_and_discard, repwf, [('out_file', 'inputnode.orig')]), (mean, repwf, [('out_file', 'inputnode.epi_mean')]), (tsnr, repwf, [('stddev_file', 'inputnode.in_stddev')]), (bmw, repwf, [('outputnode.out_file', 'inputnode.brainmask')]), (hmcwf, repwf, [('outputnode.out_fd', 'inputnode.hmc_fd')]), (ema, repwf, [('outputnode.epi_parc', 'inputnode.epi_parc'), ('outputnode.report', 'inputnode.mni_report')]), (reorient_and_discard, repwf, [('exclude_index', 'inputnode.exclude_index')]), (iqmswf, repwf, [('outputnode.out_file', 'inputnode.in_iqms'), ('outputnode.out_dvars', 'inputnode.in_dvars'), ('outputnode.out_spikes', 'inputnode.in_spikes'), ('outputnode.outliers', 'inputnode.outliers')]), (hmcwf, outputnode, [('outputnode.out_fd', 'out_fd')]), ]) return workflow
def init_func_report_wf(workdir=None, fd_thres=None, name="func_report_wf", memcalc=MemoryCalculator()): """ """ workflow = pe.Workflow(name=name) # fmriprepreports = ["bold_conf", "reg", "bold_rois", "compcor", "conf_corr", "sdc"] fmriprepreportdatasinks = [f"ds_report_{fr}" for fr in fmriprepreports] strfields = [ "bold_std", "bold_std_ref", "bold_mask_std", "movpar_file", "skip_vols", "confounds", "std_dseg", "method", *fmriprepreportdatasinks, ] inputnode = pe.Node( Exec( fieldtpls=[ ("tags", None), *[(field, "firststr") for field in strfields], ("fd_thres", None) ] ), name="inputnode", ) outputnode = pe.Node(niu.IdentityInterface(fields=["vals"]), name="outputnode") # make_resultdicts = pe.Node( MakeResultdicts( reportkeys=["epi_norm_rpt", "tsnr_rpt", "carpetplot", *fmriprepreports], valkeys=["dummy", "sdc_method"] ), name="make_resultdicts", ) workflow.connect(inputnode, "tags", make_resultdicts, "tags") workflow.connect(inputnode, "skip_vols", make_resultdicts, "dummy") workflow.connect(inputnode, "method", make_resultdicts, "sdc_method") # resultdict_datasink = pe.Node( ResultdictDatasink(base_directory=workdir), name="resultdict_datasink" ) workflow.connect(make_resultdicts, "resultdicts", resultdict_datasink, "indicts") # for fr, frd in zip(fmriprepreports, fmriprepreportdatasinks): workflow.connect(inputnode, frd, make_resultdicts, fr) # EPI -> mni epi_norm_rpt = pe.Node( PlotRegistration(template=config.workflow.spaces.get_spaces()[0]), name="epi_norm_rpt", mem_gb=0.1, ) workflow.connect(inputnode, "bold_std_ref", epi_norm_rpt, "in_file") workflow.connect(inputnode, "bold_mask_std", epi_norm_rpt, "mask_file") workflow.connect(epi_norm_rpt, "out_report", make_resultdicts, "epi_norm_rpt") # plot the tsnr image tsnr = pe.Node(nac.TSNR(), name="compute_tsnr", mem_gb=memcalc.series_std_gb) workflow.connect(inputnode, "bold_std", tsnr, "in_file") tsnr_rpt = pe.Node(PlotEpi(), name="tsnr_rpt", mem_gb=memcalc.min_gb) workflow.connect(tsnr, "tsnr_file", tsnr_rpt, "in_file") workflow.connect(inputnode, "bold_mask_std", tsnr_rpt, "mask_file") workflow.connect(tsnr_rpt, "out_report", make_resultdicts, "tsnr_rpt") # reference_dict = dict(reference_space=constants.reference_space, reference_res=constants.reference_res) reference_dict["input_space"] = reference_dict["reference_space"] resample = pe.Node( Resample(interpolation="MultiLabel", **reference_dict), name="resample", mem_gb=memcalc.series_std_gb, ) workflow.connect(inputnode, "std_dseg", resample, "input_image") # vals confvals = pe.Node( Vals(), name="vals", mem_gb=memcalc.series_std_gb ) workflow.connect(inputnode, "fd_thres", confvals, "fd_thres") workflow.connect(inputnode, "confounds", confvals, "confounds") calcmean = pe.Node( CalcMean(key="mean_gm_tsnr"), name="calcmean", mem_gb=memcalc.series_std_gb ) workflow.connect(confvals, "vals", calcmean, "vals") # base dict to update workflow.connect(tsnr, "tsnr_file", calcmean, "in_file") workflow.connect(resample, "output_image", calcmean, "dseg") workflow.connect(calcmean, "vals", make_resultdicts, "vals") workflow.connect(make_resultdicts, "vals", outputnode, "vals") return workflow