Brenda Parser README(1, v1.0)

Review

网上可以很快地搜到三个 Brenda Parser,都是基于Python的:
Midnighter
alexandra-zaharia
Robaina
目前都处于发展完善的阶段。
还有一个基于R的,并且Brenda自身提供了SOAP访问方法。

Target

以脂肪酶(EC 3.1.1.3)为例,开发Brenda Parser,实现酶 - 底物(产物)相互作用网络信息的整理。

  • 识别文本格式信息,读入为条目信息(分表)
  • 对条目进行信息精炼
  • 以物种区分的酶信息(PR)
  • 反应信息(关联信息)与化学物质信息(NSP/SP)

API

在不考虑化学物质库/酶库/文献库的时候,Brenda是这样的:
Brenda文件格式

导入brenda_parser:

from brenda_parser import brenda_parser
with brenda_parser('./brenda_download.txt') as parser:
	brenda = parser.parse()

brenda为一个字典,即将文本信息转化为一个字典(或一个树型结构):

page = brenda.Pages['3.1.1.3'] # EC 3.1.1.3的记录页 # Pages 是一个字典
# page.TableNames # EC 3.1.1.3的条目(表头)
record = page.Records['PROTEIN'] # List of String,中间结果,理论上不作为API
table = page.Tables['PROTEIN'] # List of Tuple,加工后的结果,可以作为API.

对于brenda进行分析和分解,可以整理出来许多的子数据库,例如:酶/化学物质/反应(子)数据库。这些是我们这里所关心的。

brenda -> DB

这些子库可能有全局调用或者在某一个EC号下调用的可能性。未来可能涉及到合并问题,但此时我们只考虑在某一个page页下的局部信息。

page.DBs['Enzymes'] # 酶表
page.DBs['Chemicals'] # 化合物表
page.DBs['ECIs'] # 酶-化合物关系表

TODO

实际上API已经表明了需要做的事情。
主要工作便是充实下面的函数,实现对Brenda记录的处理:
gen函数图示

class brenda_parser:
	def parse(filename):
		# 处理生成TableNames和Records.
		genRecords(filename)
		# 处理 Records 生成 Tables.
		genTables(tables = ['PROTEIN',
							'NATURAL_SUBSTRATE_PRODUCT',
							'SUBSTRATE_PRODUCT'])
		# 处理 Tables 生成Enzymes, Chemicals, Enzymechemicals三个表.
		genEnzymes()
		genChemicals()
		genECIs() # 可与 genChemicals()合并。
getRecords(filename)

维护一个scanner的状态,逐行读入文件(或\n分割)进行转移。根据该行所匹配的正则表达式决定状态转移方式及内容写入位置。
getRecords 状态转移示意图

genTables(tables = TABLE_DEALABLE)

给定参数 tables,表明需要生成的表。默认tables参数为一个全局变量,表示已经实现了处理程序的表(table that could be dealed with.)。
实际上便是对字符串进行信息提取。格式可以参考brenda网站上的表格。
目前实现’PROTEIN’, ‘NATURAL_SUBSTRATE_PRODUCT’, ‘SUBSTRATE_PRODUCT’ 三个表的格式整理。

PROTEIN

输入:#n# value (note1, note2) <ref1,ref2>
输出:(Id, Organism, Note, Ref)
Organism 即 value。

NSP 和 SP

输入:#n1,n2# value (note1, note2) <ref1,ref2>
输出:(Protein, Reaction, Note, Ref)
Protein 即 蛋白的序号n1,n2;Reaction 即 value。

genEnzymes()

由 Tables[‘PROTEIN’]生成 Enzymes。
输入:(Id, Organism, Note, Ref)
输出:(Id, EC, Organism)

genChemicals(), genECIs()

