Python 与第二个文件中的数组相比,将文件解析为数组的速度更快
我目前有一个包含MS2光谱数据的MGF文件(QE_2706_229_sequest_high_conf.MGF)。文件模板位于下面的链接以及示例片段中: 此未注光谱文件包含数千个此类条目,总文件大小约为150 MB。 然后我有一系列需要解析的文本文件。每个文件都类似于上面的格式,第一列被读入numpy数组。然后对每个条目解析未注释的光谱文件,直到从注释文本文件输入中找到匹配的数组 (文件名GRPGPVAGHHQMPR) 找到匹配项后,将写入一个MGF注释文件,该文件随后包含未注释文件中的完整条目信息,但其中有一行指定与该特定条目匹配的注释文本文件的文件名。结果如下:Python 与第二个文件中的数组相比,将文件解析为数组的速度更快,python,bioinformatics,Python,Bioinformatics,我目前有一个包含MS2光谱数据的MGF文件(QE_2706_229_sequest_high_conf.MGF)。文件模板位于下面的链接以及示例片段中: 此未注光谱文件包含数千个此类条目,总文件大小约为150 MB。 然后我有一系列需要解析的文本文件。每个文件都类似于上面的格式,第一列被读入numpy数组。然后对每个条目解析未注释的光谱文件,直到从注释文本文件输入中找到匹配的数组 (文件名GRPGPVAGHHQMPR) 找到匹配项后,将写入一个MGF注释文件,该文件随后包含未注释文件中的完整条
BEGIN IONS
SEQ=GRPGPVAGHHQMPR
TITLE=File3249 Spectrum10594 scans: 11084
PEPMASS=499.59366 927079.3
... ...
END IONS
可能有一种计算成本更低的解析方法。给定要搜索的2000个带注释的文件,以及上面的大型未注释文件,在2.6 GHz四核Intel Haswell cpu上解析当前需要约12小时
以下是工作代码:
import numpy as np
import sys
from pyteomics import mgf
from glob import glob
def main():
"""
Usage: python mgf_parser
"""
pep_files = glob('*.txt')
mgf_file = 'QE_2706_229_sequest_high_conf.mgf'
process(mgf_file, pep_files)
def process(mgf_file, pep_files):
"""Parses spectra from annotated text file. Converts m/z values to numpy array.
If spectra array matches entry in MGF file, writes annotated MGF file.
"""
ann_arrays = {}
for ann_spectra in pep_files:
a = np.genfromtxt(ann_spectra, dtype=float, invalid_raise=False,
usemask=False, filling_values=0.0, usecols=(0))
b = np.delete(a, 0)
ann_arrays[ann_spectra] = b
with mgf.read(mgf_file) as reader:
for spectrum in reader:
for ann_spectra, array in ann_arrays.iteritems():
if np.array_equal(array, spectrum['m/z array']):
print '> Spectral match found for file {}.txt'.format(ann_spectra[:-4])
file_name = '{}.mgf'.format(ann_spectra[:-4])
spectrum['params']['seq'] = file_name[52:file_name.find('-') - 1]
mgf.write((spectrum,), file_name)
if __name__ == '__main__':
main()
过去,它一次只能解析给定数量的文件。关于任何更有效的解析方法的建议?我认为还有改进的余地,因为您正在为每个小文件重复解析整个MGF文件。如果你重构代码,使它只被解析一次,你可能会得到一个不错的加速 下面是我如何调整您的代码,同时摆脱bash循环,并使用函数,该函数可能比
np.savetxt
慢一点,但更易于使用:
from pyteomics import mgf
import sys
import numpy as np
def process(mgf_file, pep_files):
ann_arrays = {}
for ann_spectra in pep_files:
a = np.genfromtxt(ann_spectra, invalid_raise=False,
filling_values=0.0, usecols=(0,))
b = np.delete(a, 0)
ann_arrays[ann_spectra] = b
with mgf.read(mgf_file) as reader:
for spectrum in reader:
for ann_spectra, array in ann_arrays.iteritems():
if np.allclose(array, spectrum['m/z array']):
# allclose may be better for floats than array_equal
file_name = 'DeNovo/good_training_seq/{}.mgf'.format(
ann_spectra[:-4])
spectrum['params']['seq'] = ann_spectra[
:ann_spectra.find('-') - 1]
mgf.write((spectrum,), file_name)
if __name__ == '__main__':
pep_files = sys.argv[1:]
mgf_file = '/DeNovo/QE_2706_229_sequest_high_conf.mgf'
process(mgf_file, pep_files)
然后,为了实现与bash循环相同的功能,可以将其称为
python2.7 mgf_parser.py *.txt
如果展开的参数列表太长,可以使用而不是依赖bash来展开它:
from glob import iglob
pep_files = iglob(sys.argv[1])
并这样称呼它以防止bash进行扩展:
python2.7 mgf_parser.py '*.txt'
代码已使用建议的更改进行了更新。它正确地运行,从调用脚本(未显示)的bash运行正确的输出,但上面的版本在没有bash循环的情况下运行时只写入7个(正确的)带注释的mgf文件,然后再次重复写入文件2-6。@user2277435我不确定我是否理解所需行为和实际行为之间的区别,你能详细说明一下吗?我在文本文件中有数千个未注释的光谱。这些光谱需要与mgf文件中的相应条目相匹配,并为每个未注释的文本文件生成一个带注释的mgf文件。到目前为止,上述版本仅与前几个光谱正确匹配而失败,并且一遍又一遍地写入相同的文件。@user2277435您问题中的“建议”代码与我的答案不同:请参阅mgf.read(…)块的缩进级别。这是打字错误吗?@LevLivitsky这就是问题所在,我现在看到了正确的输出。解析速度要快几个数量级。非常感谢。您说您在四核处理器上运行此功能,但在我看来,
线程
和多处理
都没有在任何地方实现。在我看来,使用函数过程
中的一个for
循环,您可以相当轻松地完成此操作。
from glob import iglob
pep_files = iglob(sys.argv[1])
python2.7 mgf_parser.py '*.txt'