什么是nipype?
-
功能
- 提供多种脑影像处理软件的统一接口(SPM, FSL, FreeSurfer, AFNI, ANTS, Camino, MRtrix, MNE, Slicer等)
- 允许使用任何软件包创建由多个处理步骤组成的工作流
- 通过并行执行插件来优化计算
-
组成(主要部分)
- 接口(interfaces):一个可以调用外部package的模块
- 工作流(workflow engine):
- 节点(Node/MapNode):包装(wrap)在工作流中调用的接口
- 工作流(workflow):连边是数据流的图
- 执行插件(execution plugins):描述工作流如何执行
接口
运行code的核心部分
帮助函数 xx.help # xx–>命令
- 解释
- 输入参数
- 输出参数
错误提示
节点
-
以合理的顺序执行多个接口,可以更高效的分析——需要把接口放到节点中。
-
每个节点执行一个确定的函数,包括:
1、节点名;
2、接口类别;
3、至少一个输入数据;
4、至少一个输出数据。 -
设置节点的基本格式
nodename = Nodetype(interface_function(), name='labelname') # nodename --> python环境中,节点的变量名 # Nodetype --> 创造的节点类型:Node,MapNode,JoinNode【这几个类型有啥区别?】 # interface_function -->节点执行的具体函数,可以是用户自定义的,也可以是接口调用的 # labelname --> 工作流环境中,节点的标签名
-
示例
from nipype.interfaces.fsl import BET # Import BET from the FSL interface from nipype import Node # Import the Node module bet = Node(BET(frac=0.3), name='bet_node') # Create Node --> bet是节点名,Node是节点类型,BET是调用的接口函数,name是工作流中的标签名 bet.inputs.in_file = '/data/ds000114/sub-01/ses-test/anat/sub-01_ses-test_T1w.nii.gz' bet.inputs.out_file = '/output/node_T1w_bet.nii.gz' # Specify node inputs --> 定义输入数据和输出文件名 res = bet.run() # 运行并输出结果
工作流
-
每一个节点按一定的顺序联系起来(上一个节点的输出作为下一个节点的输入)形成工作流。
-
安排串行和并行,根据每个节点(嵌入了接口)的输入和输出,决定哪些节点是串行的哪些是并行的。
-
对数据进行修改时,不涉及修改的部分会直接输出上个run的结果,可以节省计算时间
-
workflow中可以嵌入sub-workflow
-
示例:创建一个simple workflow
from nipype import Node, Workflow from nipype.interfaces import fsl # Import Node and Workflow object and FSL interface from os.path import abspath in_file = abspath("/data/ds000114/sub-01/ses-test/anat/sub-01_ses-test_T1w.nii.gz") # 此处使用绝对路径,与工作流base文件夹路径设置有关 For reasons that will later become clear, it's important to pass filenames to Nodes as absolute paths skullstrip = Node(fsl.BET(in_file=in_file, mask=True), name="skullstrip") # 定义节点skullstrip,Skullstrip process smooth = Node(fsl.IsotropicSmooth(in_file=in_file, fwhm=4), name="smooth") # 定义节点smooth,Smooth process mask = Node(fsl.ApplyMask(), name="mask") # 定义节点mask,Mask process wf = Workflow(name="smoothflow", base_dir="/output/working_dir") # 定义工作流,工作流名称为smoothflow;重要:定义工作流的base文件夹! Initiation of a workflow wf.connect(skullstrip, "mask_file", mask, "mask_file") # 定义连接第一种,First the "simple", but more restricted method wf.connect([(smooth, mask, [("out_file", "in_file")])]) # 定义连接第二种,Now the more complicated method wf.write_graph("workflow_graph.dot") from IPython.display import Image Image(filename="/output/working_dir/smoothflow/workflow_graph.png") #可视化workflow wf.write_graph(graph2use='flat') Image(filename="/output/working_dir/smoothflow/graph_detailed.png") #可视化节点间的具体连接(input和output) wf.base_dir = "/output/working_dir" # Specify the base directory for the working directory wf.run() # 执行工作流 Execute the workflow定义连接关系需要的信息【两种方法】:
1、The source node object
2、The name of the output field from the source node
3、The destination node object
4、The name of the input field from the destination node、 -
在工作流中嵌入工作流【nested workflows】
示例:创建一个包含susan workflow作为sub-node的workflow
wf2 = Workflow(name="susanflow", base_dir="/output/working_dir") # 定义工作流,Initiate workflow with name and base directory skullstrip2 = Node(fsl.BET(in_file=in_file, mask=True), name="skullstrip") mask2 = Node(fsl.ApplyMask(), name="mask") # 定义节点,Create new skullstrip and mask nodes wf2.connect([ (skullstrip2, mask2, [("mask_file", "mask_file")]), (skullstrip2, susan, [("mask_file", "inputnode.mask_file")]), (susan, list_extract, [("outputnode.smoothed_files","list_out")]), (list_extract, mask2, [("out_file", "in_file")]) ]) # 定义工作流中的节点连接,Connect the nodes to each other and to the susan workflow susan.inputs.inputnode.in_files = abspath( "/data/ds000114/sub-01/ses-test/anat/sub-01_ses-test_T1w.nii.gz") susan.inputs.inputnode.fwhm = 4 # 设置susan workflow需要输入的其他变量,Specify the remaining input variables for the susan workflow wf2.write_graph(dotfilename='/output/working_dir/full_susanflow.dot', graph2use='colored') from IPython.display import Image Image(filename="/output/working_dir/full_susanflow.png") # 可视化workfolw wf2.write_graph(dotfilename='/output/working_dir/full_susanflow_toplevel.dot', graph2use='orig') from IPython.display import Image Image(filename="/output/working_dir/full_susanflow_toplevel.png") #可视化更高水平的workflow wf2.run() #执行workflow
数据输入
-
抓取数据的模块
- DataFinder
DataGrabber
FreeSurferSource
JSONFileGrabber
S3DataGrabber
SSHDataGrabber
SelectFiles
XNATSource
- DataFinder
-
DataGrabber
import nipype.interfaces.io as nio datasource1 = nio.DataGrabber() # 生成一个DataGrabber对象 datasource1.inputs.base_directory = '/data/ds000114' # 指定根目录 # .base_directory --> 在指定文件夹中进行搜索 datasource1.inputs.template = 'sub-01/ses-test/func/sub-01_ses-test_task-fingerfootlips_bold.nii.gz' # .template --> 指定要匹配的字符串模版,定义抓取的文件名称,可以是具体的文件名 datasource1.inputs.sort_filelist = True results = datasource1.run() results.outputs datasource2.inputs.template = 's*/ses-test/funcses-{ses_name}/anat/sub-*_ses-{ses_name}_T1w.nii.gz'} # sub-0 [1,2] --> 选择1、2号被试 templates = {'anat': 'sub-0[1,2]/ses-{ses_name}/anat/sub-0[1,2]]_ses-{ses_name}_T1w.nii.gz'} # 当与template匹配的只有一个文件时,默认返回的是字符串而不是列表,强制输出列表可使用force_lists sf = SelectFiles(templates, force_lists=["anat"]) -
FreeSurferSource
专门用于加速FreeSurfer 中recon-all算法数据的导入
from nipype.interfaces.freesurfer import FSCommand from os.path import abspath as opap from nipype import Node from nipype.interfaces.io import FreeSurferSource fs_dir = opap('/data/ds000114/derivatives/freesurfer/') # Path to your freesurfer output folder FSCommand.set_default_subjects_dir(fs_dir) # Set SUBJECTS_DIR fssource = Node(FreeSurferSource(subjects_dir=fs_dir), name='fssource') # 创建节点 fssource.inputs.subject_id = 'sub-01' result = fssource.run() # 输出第一个被试皮层重建的数据 print('aparc_aseg: %sn' % result.outputs.aparc_aseg) print('inflated: %sn' % result.outputs.inflated) # 查看输出的文件,inflated储存了左右半脑的数据 fssource.inputs.hemi = 'lh' result = fssource.run() result.outputs.inflated # 只输出左半脑的数据,右半脑'rh'
数据输出
-
nipype提供的处理输出数据流的模块
- DataSink
JSONFileSink
MySQLSink
SQLiteSink
XNATSink
- DataSink
-
使用datasink输出之前,先run一下单个被试的workflow,根据输出进行node的创建
from nipype.interfaces.io import DataSink sinker = Node(DataSink(), name='sinker') # 创建sinker节点 sinker.inputs.base_directory = '/output/working_dir/preprocWF_output' # 输出文件夹名称 wf.connect([(smooth, sinker, [('out_file', 'in_file')]), (mcflirt, sinker, [('mean_img', 'mean_img'), ('par_file', 'par_file')]), ]) # 把相关节点和sinker节点连接,生成3个文件夹 # 可以把3个文件夹的输出合为1个 wf.connect([(smooth, sinker, [('out_file', 'preproc.@in_file')]), (mcflirt, sinker, [('mean_img', 'preproc.@mean_img'), ('par_file', 'preproc.@par_file')]), ]) # 文件夹A.@XX --> 输出到同一个文件夹A # 可以对输出文件名进行替换 substitutions = [('_task-fingerfootlips', ''), ("_ses-test", ""), ('_bold_mcf', ''), ('.nii.gz_mean_reg', '_mean'), ('.nii.gz.par', '.par')] # 定义替换的字符串 sinker.inputs.substitutions = substitutions # 将替换的字符串反馈到节点 wf.run()



