<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>生信菜鸟团 &#187; bwt</title>
	<atom:link href="http://www.bio-info-trainee.com/tag/bwt/feed" rel="self" type="application/rss+xml" />
	<link>http://www.bio-info-trainee.com</link>
	<description>欢迎去论坛biotrainee.com留言参与讨论，或者关注同名微信公众号biotrainee</description>
	<lastBuildDate>Sat, 28 Jun 2025 14:30:13 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.33</generator>
	<item>
		<title>Bowtie算法第六讲-tally法对bwt索引进行搜索</title>
		<link>http://www.bio-info-trainee.com/650.html</link>
		<comments>http://www.bio-info-trainee.com/650.html#comments</comments>
		<pubDate>Sat, 18 Apr 2015 14:46:04 +0000</pubDate>
		<dc:creator><![CDATA[ulwvfje]]></dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[bowtie]]></category>
		<category><![CDATA[bwt]]></category>
		<category><![CDATA[tally]]></category>

		<guid isPermaLink="false">http://www.bio-info-trainee.com/?p=650</guid>
		<description><![CDATA[因为要讲搜索，所以我选择了一个长一点的字符串来演示多种情况的搜索 perl ro &#8230; <a href="http://www.bio-info-trainee.com/650.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>因为要讲搜索，所以我选择了一个长一点的字符串来演示多种情况的搜索</p>
<p>perl rotation_one_by_one.pl atgtgtcgtagctcgtnncgt</p>
<p>程序运行的结果如下</p>
<p>$ATGTGTCGTAGCTCGTNNCGT 21</p>
<p>AGCTCGTNNCGT$ATGTGTCGT 9</p>
<p>ATGTGTCGTAGCTCGTNNCGT$ 0</p>
<p>CGT$ATGTGTCGTAGCTCGTNN 18</p>
<p>CGTAGCTCGTNNCGT$ATGTGT 6</p>
<p>CGTNNCGT$ATGTGTCGTAGCT 13</p>
<p>CTCGTNNCGT$ATGTGTCGTAG 11</p>
<p>GCTCGTNNCGT$ATGTGTCGTA 10</p>
<p>GT$ATGTGTCGTAGCTCGTNNC 19</p>
<p>GTAGCTCGTNNCGT$ATGTGTC 7</p>
<p>GTCGTAGCTCGTNNCGT$ATGT 4</p>
<p>GTGTCGTAGCTCGTNNCGT$AT 2</p>
<p>GTNNCGT$ATGTGTCGTAGCTC 14</p>
<p>NCGT$ATGTGTCGTAGCTCGTN 17</p>
<p>NNCGT$ATGTGTCGTAGCTCGT 16</p>
<p>T$ATGTGTCGTAGCTCGTNNCG 20</p>
<p>TAGCTCGTNNCGT$ATGTGTCG 8</p>
<p>TCGTAGCTCGTNNCGT$ATGTG 5</p>
<p>TCGTNNCGT$ATGTGTCGTAGC 12</p>
<p>TGTCGTAGCTCGTNNCGT$ATG 3</p>
<p>TGTGTCGTAGCTCGTNNCGT$A 1</p>
<p>TNNCGT$ATGTGTCGTAGCTCG 15</p>
<p>它的BWT及索引是</p>
<p>T 21</p>
<p>T 9</p>
<p>$ 0</p>
<p>N 18</p>
<p>T 6</p>
<p>T 13</p>
<p>G 11</p>
<p>A 10</p>
<p>C 19</p>
<p>C 7</p>
<p>T 4</p>
<p>T 2</p>
<p>C 14</p>
<p>N 17</p>
<p>T 16</p>
<p>G 20</p>
<p>G 8</p>
<p>G 5</p>
<p>C 12</p>
<p>G 3</p>
<p>A 1</p>
<p>G 15</p>
<p>然后得到它的tally文件如下</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/04/图片1.png"><img class="alignnone size-full wp-image-651" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/04/图片1.png" alt="图片1" width="418" height="423" /></a></p>
<p>接下来用我们的perl程序在里面找字符串</p>
<p>第一次我测试 GTGTCG 这个字符串，程序可以很清楚的看到它的查找过程。</p>
<p>perl search_char.pl    GTGTCG   tm.tally</p>
<p>your last char is G</p>
<p>start is 7 ; and end is 13</p>
<p>now it is number 5 and the char is C</p>
<p>start is 3 ; and end is 6</p>
<p>now it is number 4 and the char is T</p>
<p>start is 17 ; and end is 19</p>
<p>now it is number 3 and the char is G</p>
<p>start is 10 ; and end is 11</p>
<p>now it is number 2 and the char is T</p>
<p>start is 19 ; and end is 20</p>
<p>now it is number 1 and the char is G</p>
<p>start is 11 ; and end is 12</p>
<p>It is just one perfect match !</p>
<p>The index is 2</p>
<p>第二次我测试一个多重匹配的字符串GT，在原字符串出现了五次的</p>
<p>perl search_char.pl  GT  tm.tally</p>
<p>your last char is T</p>
<p>start is 15 ; and end is 22</p>
<p>now it is number 1 and the char is G</p>
<p>start is 8 ; and end is 13</p>
<p>we find more than one perfect match!!!</p>
<p>8 13</p>
<p>One of the index is 11</p>
<p>One of the index is 10</p>
<p>One of the index is 19</p>
<p>One of the index is 7</p>
<p>One of the index is 4</p>
<p>One of the index is 2</p>
<p>One of the index is 14</p>
<p>惨了，这个是很严重的bug，不知道为什么，对于多个匹配总是会多出那么一点点的结果。</p>
<p>去转换矩阵里面查看，可知，前面两个结果11和10是错误的。</p>
<p>CTCGTNNCGT$ATGTGTCGTAG 11</p>
<p>GCTCGTNNCGT$ATGTGTCGTA 10</p>
<p>GT$ATGTGTCGTAGCTCGTNNC 19</p>
<p>GTAGCTCGTNNCGT$ATGTGTC 7</p>
<p>GTCGTAGCTCGTNNCGT$ATGT 4</p>
<p>GTGTCGTAGCTCGTNNCGT$AT 2</p>
<p>GTNNCGT$ATGTGTCGTAGCTC 14</p>
<p>最后我们测试未知字符串的查找。</p>
<p>perl search_char.pl ACATGTGT tm.tally</p>
<p>your last char is T</p>
<p>start is 15 ; and end is 22</p>
<p>now it is number 7 and the char is G</p>
<p>start is 8 ; and end is 13</p>
<p>now it is number 6 and the char is T</p>
<p>start is 19 ; and end is 21</p>
<p>now it is number 5 and the char is G</p>
<p>start is 11 ; and end is 12</p>
<p>now it is number 4 and the char is T</p>
<p>start is 20 ; and end is 21</p>
<p>now it is number 3 and the char is A</p>
<p>start is 2 ; and end is 3</p>
<p>now it is number 2 and the char is C</p>
<p>start is 3 ; and end is 3</p>
<p>we can just find the last 6 char ,and it is ATGTGT</p>
<p>原始字符串是ATGTGTCGTAGCTCGTNNCGT，所以查找的挺对的！！！</p>
<p>&nbsp;</p>
<p>[perl]</p>
<p>$a=$ARGV[0];</p>
<p>$a=uc $a;</p>
<p>open FH,&quot;&lt;$ARGV[1]&quot;;</p>
<p>while(&lt;FH&gt;){</p>
<p>chomp;</p>
<p>@F=split;</p>
<p>$hash_count_atcg{$F[0]}++;</p>
<p>$hash{$.}=$_;</p>
<p># the first line is $ and the last char and the last index !</p>
<p>}</p>
<p>$all_a=$hash_count_atcg{'A'};</p>
<p>$all_c=$hash_count_atcg{'C'};</p>
<p>$all_g=$hash_count_atcg{'G'};</p>
<p>$all_n=$hash_count_atcg{'N'};</p>
<p>$all_t=$hash_count_atcg{'T'};</p>
<p>#print &quot;$all_a\t$all_c\t$all_g\t$all_t\n&quot;;</p>
<p>$len_a=length $a;</p>
<p>$end_a=$len_a-1;</p>
<p>#print &quot;your query is $a\n&quot;;</p>
<p>#print &quot;and the length of your query is $len_a \n&quot;;</p>
<p>$after=substr($a,$end_a,1);</p>
<p>#we fill search your query from the last char !</p>
<p>if ($after eq 'A') {</p>
<p>$start=2;</p>
<p>$end=$all_a+1;</p>
<p>}</p>
<p>elsif ($after eq 'C') {</p>
<p>$start=$all_a+1;</p>
<p>$end=$all_a+$all_c+1;</p>
<p>}</p>
<p>elsif ($after eq 'G') {</p>
<p>$start=$all_a+$all_c+1;</p>
<p>$end=$all_a+$all_c+$all_g+1;</p>
<p>}</p>
<p>elsif ($after eq 'T'){</p>
<p>$start=$all_a+$all_c+$all_g+$all_n+1;</p>
<p>$end=$all_a+$all_c+$all_g+$all_t+$all_n+1;</p>
<p>}</p>
<p>else {die &quot;error !!! we just need A T C G !!!\n&quot;}</p>
<p>print &quot;your last char is $after\n &quot;;</p>
<p>print &quot;start is $start ; and end is $end \n&quot;;</p>
<p>foreach (reverse (1..$end_a)){</p>
<p>$after=substr($a,$_,1);</p>
<p>$before=substr($a,$_-1,1);</p>
<p>($start,$end)=&amp;find_level($after,$before,$start,$end);</p>
<p>print &quot;now it is number $_ and the char is $before \n &quot;;</p>
<p>print &quot;start is $start ; and end is $end \n&quot;;</p>
<p>if ($_  &gt; 1 &amp;&amp; $start == $end) {</p>
<p>$find_char=substr($a,$_);</p>
<p>$find_len=length $find_char;</p>
<p>print &quot;we can just find the last $find_len char ,and it is $find_char \n&quot;;</p>
<p>#return &quot;miss&quot;;</p>
<p>last;</p>
<p>}</p>
<p>if ($_ == 1) {</p>
<p>if (($end-$start)==1) {</p>
<p>print &quot;It is just one perfect match ! \n&quot;;</p>
<p>my @F_start=split/\s+/,$hash{$end};</p>
<p>print &quot;The index is $F_start[1]\n&quot;;</p>
<p>#return $F_start[1];</p>
<p>last;</p>
<p>}</p>
<p>else {</p>
<p>print &quot;we find more than one perfect match!!!\n&quot;;</p>
<p>print &quot;$start\t$end\n&quot;;</p>
<p>foreach  (($start-1)..$end) {</p>
<p>my @F_start=split/\s+/,$hash{$_};</p>
<p>print &quot;One of the index is $F_start[1]\n&quot;;</p>
<p>}</p>
<p>#return &quot;multiple&quot;;</p>
<p>last;</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>sub find_level{</p>
<p>my($after,$before,$start,$end)=@_;</p>
<p>my @F_start=split/\s+/,$hash{$start};</p>
<p>my @F_end=split/\s+/,$hash{$end};</p>
<p>if ($before eq 'A') {</p>
<p>return ($F_start[2]+1,$F_end[2]+1);</p>
<p>}</p>
<p>elsif ($before eq 'C') {</p>
<p>return ($all_a+$F_start[3]+1,$all_a+$F_end[3]+1);</p>
<p>}</p>
<p>elsif ($before eq 'G') {</p>
<p>return ($all_a+$all_c+1+$F_start[4],$all_a+$all_c+1+$F_end[4]);</p>
<p>}</p>
<p>elsif ($before eq 'T') {</p>
<p>return ($all_a+$all_c+$all_g+$all_n+1+$F_start[5],$all_a+$all_c+$all_g+1+$all_n+$F_end[5]);</p>
<p>}</p>
<p>else {die &quot;error !!! we just need A T C G !!!\n&quot;}</p>
<p>}</p>
<p>[/perl]</p>
<p>&nbsp;</p>
<p>原始字符串是atgtgtcgtagctcgtnncgt</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bio-info-trainee.com/650.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bowtie算法第五讲-index2tally</title>
		<link>http://www.bio-info-trainee.com/648.html</link>
		<comments>http://www.bio-info-trainee.com/648.html#comments</comments>
		<pubDate>Sat, 18 Apr 2015 14:02:47 +0000</pubDate>
		<dc:creator><![CDATA[ulwvfje]]></dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[生信基础]]></category>
		<category><![CDATA[bwt]]></category>
		<category><![CDATA[tally]]></category>

		<guid isPermaLink="false">http://www.bio-info-trainee.com/?p=648</guid>
		<description><![CDATA[前面讲到了如何用笨方法进行字符串搜索，也讲了如何构建bwt索引，和把bwt索引还 &#8230; <a href="http://www.bio-info-trainee.com/648.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>前面讲到了如何用笨方法进行字符串搜索，也讲了如何构建bwt索引，和把bwt索引还原成字符串！</p>
<p>原始字符串是ATGCGTANNGTC</p>
<p>排序过程是下面的</p>
<p>$ATGCGTANNGTC 12</p>
<p>ANNGTC$ATGCGT 6</p>
<p>ATGCGTANNGTC$ 0</p>
<p>C$ATGCGTANNGT 11</p>
<p>CGTANNGTC$ATG 3</p>
<p>GCGTANNGTC$AT 2</p>
<p>GTANNGTC$ATGC 4</p>
<p>GTC$ATGCGTANN 9</p>
<p>NGTC$ATGCGTAN 8</p>
<p>NNGTC$ATGCGTA 7</p>
<p>TANNGTC$ATGCG 5</p>
<p>TC$ATGCGTANNG 10</p>
<p>TGCGTANNGTC$A 1</p>
<p>现在讲讲如何根据bwt索引构建tally，并且用tally搜索方法来搜索字符串！</p>
<p>首先是bwt索引转换为tally</p>
<p>C 12</p>
<p>T 6</p>
<p>$ 0</p>
<p>T 11</p>
<p>G 3</p>
<p>T 2</p>
<p>C 4</p>
<p>N 9</p>
<p>N 8</p>
<p>A 7</p>
<p>G 5</p>
<p>G 10</p>
<p>A 1</p>
<p>这个其实非常简单的，tally就是增加四列计数的列即可</p>
<p>[perl]</p>
<p>$hash_count{'A'}=0;</p>
<p>$hash_count{'C'}=0;</p>
<p>$hash_count{'G'}=0;</p>
<p>$hash_count{'T'}=0;</p>
<p>open FH ,&quot;&lt;$ARGV[0]&quot;;</p>
<p>while(&lt;FH&gt;){</p>
<p>        chomp;</p>
<p> @F=split;</p>
<p> $last=$F[0]; # 读取上面的tally文件，分列，判断第一列，并计数</p>
<p>        $hash_count{$last}++;</p>
<p>   print  &quot;$_\t$hash_count{'A'}\t$hash_count{'C'}\t$hash_count{'G'}\t$hash_count{'T'}\n&quot;;</p>
<p>}</p>
<p>[/perl]</p>
<p>输出的tally如下</p>
<p>C 12 0 1 0 0</p>
<p>T 6 0 1 0 1</p>
<p>$ 0 0 1 0 1</p>
<p>T 11 0 1 0 2</p>
<p>G 3 0 1 1 2</p>
<p>T 2 0 1 1 3</p>
<p>C 4 0 2 1 3</p>
<p>N 9 0 2 1 3</p>
<p>N 8 0 2 1 3</p>
<p>A 7 1 2 1 3</p>
<p>G 5 1 2 2 3</p>
<p>G 10 1 2 3 3</p>
<p>A 1 2 2 3 3</p>
<p>接下来就是针对这个tally的查询函数了</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bio-info-trainee.com/648.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bowtie 算法第四讲</title>
		<link>http://www.bio-info-trainee.com/646.html</link>
		<comments>http://www.bio-info-trainee.com/646.html#comments</comments>
		<pubDate>Sat, 18 Apr 2015 11:51:18 +0000</pubDate>
		<dc:creator><![CDATA[ulwvfje]]></dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[bowtie]]></category>
		<category><![CDATA[bwa]]></category>
		<category><![CDATA[bwt]]></category>

		<guid isPermaLink="false">http://www.bio-info-trainee.com/?p=646</guid>
		<description><![CDATA[由于之前就简单的看了看bowtie作者的ppt，没有完全吃透就开始敲代码了，写了 &#8230; <a href="http://www.bio-info-trainee.com/646.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>由于之前就简单的看了看bowtie作者的ppt，没有完全吃透就开始敲代码了，写了十几个程序最后我自己都搞不清楚进展到哪一步了，所以我现在整理一下，从新开始！！！</p>
<p>&nbsp;</p>
<p>首先，bowtie的作用就是在一个大字符串里面搜索一个小字符串！那么本身就有一个非常笨的复杂方法来搜索，比如，大字符串长度为100万，小字符串为10，那么就依次取出大字符串的10个字符来跟小字符串比较即可，这样的算法是非常不经济的，我简单用perl代码实现一下。</p>
<p>[perl]</p>
<p>#首先读取大字符串的fasta文件</p>
<p>open FH ,&quot;&lt;$ARGV[0]&quot;;</p>
<p>$i=0;</p>
<p>while (&lt;FH&gt;) {</p>
<p>next if /^&gt;/;</p>
<p>chomp;</p>
<p>$a.=(uc);</p>
<p>}</p>
<p>#print &quot;$a\n&quot;;</p>
<p>#然后接受我们的小的查询字符串</p>
<p>$query=uc $ARGV[1];</p>
<p>$len=length $a;</p>
<p>$len_query=length $query;</p>
<p>$a=$a.'$'.$a;</p>
<p>#然后依次循环取大字符串来精确比较！</p>
<p>foreach (0..$len-1){</p>
<p>if (substr($a,$_,$len_query) eq $query){</p>
<p>print &quot;$_\n&quot;;</p>
<p>#last;</p>
<p>}</p>
<p>}</p>
<p>[/perl]</p>
<p>&nbsp;</p>
<p>这样在时间复杂度非常恐怖，尤其是对人的30亿碱基。</p>
<p>&nbsp;</p>
<p>正是因为这样的查询效率非常低，所以我们才需要用bwt算法来构建索引，然后根据tally来进行查询</p>
<p>其中构建索引有三种方式，我首先讲最效率最低的那种索引构造算法，就是依次取字符串进行旋转，然后排序即可。</p>
<p>[perl]</p>
<p>$a=uc $ARGV[0];</p>
<p>$len=length $a;</p>
<p>$a=$a.'$'.$a;</p>
<p>foreach (0..$len){</p>
<p>$hash{substr($a,$_,$len+1)}=$_;</p>
<p>}</p>
<p>#print &quot;$_\t$hash{$_}\n&quot; foreach sort keys %hash;</p>
<p>print  substr($_,-1),&quot;\t$hash{$_}\n&quot; foreach sort keys %hash;</p>
<p>[/perl]</p>
<p>这个算法从时间复杂度来讲是非常经济的，对小字符串都是瞬间搞定！！！</p>
<p>perl rotation_one_by_one.pl atgcgtanngtc 这个字符串的BWT矩阵索引如下！</p>
<p>C 12</p>
<p>T 6</p>
<p>$ 0</p>
<p>T 11</p>
<p>G 3</p>
<p>T 2</p>
<p>C 4</p>
<p>N 9</p>
<p>N 8</p>
<p>A 7</p>
<p>G 5</p>
<p>G 10</p>
<p>A 1</p>
<p>但同样的，它也有一个无法避免的弊端，就是内存消耗太恐怖。对于30亿的人类碱基来说，这样旋转会生成30亿乘以30亿的大矩阵，一般的服务器根本hold不住的。</p>
<p>&nbsp;</p>
<p>最后我讲一下，这个BWT矩阵索引如何还原成原字符串，这个没有算法的差别，因为就是很简单的原理。</p>
<p>[perl]</p>
<p>#first read the tally !!!</p>
<p>#首先读取上面输出的BWT矩阵索引文件。</p>
<p>open FH,&quot;&lt;$ARGV[0]&quot;;</p>
<p>$hash_count{'A'}=0;</p>
<p>$hash_count{'C'}=0;</p>
<p>$hash_count{'G'}=0;</p>
<p>$hash_count{'T'}=0;</p>
<p>while(&lt;FH&gt;){</p>
<p>        chomp;</p>
<p>        @F=split;</p>
<p>        $hash_count{$F[0]}++;</p>
<p>        $hash{$.}=&quot;$F[0]\t$F[1]\t$hash_count{$F[0]}&quot;;</p>
<p>#print &quot;$hash{$.}\n&quot;;</p>
<p>}</p>
<p>$all_a=$hash_count{'A'};        </p>
<p>$all_c=$hash_count{'C'};        </p>
<p>$all_g=$hash_count{'G'};        </p>
<p>$all_t=$hash_count{'T'};</p>
<p>$all_n=$hash_count{'N'};</p>
<p>#start from the first char !</p>
<p>$raw='';</p>
<p>&amp;restore(1);</p>
<p>sub restore{</p>
<p>my($num)=@_;</p>
<p>my @F=split/\t/,$hash{$num};</p>
<p>$raw.=$F[0];</p>
<p>   my $before=$F[0];</p>
<p>     if ($before eq 'A') { </p>
<p>$new=$F[2]+1;</p>
<p>        }</p>
<p>        elsif ($before eq 'C') {</p>
<p>               $new=1+$all_a+$F[2];</p>
<p>        }</p>
<p>        elsif ($before eq 'G') {</p>
<p>               $new=1+$all_a+$all_c+$F[2];</p>
<p>        }</p>
<p>elsif ($before eq 'N') {</p>
<p>                $new =1+$all_a+$all_c+$all_g+$F[2];</p>
<p>        }</p>
<p>        elsif ($before eq 'T') {</p>
<p>                $new=1+$all_a+$all_c+$all_g+$all_n+$F[2];</p>
<p>        }</p>
<p>        elsif ($before eq '$') {</p>
<p>chop $raw;</p>
<p>                $raw = reverse $raw;</p>
<p>print &quot;$raw\n&quot;;</p>
<p>exit;</p>
<p>        }</p>
<p>else {die &quot;error !!! we just need A T C N G !!!\n&quot;}</p>
<p>#print &quot;$F[0]\t$new\n&quot;;</p>
<p>&amp;restore($new);</p>
<p>}</p>
<p>[/perl]</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bio-info-trainee.com/646.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自己动手写bowtie第三讲：序列查询。</title>
		<link>http://www.bio-info-trainee.com/511.html</link>
		<comments>http://www.bio-info-trainee.com/511.html#comments</comments>
		<pubDate>Sat, 28 Mar 2015 02:24:31 +0000</pubDate>
		<dc:creator><![CDATA[ulwvfje]]></dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[bowtie]]></category>
		<category><![CDATA[bwt]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.bio-info-trainee.com/?p=511</guid>
		<description><![CDATA[查询需要根据前面建立的索引来做。 这是一个比较复杂的过程，我也是看了bowtie &#8230; <a href="http://www.bio-info-trainee.com/511.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>查询需要根据前面建立的索引来做。</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲532.png"><img class="alignnone size-full wp-image-506" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲532.png" alt="BWT算法第二讲532" width="554" height="427" /></a></p>
<p>这是一个比较复杂的过程，我也是看了bowtie的作者的ppt才慢慢弄懂的，感觉自己也不可能三言两语就说清楚，一般都是辅助图片，动画，再经过多方交流才能慢慢理解。</p>
<p>所以大家呢，就自己去看ppt，看懂那个查询算法。（ppt及代码在我的群里面有共享，欢迎大家加群交流）</p>
<p>这里我简单讲讲我的程序</p>
<p>首先读取索引文件，统计好A,C,G,T的总数</p>
<p>然后把查询序列从最后一个字符往前面回溯。</p>
<p>我创建了一个子函数，专门来处理回溯的问题</p>
<p>每次接受四个参数（左右两端的碱基，上下的阈值），并返回两个参数（新的上下两个阈值）</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询261.png"><img class="alignnone size-full wp-image-512" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询261.png" alt="自己动手写bowtie之三序列查询261" width="554" height="225" /></a></p>
<p>大家要看懂阈值是如何更新迭代，这样动态的一个个回溯字符串，一个个迭代阈值。</p>
<p>直到四种临界情况的出现。</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询477.png"><img class="alignnone size-full wp-image-513" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询477.png" alt="自己动手写bowtie之三序列查询477" width="554" height="342" /></a></p>
<p>第一是上下阈值已经相等了，但是我们还没有回溯完全，那就说明字符串只能查找后几个字符，前面还有字符是无法匹配的</p>
<p>第二种情况是上下阈值已经相等了，正巧我们也回溯到了最后一个字符串，那么我们就找到了精确匹配。</p>
<p>第三种情况是已经进行到了最后一个字符串，但是上下阈值还有差值，那么就找到了多个精确匹配点。</p>
<p>最后一种情况是各种非法字符。</p>
<p>然后我简单的测序了一下在病毒的5K基因组里面的精确匹配情况，好像效果还挺好的</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询518.png"><img class="alignnone size-full wp-image-514" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/自己动手写bowtie之三序列查询518.png" alt="自己动手写bowtie之三序列查询518" width="554" height="391" /></a></p>
<p>但是在酵母里面还有一个问题没有解决，就是取前二十个字符串排序的问题，不够精确，需要重新审视排序结果进行局部优化，可能是需要用堆排序发，具体我还得考虑一个星期，只能等下周上课再看看了，平时太忙了，基本没时间码代码。</p>
<p>这里贴上我的代码给大家看看，</p>
<p>[perl]</p>
<p>$a='CGCTATGTACTGGATGCGCTGGCAAACGAGCCTGCCGTAAG';</p>
<p>while(&lt;&gt;){</p>
<p>chomp;</p>
<p>@F=split;</p>
<p>$hash_count_atcg{$F[0]}++;</p>
<p>$hash{$.}=$_;</p>
<p>}</p>
<p>$all_a=$hash_count_atcg{'A'};</p>
<p>$all_c=$hash_count_atcg{'C'};</p>
<p>$all_g=$hash_count_atcg{'G'};</p>
<p>$all_t=$hash_count_atcg{'T'};</p>
<p>#print &quot;$all_a\t$all_c\t$all_g\t$all_t\n&quot;;</p>
<p>$len_a=length $a;</p>
<p>$end_a=$len_a-1;</p>
<p>print &quot;your query is $a\n&quot;;</p>
<p>print &quot;and the length of your query is $len_a \n&quot;;</p>
<p>foreach (reverse (0..$end_a)){</p>
<p>$after=substr($a,$_,1);</p>
<p>$before=substr($a,$_-1,1);</p>
<p>#对第一个字符进行找阈值的时候，我们需要人为的定义起始点！</p>
<p>if($_ == $end_a){</p>
<p>if ($after eq 'A') {</p>
<p>$start=1;</p>
<p>$end=$all_a;</p>
<p>}</p>
<p>elsif ($after eq 'C') {</p>
<p>$start=$all_a+1;</p>
<p>$end=$all_a+$all_c;</p>
<p>}</p>
<p>elsif ($after eq 'G') {</p>
<p>$start=$all_a+$all_c+1;</p>
<p>$end=$all_a+$all_c+$all_g;</p>
<p>}</p>
<p>elsif ($after eq 'T'){</p>
<p>$start=$all_a+$all_c+$all_g+1;</p>
<p>$end=$all_a+$all_c+$all_g+$all_t;</p>
<p>}</p>
<p>else {print &quot;error !!! we just need A T C G !!!\n&quot;;exit;}</p>
<p>}</p>
<p>#如果阈值已经无法继续分割，但是字符串还未查询完</p>
<p>if ($_  &gt; 0 &amp;&amp; $start == $end) {</p>
<p>$find_char=substr($a,$_);</p>
<p>$find_len=length $find_char;</p>
<p>#这里需要修改，但是不影响完全匹配了</p>
<p>print &quot;we can just find the last $find_len char ,and it is $find_char \n&quot;;</p>
<p>exit;</p>
<p>}</p>
<p>#如果进行到了最后一个字符</p>
<p>if ($_ == 0) {</p>
<p>if ($start == $end) {</p>
<p>print &quot;It is just one perfect match ! \n&quot;;</p>
<p>my @F_start=split/\s+/,$hash{$start};</p>
<p>print &quot;The index is $F_start[1]\n&quot;;</p>
<p>exit;</p>
<p>}</p>
<p>else {</p>
<p>print &quot;we find more than one perfect match!!!\n&quot;;</p>
<p>#print &quot;$start\t$end\n&quot;;</p>
<p>foreach  ($start..$end) {</p>
<p>my @F_start=split/\s+/,$hash{$_};</p>
<p>print &quot;One of the index is $F_start[1]\n&quot;;</p>
<p>}</p>
<p>exit;</p>
<p>}</p>
<p>}</p>
<p>($start,$end)=&amp;find_level($after,$before,$start,$end);</p>
<p>}</p>
<p>sub find_level{</p>
<p>my($after,$before,$start,$end)=@_;</p>
<p>my @F_start=split/\s+/,$hash{$start};</p>
<p>my @F_end=split/\s+/,$hash{$end};</p>
<p>if ($before eq 'A') {</p>
<p>return ($F_start[2],$F_end[2]);</p>
<p>}</p>
<p>elsif ($before eq 'C') {</p>
<p>return ($all_a+$F_start[3],$all_a+$F_end[3]);</p>
<p>}</p>
<p>elsif ($before eq 'G') {</p>
<p>return ($all_a+$all_c+$F_start[4],$all_a+$all_c+$F_end[4]);</p>
<p>}</p>
<p>elsif ($before eq 'T') {</p>
<p>return ($all_a+$all_c+$all_g+$F_start[5],$all_a+$all_c+$all_g+$F_end[5]);</p>
<p>}</p>
<p>else {print &quot;sorry , I can't find the right match!!!\n&quot;;}</p>
<p>}</p>
<p>#perl -alne '{next if /&gt;/;$all.=$_;}END{print substr($all,308,10)}'   lambda_virus.fa </p>
<p>[/perl]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bio-info-trainee.com/511.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自己动手写bowtie第二讲：优化索引</title>
		<link>http://www.bio-info-trainee.com/503.html</link>
		<comments>http://www.bio-info-trainee.com/503.html#comments</comments>
		<pubDate>Sat, 28 Mar 2015 01:56:55 +0000</pubDate>
		<dc:creator><![CDATA[ulwvfje]]></dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[bwt]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.bio-info-trainee.com/?p=503</guid>
		<description><![CDATA[其中第一讲我提到了一个简单的索引产生方式，因为是课堂就半个小时想的，很多细节没有 &#8230; <a href="http://www.bio-info-trainee.com/503.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲192.png"><img class="alignnone size-full wp-image-504" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲192.png" alt="BWT算法第二讲192" width="437" height="368" /></a></p>
<p>其中第一讲我提到了一个简单的索引产生方式，因为是课堂就半个小时想的，很多细节没有考虑到，对病毒那种几K大小的基因组来说是很简单的，速度也非常快，但是我测试了一下酵母，却发现好几个小时都没有结果，我只好kill掉重新改写算法，我发现之前的测序最大的问题在于没有立即substr函数的实现方式，把一个5M的字符串不停的截取首尾字符串好像是一个非常慢的方式。</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲241.png"><img class="alignnone size-full wp-image-505" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲241.png" alt="BWT算法第二讲241" width="554" height="621" /></a></p>
<p>所以我优化了那个字符串的函数，虽然代码量变多了，实现过程也繁琐了一点，但是速度提升了几千倍。</p>
<p>&nbsp;</p>
<p>time perl bwt_new_index.pl e-coli.fa &gt;e-coli.index</p>
<p>测试了一下我的脚本，对酵母这样的5M的基因组，索引耗费时间是43秒</p>
<p>real 0m43.071s</p>
<p>user 0m41.277s</p>
<p>sys 0m1.779s</p>
<p>输出的index矩阵如下，我简单的截取头尾各10行给大家看，一点要看懂这个index。</p>
<p><a href="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲532.png"><img class="alignnone size-full wp-image-506" src="http://www.bio-info-trainee.com/wp-content/uploads/2015/03/BWT算法第二讲532.png" alt="BWT算法第二讲532" width="554" height="427" /></a></p>
<p>首先第一列就是我们的BWT向量，也就是BWT变换后的尾字符</p>
<p>第二列是之前的顺序被BWT变换后的首字符排序后的打乱的顺序。</p>
<p>第三，四，五，六列分别是A,C,G,T的计数，就是在当行之前累积出现的A,C,G,T的数量，是对第一列的统计。</p>
<p>&nbsp;</p>
<p>这个索引文件将会用于下一步的查询，这里贴上我新的索引代码，查询见下一篇文章</p>
<p>[perl]</p>
<p>while (&lt;&gt;){</p>
<p>        next if /&gt;/;</p>
<p>        chomp;</p>
<p>        $a.=$_;</p>
<p>}</p>
<p>$len=length $a;</p>
<p>open FH_F,&quot;&gt;tmp_forward.txt&quot;;</p>
<p>open FH_R,&quot;&gt;tmp_reverse.txt&quot;;</p>
<p>for(my $i=0;$i&lt;=$len-1;$i+=20){</p>
<p>        print FH_F  substr($a,$i,20);</p>
<p>        print FH_F &quot;\n&quot;;</p>
<p>}</p>
<p>$rev_a=reverse $a;</p>
<p>for(my $i=0;$i&lt;=$len-1;$i+=20){</p>
<p>        print FH_R  substr($rev_a,$i,20);</p>
<p>        print FH_R &quot;\n&quot;;</p>
<p>}</p>
<p>close FH_F;</p>
<p>close FH_R;</p>
<p>$a='';</p>
<p>open FH_F,&quot;tmp_forward.txt&quot;;</p>
<p>open FH_R,&quot;tmp_reverse.txt&quot;;</p>
<p>#把前一行的所有20bp碱基当做后一行的头部信息</p>
<p>$residue_F=&lt;FH_F&gt;;</p>
<p>$residue_R=&lt;FH_R&gt;;</p>
<p>$i=0;</p>
<p>while  ($F_reads=&lt;FH_F&gt;){</p>
<p>        $R_reads=&lt;FH_R&gt;;</p>
<p>        $F_merge=$residue_F.$F_reads;</p>
<p>        $R_merge=$residue_R.$R_reads;</p>
<p>#这样每次就需要处理20个碱基</p>
<p>foreach  (0..19) {</p>
<p>$up  =substr($F_merge,$_,20);</p>
<p>                        $down=substr($R_merge,$_,1);</p>
<p>                        $hash{&quot;$up\t$down&quot;}=$i;</p>
<p>                        $i++;</p>
<p>}</p>
<p>#处理完毕之后再保存当行的20bp碱基做下一行的头部信息</p>
<p>$residue_F=$F_reads;</p>
<p>$residue_R=$R_reads;</p>
<p>}</p>
<p>#print &quot;then we sort it\n&quot;;</p>
<p>$count_a=0;</p>
<p>$count_c=0;</p>
<p>$count_g=0;</p>
<p>$count_t=0;</p>
<p>foreach  (sort keys  %hash){</p>
<p>$first=substr($_,0,1);</p>
<p>$len=length;</p>
<p>$last=substr($_,$len-1,1);</p>
<p>#print &quot;$first\t$last\t$hash{$_}\n&quot;;</p>
<p>$count_a++ if $last eq 'A';</p>
<p>$count_c++ if $last eq 'C';</p>
<p>$count_g++ if $last eq 'G';</p>
<p>$count_t++ if $last eq 'T';</p>
<p>print &quot;$last\t$hash{$_}\t$count_a\t$count_c\t$count_g\t$count_t\n&quot;;</p>
<p>}</p>
<p>unlink(&quot;tmp_forward.txt&quot;);</p>
<p>unlink(&quot;tmp_reverse.txt&quot;);</p>
<p>[/perl]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bio-info-trainee.com/503.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
