mysql inputoutput_Nipype学习笔记(2)——Input & Output

本文介绍了Nipype中用于数据输入的DataGrabber和SelectFiles工具。DataGrabber允许灵活地从目录中按规则选择数据,而SelectFiles使用大括号模板更直观地获取文件。此外,文章还提到了BIDS格式数据的处理和数据输出模块DataSink的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4. 数据的输入

在Nipype中提供了丰富的文件操作功能,使得我们在数据处理时不需要再把数据“复制过来,粘贴过去”,不仅极大地简化了操作,也避免了存储空间的浪费。

4.1 DataGrabber

顾名思义,DataGrabber是一个数据抓取工具,能够从指定的目录中按照一定的规则挑选出需要的数据。

假设我们使用的是DS00014的数据集合,其数据结构如下图所示:

91453c76dbc3?from=singlemessage

image.png

对于这样一个数据集合,如何从中挑选出fingerfootlips任务的数据呢?其实可以这样:

import nipype.interfaces.io as nio

# 生成一个DataGrabber对象

ds = nio.DataGrabber()

# 指定根目录

ds.inputs.base_directory = '/data/ds000114'

# 指定模板,用来过滤文档

ds.inputs.template = 's*/ses-test/func/*fingerfootlips*.nii.gz'

# 需要注意的是,此处并没有对文档进行排序,如果需要排序需要指定sorted参数

ds.inputs.sort_filelist = True

# 执行

results = ds.run()

# 查看执行结果

results.outputs

