按序列大小排序fasta

时间:2016-12-20 09:59:06

标签: 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
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)

我的问题是以下是真的很慢是否正常(需要几天)?我还有其他办法吗?我不是一个纯粹的信息,所以我可能会错过一些观点,但我相信索引文件和使用搜索是实现这个错误的最好方法吗?

4 个答案:

答案 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 脚本),对于此类问题,我强烈推荐该社区。