美文网首页生信Python
用python分割fastq文件的脚本(自写)

用python分割fastq文件的脚本(自写)

作者: 想把生信学好的胡小慧 | 来源:发表于2020-07-06 16:33 被阅读0次

    唠唠叨叨:

    因为处理ATAC-seq的原始fastq数据太大(已知GEO号在ncbi上下载),所以被老师要求用python编程分割fastq脚本,其实用软件seqkit就可以进行分割,命令简单还快速,想分多少份就分多少份,但老师说我不练怎么会编程呢,所以没办法,我这刚入门的小白,就在网上各种查资料,发现都是处理fasta格式的,因为fastq格式和fasta格式并不一样,不知道可以借鉴不,日夜研究别人的代码,以及翻找网络,读到一篇将fastq文件写入和读出的代码,理解并做出了尝试,然后又绞尽脑汁如何进行分割,后来想到按行分配,只是需要每次都查看一下文件有多少行,然后又搜了一下代码,想把两者结合起来,中间报了各种error,就反复调试,7.1的那一天上午成功了,但是我取的是10000行,不知道生成的文件为什么是7000多行,没找到原因,没有打开生成的文件看看,下午老师过来看我发现是没有加换行符的问题,实际上输出是对的

    分割fastq脚本:

    需要引入时间函数(此处参考网上),可以看脚本分割用了多久

    gz文件打开需要引入gzip函数

    from datetime import datetime

    import re

    import sys

    def Main():#定义函数,读入fastq文件

        source_dir = sys.argv[1] #传入的参数1:目标文件夹所在目录

        read_number=int(sys.argv[2]) #传入的参数2:需要分割的行数,需要是4的倍数,脚本里需要验证一下

        target_dir = sys.argv[3]#传入的参数3:分割后文件所在的目录

        #print(target_dir)

        fas={}

        id=None

        name = 1

        N=0 #读取数据的行数数值,初始值为0

        if read_number%4 != 0:

          print("参数错误,程序退出")

          sys.exit()

        else:

          print("开始。。。。。")

          print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

          with gzip.open(source_dir,'rb') as f:

              for line in f:

                N+=1

                if line.decode()[0]=="@":

                    id=line.decode().strip().split()[0][1:]#对二进制文件进行解码

                    fas[id]=[]  #将该id对应的初始值为空

                else:

                    seq=fas[id].append(line.decode()) 

                    #print(fas)

                if N==read_number:

                #  with gzip.open(target_dir+'/57.%04d.fq.gz'%(name),'wb') as out:

                    #  print(target_dir+'/57.%04d.fq.gz'%(name))

                        if re.findall('r1', source_dir, flags=re.IGNORECASE):  #正则匹配可以不区分大小写 或直接判断R1是否在source_dir里,需大写:if R in source_dir:

                            with gzip.open(target_dir+'.R1.%04d.fq.gz'%(name),'wb') as out:

                                print(target_dir+'.R1.%04d.fq.gz'%(name))

                                for id,seq in fas.items(): 

                                    res = '@'+id+"/1"+"\n"+seq[0]+seq[1]+seq[2]

                                    out.write(res.encode())

                            name+=1

                            N=0

                            fas={}

                        else:

                            with gzip.open(target_dir+'.R2.%04d.fq.gz'%(name),'wb') as out:

                                print(target_dir+'.R2.%04d.fq.gz'%(name))

                                for id,seq in fas.items():

                                    res = '@'+id+"/2"+"\n"+seq[0]+seq[1]+seq[2]

                                    out.write(res.encode())

                            name+=1

                            N=0

                            fas={}

                else:

                      continue

          print("完成。。。。。")

          print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

    if __name__ == "__main__":

        Main()

    优化:此脚本由我的导师提出几个优化步骤又进行改进,以上是完整版,改进为:一传入参数;二对传入的文件名进行判断是含R1还是R2,如果含R1在文件的read_name后加上/1,反之R2加上/2;三将输出的文件名的数固定住

    对于我的脚本有一些缺陷:如果文件生于的行数怎么办,虽然此脚本有考虑到,但我没运行成功,二就是分割的时间太慢

    7月的第一天,我一个小白能写出脚本感觉异常欣慰,二是班长通知六级报名,而我去年六级竟然裸考过了,终于不用再去奔赴六级的考场了,哈哈,开心,感谢我读过的英文文献

    老师版:

    第二天我们老师在我旁边又教我写出另一个版本,即按read数进行分割fastq文件,不得不说我们老师真厉害,代码比我简洁多了,而且教我写出只用了一个小时,时间上也会慢些,应该是文件较大,但是不用考虑剩余行的问题,只需要提前计算好分割的reads数

    import gzip

    from datetime import datetime

    import re

    import sys

    def Main():

        test_R1=False

        test_R2=False

        source_dir = sys.argv[1]

        read_number=int(sys.argv[2])

        target_dir = sys.argv[3]

        #print(target_dir)

        fas={}

        id=None

        name = 1

        N=0 #读取数据的行数数值,初始值为0

        print("开始。。。。。")

        print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

        with gzip.open(source_dir,'rb') as f:

          for line in f:

            if N%(4*read_number)==0:

                if re.findall('r1', source_dir, flags=re.IGNORECASE):

                      f_out = gzip.open(target_dir+'.R1.%04d.fq.gz'%(name),'wb')

                      print(target_dir+'.R1.%04d.fq.gz'%(name))

                      test_R1 = True

                      suffix="/1"

                elif re.findall('r2', source_dir, flags=re.IGNORECASE):

                      f_out = gzip.open(target_dir+'.R2.%04d.fq.gz'%(name),'wb')

                      print(target_dir+'.R2.%04d.fq.gz'%(name))

                      test_R2= True

                      suffix="/2"

                else:

                      print("Error: R1 or R2 in filename not detected,exit")

                      sys.exit()

                name+=1 

            N+=1

            if N%4==1:

                if test_R1:

                    if re.findall('/1', line.decode(), flags=re.IGNORECASE):

                        f_out.write(line)

                    else:

                        f_out.write((line.decode().strip().split()[0]+suffix+"\n").encode())

                if test_R2:

                      if re.findall('/2', line.decode(), flags=re.IGNORECASE):

                        f_out.write(line)

                      else:

                        f_out.write((line.decode().strip().split()[0]+suffix+"\n").encode())

            elif N%4==3:

                f_out.write(("+\n").encode())

            else:

                f_out.write(line)

        print("完成。。。。。")

        print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

    if __name__ == "__main__":

        Main()

    这两段代码都已运行成功

    相关文章

      网友评论

        本文标题:用python分割fastq文件的脚本(自写)

        本文链接:https://www.haomeiwen.com/subject/yjtgqktx.html