从单个字符串有效地计算统计数据(由bowtie2的bam文件)

时间:2015-09-23 15:07:05

标签: parsing optimization bioinformatics

我的目标是有效地将包含短DNA测序读数的bowtie2映射的bam文件转换为包含映射开始和百分比同一性的简单表。我即将完成此任务,但我的解决方案非常缓慢,无法处理重要的异常。我将逐步解释这种情况:

我们从像这样的字符串开始

    FCC5G2YACXX:5:1101:1224:2059#NNNNNNNN   97  genome  96003934    24  118M4D11M   =   96004135    0   GCA....ACG  P\..GW^EO   AS:i:-28    XN:i:0  XM:i:2  XO:i:1  XG:i:4  NM:i:6  MD:Z:54G53T9^TACA11 YT:Z:UP

我们只采用第四列和MD:Z:54G53T9^TACA11部分,后者表示匹配(数字)和不匹配(字母)。除非字母前面有' ^'然后字母是参考序列中的删除。

然后我把它计算成一个像96003934 98.00

这样的字符串

第一列与原始输入的第四列相同,第二列是匹配,除以总和匹配和不匹配。

由于我更喜欢​​bash / zsh脚本,所以我做了以下

    if_sam2tab() {
    tab=$(echo $1 | rev | cut -d '.' -f 2- | rev)
    if      [ ! -e ./bowtie_results/$tab.tab ]
    then    echo -e "rstart\tmatch\tmismatch" > ./bowtie_results/$tab.tab
            while   read -r l
            do      rstart=$(echo $l | cut -f 4 -d " "      )
                    t=$(echo $l | grep -o 'MD:Z:[0-9A-Z]*' )
                    match=$(echo ${t: 5} | tr '[a-zA-Z]' '+' | bc )
                    mismatch=$(echo ${t: 5} | tr -d '[0-9]\n' | wc -c )
                    sum=$(echo "$match + $mismatch" | bc )
                    id=$(echo "scale=2; $match / $sum *100"         | bc  )
                    echo -e "$rstart\t$id" >> ./bowtie_results/$tab.tab
            done < <(grep 'MD:Z' ./bowtie_results/$1 )
    fi
    }

然而,此解决方案有问题,因为它将^TCTAAG等删除视为不匹配。

其次它对我来说似乎非常慢,即使我在六个CPU上并行运行它们中的五个。

重述一下,我的目标是有效地将带有映射信息的字符串转换为身份百分比。

感谢您的考虑

2 个答案:

答案 0 :(得分:2)

Jose对前一个答案的补充:MD字符串不一定是第18列。因此,我在Jose的awk脚本中添加了一行来查找MD字符串,而不管该行中的位置如何。毫无疑问,在整个过程中添加一个正则表达式步骤会使整个过程变慢。

/repoName

我选择直接在这个awk脚本中管道bowtie输出而不将其保存在磁盘上。在我的有限测试中,我没有发现磁盘i / o是限制的,也没有发现直接输入awk的管道bowtie2输出大大降低了同时运行时的整体性能。

答案 1 :(得分:1)

  • 使用二进制数据(bam文件)输入和输出要快得多,但你有一个sam文件(平面版)

  • 正如@cel之前评论过的那样,用编译语言(C,C ++等)编写的程序总是比脚本(ej,bash,awk等)更快

我在awk中显示了一个脚本,供您尝试

awk '{
    split($18,v,/[\^:]/); 
    nmatch = split(v[3],vmatch, /[^0-9]/); 
    cmatch=0; 
    for(i=1; i<=nmatch; i++) cmatch+=vmatch[i]; 
    printf("%s"OFS"%.2f\n", $4, cmatch*100/(cmatch+nmatch-1));
}' file.sam

你得到了

96003934 98.31

<强>解释

第18栏:MD:Z:54G53T9^TACA11

匹配= 54 + 53 + 9 = 116

mismatch = count_letter(54G53T9)= 2

id = 116 /(116 + 2)= 0.9830508474576272