由 Tables[‘NATURAL_SUBSTRATE_PRODUCT’] 和 Tables[‘SUBSTRATE_PRODUCT’’]生成Chemicals和ECIs。
输入:(Protein, Reaction, Note, Ref)
输出:(id, name) 和 (eid, cid, relationship)
这里涉及到维护一个化学物质set的任务和进行数据清洗的任务。
Reaction的可能形式如下(还有一些边缘情况):
sub1 + sub2 = prod1 + prod2
其中有一些形式如下:

more = ? # brenda中表示未处理数据的方式。
retinyl palmitate + H2O = retinol + palmitate # H2O作为常见物质,维护一个列表直接去除。
tricaprylin + H2O = dicaprylin + caprylate {ir} # {ir} 表示不可逆反应。
tributyrin + H2O = dibutyrin + butyrate # 有一些重复的数据。
vinyl propionate + H2O = ? # 有些记录不全面。
flax seed oil + H2O = ? # 有些记录中不是一个物质,而是一类物质。

Brenda TXTFILE格式

上网冲浪一番,对于文件parser使用的工具叫做lex/yacc,或flex/bison。对于python,也有PLY可以使用。可以参考博文:Python Lex-YaccPLY手册翻译和知乎回答:如何愉快地写个小parser?
或者使用RE表达式硬写,上面的几个Github方案采用的都是正则表达式。毕竟问题不是特别困难。
这里先采用RE表达式硬写的"笨办法"。

Brenda 文件格式说明
EC号

以ID 开头

ID 3.1.1.3

版权说明

以星号开头。
版权说明

内容

相当于表格(Tables)呈现,大写的是表格名称,然后以缩写大写作为新的一行;字数太多会换行。表格名称和缩写可以从已有的几个parser中直接粘贴得到。
条目的格式如下:
TABLE_NAME
TN #protein1, protein2# value (note1; note2) |note1; note2| {key: value}/{bl_value} <ref1,ref2>
note = #protein1, protein2# value <ref1, ref2>
例子:

  1. PROTEIN
    brenda中对蛋白区分的依据是蛋白的来源,从#1#开始编号。#1# 表明蛋白的序号,<315>表明来源参考文献,()中为补充说明,括号中以分号作为条目的分隔符。
    1号蛋白来源于Mg,参考文献是315,括号中是Note。
  2. TABLE_NAME
    除了蛋白和参考文献的其它表格。
  3. REFERENCE
    参考文献也是从<1>开始编号的。

PROTEIN
PR #1# Meleagris gallopavo (#1# isoform Xyl3A <315>) <315>
PR #8# Rattus norvegicus (#8# isoform CHX1 <36>; #8# isoform CHX2 <38>;
#8# isoform CLH1 <40>) <10,30,34,36,38,40,42,55,56,59,116>

SUBSTRATE_PRODUCT
SP #10,14,20,24,37,64,93,105,113,123,148# tristearin + H2O = distearin +
stearate (#24,37,123# low activity <121,124,205>; #93# about 10% of the
activity with tributyrin <95>) <72,73,84,86,88,95,121,124,135,187,205>

REFERENCE
RF <1> Rollof, J.; Hedström, S.A.; Nilsson-Ehle, P.: Purification and
characterization of a lipase from Staphylococcus aureus. Biochim.
Biophys. Acta (1987) 921, 364-369. {Pubmed:3651493} ©

结束

/// 三个斜杠表示Page的结束;最后加一空行,表示文件的结束。

正则表达式提取信息

正则表达式目前有一些网络教程:
Python 正则表达式 | 菜鸟教程
在线正则表达式测试
知乎:你是如何学会正则表达式的?

PROTEIN

案例如下:

#1# Meleagris gallopavo (#1# isoform Xyl3A <315>) <315>
#2# Staphylococcus aureus <1>
#8# Rattus norvegicus (#8# isoform CHX1 <36>; #8# isoform CHX2 <38>; #8# isoform CLH1 <40>) <10,30,34,36,38,40,42,55,56,59,116>
#25# Acinetobacter calcoaceticus (#25# isoform DS-epi2 (Dse-like) <19>) <19,66>
#34# Bacillus sp. (in: Bacteria) <66,75,89,91,289,316>
#9# Sus scrofa <2,3,4,5,6,7,8,9,10,11,12,13,14,15,27,43,44,52,76,112,113,116,192,258 259,266,286,332,340,348>