使用这段代码,可以在/data/ds000114文件夹下挑选出所有满足s*/ses-test/func/*fingerfootlips*.nii.gz这一模式的文档。如果想要过滤出特定ID的被试怎么办呢?可以这样:

# 在生成DataGrabber对象的时候,需要指定infields参数

ds = nio.DataGrabber(infields=['subject_id'])

ds.inputs.base_directory = '/data/ds000114'

# 使用%02d来设计模板

ds.inputs.template = 'sub-%02d/ses-test/func/*fingerfootlips*.nii.gz'

ds.inputs.sort_filelist = True

# 指定subject_id的具体数值

ds.inputs.subject_id = [1, 7]

results = ds.run()

results.outputs

可见,Nipype的数据挑选方式有多么灵活。

官方文档中还给了几个其他的例子,其实并不是很好懂,建议没有时间的小伙伴们不要把太多的精力放在上面,因为接下来要介绍的SelectFiles会比DataGrabber更加的灵活和清晰。唯一还需要说明的是,DataGrabber的构造函数中,还有一个常用的参数,叫outfields,这个参数的含义是DataGrabber的输出会变成一个类似于字典的数据结构,该结构的KEY是由outfileds来确定。使用outfileds后,就可以用同一个DataGrabber使用不同的模板来挑选各种各样的文件了。

4.2 SelectFiles

相比于DataGrabber,SelectFiles应该是一种更加直观的数据抓取工具,它使用的是基于大括号{}的模板。这对于写过Rails和Flask的小伙伴来说应该会更加容易理解。先举个例子(这也是官方文档的例子):

msg = "This workflow uses {package}."

print(msg.format(package="FSL"))

这样一段Python代码执行之后,会看到什么结果呢?运行之后,我们可以看到:

This workflow uses FSL.

很直观的,源代码中的{package}变成了FSL,这也就是我所谓的基于大括号的模板,那么在实际中应该如何应用呢?再来看下一段代码:

from nipype import SelectFiles, Node

templates = {'anat': 'sub-{subject_id}\\ses-{ses_name}\\anat\\sub-{subject_id}_ses-{ses_name}_T1w.nii.gz',

'func': 'sub-{subject_id}\\ses-{ses_name}\\func\\sub-{subject_id}_ses-{ses_name}_task-{task_name}_bold.nii.gz'}

# Create SelectFiles node

sf = Node(SelectFiles(templates),

name='selectfiles')

# Location of the dataset folder

sf.inputs.base_directory = 'E:\\ds114_R2.0.0'

# Feed {}-based placeholder strings with values

sf.inputs.subject_id = '0[1,2]'

sf.inputs.ses_name = "test"

sf.inputs.task_name = 'fingerfootlips'

sf.run().outputs

运行上述代码之后,会得到如下结果:

anat = ['E:\\ds114_R2.0.0\\sub-01\\ses-test\\anat\\sub-01_ses-test_T1w.nii.gz', 'E:\\ds114_R2.0.0\\sub-02\\ses-test\\anat\\sub-02_ses-test_T1w.nii.gz']

func = ['E:\\ds114_R2.0.0\\sub-01\\ses-test\\func\\sub-01_ses-test_task-fingerfootlips_bold.nii.gz', 'E:\\ds114_R2.0.0\\sub-02\\ses-test\\func\\sub-02_ses-test_task-fingerfootlips_bold.nii.gz']

首先,可以看到,按照模板的设置,系统的输出会分成anat和func两部分,这个的效果就与DataGrabber的outfields是一致的。其次模板中的{subject_id}被替换成了01和02,{ses_name}被替换成了test,{task_name}被替换成了fingerfootlips。当然,和DataGrabber一样,模板中还是可以使用*符号的。最后,在替换时,使用的是字符串直接替换,因此在给模板中的变量赋值的时候,是不能使用['01','02']这种形式的,否则系统会报错。

5. BIDS格式的输入

DataGrabber和SelectFiles为我们提供了便捷的数据选择工具,不过如果你使用的是标准的BIDS格式的数据(据说OpenfMRI上的数据都是以这种格式组织的),那么恭喜你,Nipype提供了更加便捷的数据访问方式。

5.1 pybids

要想享受Nipype和BIDS给你带来的种种便捷,还需要安装pybids这样一个python工具包,安装的方式很简单:

pip install pybids

我自己刚刚试了一下,想用conda安装,不过报错了,可能需要添加新的channel,回头再研究一下这个问题。用pip安装是没有任何问题的。

在使用pybids的时候,先导入BIDSLayout对象,在生成一个对象(好吧,其实你注意到了,我把数据换了路径存放,而且是在windows下)

from bids.grabbids import BIDSLayout

layout = BIDSLayout("E:\\Workspaces\\nipy\\data")

之后就可以使用layout来获得一些数据集的元信息以及一些具体的任务对应的数据文件。

先来看一下一些常用的元数据的获取方法,包括:

get_subjects() 获取所有的被试

get_modalities()

get_types()

get_tasks() 获取所有的任务

get_metadata 获取nii和nii.gz文件的元数据

如果要获得对应的数据文件,就可以直接调用get()函数,并在get函数中通过参数指明所需要的数据集的特征,常用的参数包括:

subject 指定被试,可以指定多个被试,例如:layout.get(subject=['01','02'])就可以获取所有01和02的数据文件

modality

type

session

task 指定执行的任务,例如:layout.get(task='')就可以获得

return_type 返回数据的类型。默认情况下,get函数会返回一个文件对象,包括该文件所属的被试、session、task、type等信息,例如:File(filename='E:\\Workspaces\\nipy\\data\\sub-02\\ses-test\\func\\sub-02_ses-test_task-linebisection_events.tsv', subject='02', session='test', task='linebisection', type='events', modality='func'),如果想要获得的只是文件路径,那么就需要指定该参数为'file'

extensions 指定返回文件的扩展文件名,例如extensions=['nii', 'nii.gz'],就会返回所有后缀为nii和nii.gz的文件

5.2 pybids+nipype

pybids 已经很好的完成了所有想要做的工作,唯一的缺陷是还不能加入到我们的Workflow中,那么该如何实现呢?一个比较直观的想法就是将pybids的工作封装到Node中,而封装就需要先定义一个函数:

def get_niftis(subject_id, data_dir):

from bids.grabbids import BIDSLayout

layout = BIDSLayout(data_dir)

bolds = layout.get(subject=subject_id, type="bold", return_type='file', extensions=['nii', 'nii.gz'])

return bolds

之后,就需要定义自定义Node节点了

from nipype.pipeline import Node

from nipype.interfaces.utility import Function

BIDSDataGrabber = Node(Function(function=get_niftis, input_names=["subject_id", "data_dir"], output_names=["bolds"]),

name="BIDSDataGrabber")

之后,就是输入

BIDSDataGrabber.inputs.data_dir = "E:\\Workspaces\\nipy\\data"

BIDSDataGrabber.inputs.subject_id='01'

res = BIDSDataGrabber.run()

res.outputs

但是,这样是无法遍历所有的subjects,如果需要遍历,还需要指定iterables参数(此处没有想明白,需要在实际操作的时候再来完善,先把这部分的内容记录下来)

BIDSDataGrabber.iterables = ('subject_id', layout.get_subjects()[:2])

6. 数据的输出

在Nipype中,输出也是以模块的形式呈现的,主要包括以下几种输出模块:

DataSink

JSONFileSink

MySQLSink

SQLiteSink

XNATSink

从名称上不难发现,其中绝大多数是和特定的数据工具相关,比如MySQLSink和SQLiteSink一定是与MySQL和SQLite两种数据库相关,XNATSink肯定是和XNAT数据相关,JSONFileSink应该是以JSON文件的格式来存储和管理数据,DataSink应该是一种更为通用的数据格式。因此,不妨从DataSink来开始我们的学习。

XNAT( Extensible Neuroimaging Archive Toolkit )是一个开源的软件平台,旨在帮助神经影像及其相关数据的管理和挖掘。

6.1 DataSink

如前所述,DataSink是一种较为通用的数据存储模块,通常用于存储结构化的输出。在Workflow中,其工作目录就如同一个缓存,会存储着各个阶段的计算结果(如日志信息等),如果直接浏览Workflow的工作目录会让人十分崩溃,而我们的目标通常是这些中间过程中的一小部分。DataSink可以将缓存中的结果提取出来并放置到不同的位置。

DataSink中第一个重要参数是base_directory,该参数指定了DataSink存储的根目录。其他输入参数用于和其他模块对接,有趣的是DataSink用这些输入参数的名称指定了目录结构。其基本形式如下

string[[.[@]]string[[.[@]]string]] …

其中[]表示其中的内容是可选项,在DataSink中用.表示目录结构关系,例如:contrasts.con表示在根目录下会创建contrasts/con这样的目录结构,如果带有@则表示不会建立新的目录,例如contrasts.@con,则会创建contrasts目录,并把结果存储在contrasts目录下。

如果觉得说的不清楚,还是来看个例子吧,先来看一下Workflow图:

91453c76dbc3?from=singlemessage

Workflow

代码如下:

datasink = pe.Node(nio.DataSink(), name='sinker')

datasink.inputs.base_directory = '/path/to/output'

workflow.connect(inputnode, 'subject_id', datasink, 'container')

我们先创建了一个DataSink节点,然后将其根目录指定为/path/to/output,然后将inputnode节点的输出subject_id与datasink的container相连接,因此就会在/path/to/output/container中存储InputNode的subject_id输出。

workflow.connect(realigner, 'realigned_files', datasink, 'motion')

workflow.connect(realigner, 'realignment_parameters', datasink, 'motion.@par')

执行上面语句后,就会把头动矫正后的数据文件存储到/path/to/output/container/motion文件夹下,并将头动参数也存储到该文件夹下。

6.2 MySQLSink

MySQLSink用于将一些值直接存储到MySQL数据库中,示例代码如下:

sql = MySQLSink(input_names=['subject_id', 'some_measurement'])

sql.inputs.database_name = 'my_database'

sql.inputs.table_name = 'experiment_results'

sql.inputs.username = 'root'

sql.inputs.password = 'secret'

sql.inputs.subject_id = 's1'

sql.inputs.some_measurement = 11.4

sql.run()

这对于用过数据库的同学而言应该十分简单,就不做过多的说明了。

大致看了一下,其他几种模块都大同小异,就不仔细学习了,如果需要的话再去看文档吧,目前应该用不到。

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值