问题描述,有两个文件,一个是基因和其相对应所包含的readsID以及是正反向测序是否都要的标识。
格式如下:Tea_CCG055929.1&FCC55J8ACXX:8:1101:6302:2021#TAGCTTAT/1&A
基因名&reads名&标识。如果A则正反都要,如果S则只要一条。
另一个则是reads文件标准fq格式。依据关键字文件找出对应的reads序列存入相应基因名字建立的文件中。
reads文件大约13G,关键字文件大约2G。如果用平常循环比对,耗时将非常长。时间复杂度也为O(mn),若采用哈希表存储结构先将关键字文件存储进去,将reads文件一一比对,时间复杂度将降低到O(n)。
哈希表存储结构关键是哈希函数的构造,用perl写了一个统计关键字文件有多少行以及最后一个数字最大为多少(如例子格式最后一个数字为2021);最终统计出总共有35741312条数据,最大值为100685 。 装载因子采用0.7 所以哈希函数为 hash(KEY)=KEY×500; 存储数组为0-50342500。冲突解决方式为开放地址法,最终地址为H=hash(KEY)+di;
代码如下:
#/usr/bin/perl -w use strict; my $myReads="read1.fq";#reads文件 my $myFileAdd=".fastq1"; my $outDir="gene/";#输出目录 my $mySmalt="example.txt";#smalt结果文件 my $MAXSIZE=50342500; my $myAmplify=500; my @array; my $i=0; my $mybeginAdd=0; my $GeneName=""; my $ReadsName=""; my $myFlag=""; my $outFlag=0; my $countNum=0; my $myResult=""; for($i=0;$i<=$MAXSIZE;$i++){ $array[$i]="END"; } open(myFile,$mySmalt)||die("connot open file 1"); while(my $myLine=<myFile>){ if($myLine=~/(\S+)\&(\S+)\&(\S+)/){ $ReadsName=$2; if($ReadsName=~/(\S+)\:(\S+):(\S+):(\S+):(\S+)\#/){ $mybeginAdd=$5*$myAmplify; $mybeginAdd=&myHash($mybeginAdd); $array[$mybeginAdd]=$myLine; } } } close(myFile); open(myFile,$myReads)||die("connot open file 2"); while(my $myLine=<myFile>){ chomp($myLine); if($myLine=~/@/){ if($myLine=~/\@(\S+)\:(\S+):(\S+):(\S+):(\S+)\#/){ $mybeginAdd=$5*$myAmplify; if($mybeginAdd>$MAXSIZE){ next; } while(!($array[$mybeginAdd] eq "END")){ if($array[$mybeginAdd]=~/(\S+)\&(\S+)\&(\S+)/){ $GeneName=$1; $ReadsName=$2; $myFlag=$3; if($myFlag eq "A"){ if($ReadsName=~/(\S+)\/(\S+)/){ $ReadsName=$1; } } if($myLine=~/$ReadsName/){ $outFlag=1; $countNum=0; open(OUTFILE,">>".$outDir.$GeneName.$myFileAdd)||die("cannot open outfile"); print OUTFILE $myLine."\n"; close(OUTFILE); last; } } $mybeginAdd++; if($mybeginAdd>$MAXSIZE){ $mybeginAdd=$mybeginAdd%$MAXSIZE; } } } } elsif($outFlag==1){ if($countNum==2){ $myResult.=$myLine."\n"; open(OUTFILE,">>".$outDir.$GeneName.$myFileAdd)||die("cannot open outfile"); print OUTFILE $myResult; close(OUTFILE); $outFlag=0; $myResult=""; } else { $myResult.=$myLine."\n"; } $countNum++; } } close(myFile); sub myHash{ my ($myAdd) =@_; $myAdd=$myAdd+0; while(!($array[$myAdd] eq "END")){ $myAdd++; if($myAdd>$MAXSIZE){ $myAdd=$myAdd%$MAXSIZE; } } return ($myAdd); }