从上面的案例总结出来:
无捕获组版:

'#([\d]+)# (.+?)(?:\((?=#)(.+?)(?<=>)\))? <([\d, ]+)>'

无捕获组
对上述re进行说明:

  1. 先行断言与后行断言:a(?=b) 表示只有在b前面的a才匹配;(?<=b)a 表示只有在b后面的a才匹配,用于区分注释括号与非注释括号。
  2. a? a出现0或1次。
  3. 注意 ## 与 <> 中有包含了逗号和空格,这是因为原文件中如果太长有换行的话,空格替代了本应有的逗号。

捕获组版:

'#([\d]+)# (.+?)(?:\((?=#)(.+?)(?<=>)\))? <([\d, ]+)>'
SUBSTRATE_PRODUCT

案例:

#121# (R/S)-ibuprofen methoxyethyl ester + H2O = (R)-ibuprofen methoxyethyl ester + (S)-ibuprofen + 2-methoxyethanol {} <97>
#21# triolein + H2O = 1,3-diolein + 1,2-diolein + 2,3-diolein + oleate |#21# shows random positional specificity for triolein hydrolysis <269>| <269>
#3,5,7,9,10,21,34,47,50,68,74,90,94,196# triacylglycerol + H2O = diacylglycerol + a carboxylate (#94# … <151>) |#5# … <341>| <83,115,132,148,151,162,178,181,185,214,289,329,330,332,334,335,338,339 341,343,344,345,346>
#4,7,9,10,14,17,20,21,34,37,39,41,45,49,51,53,55,59,61,64,65,67,68,71 74,82,93,94,96,99,102,105,106,108,111,113,123,124,126,129,130,131,140 148,149,184# triolein + H2O = diolein + oleate (#41,96,123,131# low activity <61,62,121,125>) |#64# main product is oleic acid, further products are 1,3-dioleylglycerol, 1,2-dioleylglycerol, 2,3-dioleylglycerol, and minor product is 1-monooleylglycerol <73>| {r} <57,61,62,63,64,66,67,71,73,74,84,86,88,90,91,95,109,110,112,113,114 117,120,121,124,125,126,127,130,133,134,135,136,137,140,141,142,143,149 151,157,162,176,181,185,186,187,207,219,240,252,258,310,320,324>

SP相对而言增加了一些复杂性,如()中表示注释,{}表示是否是可逆反应,||中表示对产物的注释(product commentary)。但同样利用断言可以实现。
捕获组版:

'#([\d, ]+)# (.+?)(?: \((?=#)(.+?)(?<=>)\))?(?: \|(?=#)(.+?)(?<=>)\|)?(?: \{.*?\})? <([\d, ]+)>'

说明:

  1. 空格。空格很关键,在value, (note), |note|, {r}, 之间都有空格,为了精确匹配,需要考虑空格的数量。
  2. (?:a) 表示非捕获组。
反应

glyceryl trioctanoate + H2O = glycerol + octanoate

用正则的方法做的话,需要辨识( + ), ( = )和^, $。有一个补丁方法是现在开头和末尾加入’+ ‘和’ +’,这样所有的环境一致了。用下面这个式子便能全部整理出来。

re.findall('?<=[\+\=] )(.+?)(?= [\+\=]', '+ ' + line + ' +')

但是没办法区分底物和产物。所以还是用老办法——split,先拆成底物组和产物组,然后再拆成各个物质。
有一些边界情况。在原来的版本里遇到了,处理了,在EC3.1.1.3中暂时没有遇到。

总结

至此,已经完成了对Brenda中EC 3.1.1.3的所需信息提取。(2020-1-10至1-11)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值