我目前想要按序列大小对hudge fasta文件(+ 10 ** 8行和序列)进行排序。 fasta是生物学用于存储序列(遗传或蛋白质)的明确定义格式:
> ID1
序列1#可以在几行
> ID2
序列2
...
我运行的工具以tsv格式提供给我:
标识符的标识符,长度和字节数。
现在我要做的是按长度列对此文件进行排序,然后解析此文件并使用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)
我的问题是以下是真的很慢是否正常(需要几天)?我还有其他办法吗?我不是一个纯粹的信息,所以我可能会错过一些观点,但我相信索引文件和使用搜索是实现这个错误的最好方法吗?
答案 0 :(得分:2)
似乎为每个序列打开两个文件可能会对运行时间产生很大影响。您可以将文件句柄传递给您的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)
答案 1 :(得分:2)
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*
第一个位置参数是fasta文件的文件路径,第二个是输出的文件路径,即./script.sh input.fasta output.fasta
答案 2 :(得分:0)
使用fastq-sort的修改版本(目前可在https://github.com/blaiseli/fastq-tools获得),我们可以使用bioawk将文件转换为fastq格式,并使用我添加的-L
选项进行排序,以及转换回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 - &gt; fastq转换步骤非常难看。我们需要生成与序列长度相同的伪fastq质量。基于https://www.gnu.org/software/gawk/manual/html_node/Format-Modifiers.html#Format-Modifiers末尾提到的“动态宽度”事情,我发现使用(生物)awk比使用黑客更好的方法。
IIIII...
字符串应该长于输入序列中的最长字符串,否则将获得无效的fastq,并且当转换回fasta时,bioawk似乎默默地跳过这样的无效读取。
在上面的例子中,我添加了计算行数的步骤。如果行号不一致,可能是因为IIIII...
字符串太短。
生成的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
用于检查中间数据长度的功能可能很有趣了解。
答案 3 :(得分:0)
您也可以使用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"
此方法和其他方法已在 Biostars 中发布(例如使用 BBMap 的 sortbyname.sh
脚本),对于此类问题,我强烈推荐该社区。p>