Python 3.x 按序列大小对fasta排序
我目前想按序列大小对hudge fasta文件(+10**8行和序列)进行排序。fasta是生物学中一种明确定义的格式,用于存储序列(遗传或蛋白质): >id1 序列1可以在几行上 >id2 序列2 我运行了一个以tsv格式提供信息的工具: 标识、长度和标识的位置(以字节为单位) 现在我要做的是按照长度列对这个文件进行排序,然后解析这个文件并使用seek检索相应的序列,然后将它附加到一个新文件中Python 3.x 按序列大小对fasta排序,python-3.x,sorting,bioinformatics,fasta,Python 3.x,Sorting,Bioinformatics,Fasta,我目前想按序列大小对hudge fasta文件(+10**8行和序列)进行排序。fasta是生物学中一种明确定义的格式,用于存储序列(遗传或蛋白质): >id1 序列1可以在几行上 >id2 序列2 我运行了一个以tsv格式提供信息的工具: 标识、长度和标识的位置(以字节为单位) 现在我要做的是按照长度列对这个文件进行排序,然后解析这个文件并使用seek检索相应的序列,然后将它附加到一个新文件中 # this fonction will get the sequence using seek
# this fonction will get the sequence using seek
def get_seq(file, bites):
with open(file) as f_:
f_.seek(bites, 0) # go to the line of interest
line = f_.readline().strip() # this line is the begin of the
#sequence
to_return = "" # init the string which will contains the sequence
while not line.startswith('>') or not line: # while we do not
# encounter another identifiant
to_return += line
line = f_.readline().strip()
return to_return
# simply append to a file the id and the sequence
def write_seq(out_file, id_, sequence):
with open(out_file, 'a') as out_file:
out_file.write('>{}\n{}\n'.format(id_.strip(), sequence))
# main loop will parse the index file and call the function defined below
with open(args.fai) as ref:
indice = 0
for line in ref:
spt = line.split()
id_ = spt[0]
seq = get_seq(args.i, int(spt[2]))
write_seq(out_file=args.out, id_=id_, sequence=seq)
我的问题是以下是真的很慢,这是正常的(需要几天)?我还有别的办法吗?我不是一个纯粹的信息学家,所以我可能会错过一些要点,但我相信索引文件和使用seek是实现这一点的最致命的方法。我错了吗?似乎为每个序列打开两个文件可能会对运行时间造成很大影响。您可以将文件句柄传递给get/write函数,而不是文件名,但我建议使用已建立的fasta解析器/索引器,如biopython或samtools。下面是一个使用samtools的(未经测试的)解决方案:
subprocess.call(["samtools", "faidx", args.i])
with open(args.fai) as ref:
for line in ref:
spt = line.split()
id_ = spt[0]
subprocess.call(["samtools", "faidx", args.i, id_, ">>", args.out], shell=True)
bash和一些基本的unix命令(csplit是线索)怎么样?我写了这个简单的脚本,但是你可以自定义/改进它。它不是高度优化的,也不使用索引文件,但可能运行得更快
csplit -z -f tmp_fasta_file_ $1 '/>/' '{*}'
for file in tmp_fasta_file_*
do
TMP_FASTA_WC=$(wc -l < $file | tr -d ' ')
FASTA_WC+=$(echo "$file $TMP_FASTA_WC\n")
done
for filename in $(echo -e $FASTA_WC | sort -k2 -r -n | awk -F" " '{print $1}')
do
cat "$filename" >> $2
done
rm tmp_fasta_file*
csplit-z-f tmp\u fasta\u文件\uu$1'/>/'{*}
对于tmp_fasta_文件中的文件_*
做
TMP_FASTA_WC=$(WC-l<$file | tr-d'')
FASTA_WC+=$(回显“$文件$TMP_FASTA_WC\n”)
完成
文件名为$(echo-e$FASTA_WC | sort-k2-r-n | awk-F“”{print$1})
做
cat“$filename”>>$2
完成
rm tmp_fasta_文件*
第一个位置参数是指向fasta文件的文件路径,第二个位置参数是用于输出的文件路径,即
/script.sh input.fasta output.fasta
使用修改后的fastq sort版本(当前位于),我们可以使用添加的-L
选项将文件转换为fastq格式,并转换回fasta:
cat test.fasta \
| tee >(wc -l > nb_lines_fasta.txt) \
| bioawk -c fastx '{l = length($seq); printf "@"$name"\n"$seq"\n+\n%.*s\n", l, "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"}' \
| tee >(wc -l > nb_lines_fastq.txt) \
| fastq-sort -L \
| tee >(wc -l > nb_lines_fastq_sorted.txt) \
| bioawk -c fastx '{print ">"$name"\n"$seq}' \
| tee >(wc -l > nb_lines_fasta_sorted.txt) \
> test_sorted.fasta
fasta->fastq转换步骤非常难看。我们需要生成与序列长度相同的伪fastq质量。我发现(bio)awk没有比这个基于本文末尾提到的“动态宽度”的攻击更好的方法了
iiii…
字符串应该比输入序列的最长长度长,否则,将获得无效的fastq,当转换回fasta时,bioawk似乎会默默地跳过这些无效读取
在上面的示例中,我添加了计算行数的步骤。如果行号不一致,可能是因为iiii…
字符串太短
生成的fasta文件将首先具有较短的序列。
要获取文件顶部的最长序列,请将-r
选项添加到fastq sort
请注意,fastq sort
在/tmp
中写入中间文件。如果由于某种原因,在删除它们之前中断,您可能希望手动清理/tmp
,而不是等待下次重新启动
编辑
实际上,我找到了一种更好的方法来生成与序列长度相同的伪质量:只需使用序列本身:
cat test.fasta \
| bioawk -c fastx '{print "@"$name"\n"$seq"\n+\n"$seq}' \
| fastq-sort -L \
| bioawk -c fastx '{print ">"$name"\n"$seq}' \
> test_sorted.fasta
这个解决方案更干净(速度稍快),但我保留了上面的原始版本,因为
printf
的“动态宽度”功能和使用tee
检查中间数据长度可能很有趣。您也可以非常方便地使用awk
,检查下面的代码:
awk '/^>/ {printf("%s%s\t",(N>0?"\n":""),$0);N++;next;} {printf("%s",$0);} END {printf("\n");}' input.fasta |\
awk -F '\t' '{printf("%d\t%s\n",length($2),$0);}' |\
sort -k1,1n | cut -f 2- | tr "\t" "\n"
此方法和其他方法已发布(例如,使用BBMap的
sortbyname.sh
script),对于类似这样的问题,我强烈推荐这个社区。samtoosl faidx是我用来索引我的文件的工具。对于打开的文件,你显然是对的,我通过这种方式获得了很多速度,谢谢。事实上,samtools faidx的文档说明了“为了使用samtools faidx索引,FASTA文件必须是表单的文本文件“所以我想faidx是一个索引工具,它可以从索引的Fasts中获取序列。就像很多生物信息学软件一样,文档很粗略,但它说faidx可以“以FASTA格式索引引用序列或从索引引用序列中提取子序列。如果未指定区域,faidx将索引文件并在磁盘上创建.fai。如果指定了区域,将检索子序列并以FASTA格式打印到标准输出。“如果只给出不带坐标的序列名,它会将整个序列视为区域,这肯定比python更有效,谢谢。这很有趣,显然速度更快,但它必须创建超过10**8子文件。每个子文件的最小大小为4,0kb不是一个好的解决方案,但我肯定应该寻找C/C++代码,而不是pythonWhy 10**8子文件?这个脚本为每个序列创建文件,而不是每行…我有10多个**8序列是我的错,我将编辑问题。更具体地说,这就是改变一切;)所以4kb的限制很痛苦,因为有很多短序列?4kb只是一个空文件的重量,我错了吗?但基本上是的,有100到500个字符之间的序列。我没有尝试使用10^8个序列,但对于我包含大约450万个短序列的示例文件,以下基于Biopython的方法使用了几GB的RAM工作:sortedrecs=sorted(SeqIO.parse(/tmp/test.fasta),format=“fasta”),key=lambda rec:len(rec.seq))
。在python中,这可能不是表示fasta序列最简单的方法,因此可能还有改进的余地。另一个想法是修改fastq排序代码,使其使用序列长度进行排序().我得到了一些基于fastq工具的东西,但它需要fastq格式的输入:我请求将其添加到fastq工具:我添加了一个