测试数据下载

wget -c ftp://ftp.ensembl.org/pub/release-87/gtf/homo_sapiens/Homo_sapiens.GRCh38.87.chr.gtf.gz

先验知识

代码解读

实现了哪些功能?

1)读取GTF文件

2)根据feature,将其分为3种数据类型进行保存,即gene、transcript、exon。

每一种数据类型,分别构建一种对象,每种对象所具有的属性定义如下,

  • Object gene包含的属性有:所属的染色体,起始位置,终止位置,正负链信息,gene id(对应GTF文件中的gene_id
  • Object transcript包含的属性有:所属的染色体,起始位置,终止位置,transcript id(对应GTF文件中的transcript_id),parent id(对应GTF文件中的gene_id
  • Object exon包含的属性有:所属的染色体,起始位置,终止位置,parent id(对应GTF文件中的transcript_id

3)数据处理

  • 统计每一条染色体上的gene总数
  • 计算每一个gene的长度
  • 统计每个gene的转录本数
  • 记录每个exon的坐标

代码设计思路

将GTF文件的每一行看作一个对象来处理,构建不同类型的对象对信息进行存储,同时由于不同的对象之间存在信息交集,这就是类继承的应用之处。

Python代码

在正则表达式上,我进行了一定修改。

'''
Date: 2022.8.14
Description: Kind of a collection of tools to parse and analyze GTF
Main Function:
- count gene number of each chromosome
- count transcritp number of each gene
- calculate the total number of exon and intron of each transcript
- plot the result
'''
import sys
import reargs = sys.argv  # Set argv to grep the ipnut. argv is a list, e.g. [, , ]class Genome_info():def __init__(self):self.chr = ""self.start = 0self.end = 0class Gene(Genome_info):'''Note: Object Gene is inherited from Genome_infoGene has two attributes,1) orientation2) id (gene id)'''def __init__(self):Genome_info.__init__(self)self.orientation = ""self.id = ""class Transcript(Genome_info):'''Note: Object Transcript is inherited from Genome_infoTranscript has two attributes,1) id (transcript id)2) parent (gene id)'''def __init__(self):Genome_info.__init__(self)self.id = ""self.parent = ""class Exon(Genome_info):'''Note: Object Exon is inherited from Genome_infoTranscript has one attributes,2) parent (?)'''def __init__(self):Genome_info.__init__(self)self.parent = ""'''
Define a main function to handle gtf file
'''
def main(args):list_chr = []list_gene = {}list_transcript = {}list_exon = []# l_n = 0with open(args[1]) as fp_gtf:for line in fp_gtf:if line.startswith("#"):continue# print ("in %s" % l_n)# l_n += 1lines = line.strip("\n").split("\t")chr = lines[0]type = lines[2]start = int(lines[3])end = int(lines[4])orientation = lines[6]attr = lines[8]if not re.search(r'protein_coding', attr):   # 只针对protein_coding进行统计分析continueif not chr in list_chr :list_chr.append(chr)if type == "gene":gene = Gene()id = re.search(r'gene_id "([^;]+)";?', attr).group(1)  # Original version, could be adapted to r'gene_id "(\S+)";'# id = re.search(r'gene_id "(\S+)";', attr).group(1)      # My adaptationgene.chr = chrgene.start = startgene.end = endgene.id = idgene.orientation = orientationlist_gene[id] = gene  # list_gene is a dict to depost gene id and its correspoding Gene Object# print(id)elif type == "transcript":transcript = Transcript()id = re.search(r'transcript_id "([^;]+)";?', attr).group(1)# id = re.search(r'transcript_id "(\S+)";', attr).group(1)      # My adaptationparent = re.search(r'gene_id "([^;]+)";?', attr).group(1)# id = re.search(r'gene_id "(\S+)";', attr).group(1)      # My adaptationif not parent in list_gene:continuetranscript.chr = chrtranscript.start = starttranscript.end = endtranscript.id = idtranscript.parent = parentlist_transcript[id] = transcriptelif type == "exon":exon = Exon()parent = re.search(r'transcript_id "([^;]+)";?', attr).group(1)# parent = re.search(r'transcript_id "(\S+)";', attr).group(1) # My adaptationif not parent in list_transcript:continueexon.chr = chrexon.start = startexon.end = endexon.parent = parentlist_exon.append(exon)chr_gene(list_gene)gene_len(list_gene)gene_transcript(list_transcript)transcript_exon(list_exon)exon_pos(list_exon)def chr_gene(list_gene):print("-------------------------------- Count gene number of each chromosome --------------------------------")count_gene = {}for info in list_gene.values():chr = info.chrif chr in count_gene:count_gene[info.chr] += 1else:count_gene[info.chr] = 1with open("chr_gene.txt", 'w') as fp_out:for chr, num in count_gene.items():print("\t".join([chr, str(num)]) + "\n")fp_out.write("\t".join([chr, str(num)]) + "\n")def gene_len(list_gene):print("-------------------------------- Calculate the length of each gene --------------------------------")with open("gene_len.txt", 'w') as fp_out:for gene_id, info in list_gene.items():len = info.end - info.start + 1fp_out.write("\t".join([gene_id, str(len)]) + "\n")# print("\t".join([gene_id, str(len)]) + "\n")def gene_transcript(list_transcript):print("-------------------------------- Count transcript number of each gene --------------------------------")count_transcript = {}for info in list_transcript.values():gene_id = info.parentif gene_id in count_transcript:count_transcript[gene_id] += 1else:count_transcript[gene_id] = 1with open("gene_transcript.txt", 'w') as fp_out:for gene_id, num in count_transcript.items():# print("\t".join([gene_id, str(num)]) + "\n")fp_out.write("\t".join([gene_id, str(num)]) + "\n")def transcript_exon(list_exon):print("-------------------------------- Count exon number of each transcript --------------------------------")count_exon = {}for exon in list_exon:transcript_id = exon.parentif transcript_id in count_exon:count_exon[transcript_id] += 1else:count_exon[transcript_id] = 1with open("transcript_exon.txt", 'w') as fp_out:for transcript_id, num in count_exon.items():# print("\t".join([transcript_id, str(num)]) + "\n")fp_out.write("\t".join([transcript_id, str(num)]) + "\n")def exon_pos(list_exon):print("-------------------------------- Save the position info of each exon --------------------------------")count_exon = {}for exon in list_exon:transcript_id = exon.parentif transcript_id in count_exon:count_exon[transcript_id] += ",%s-%s" % (str(exon.start), str(exon.end))else:count_exon[transcript_id] = "%s-%s" % (str(exon.start), str(exon.end))with open("exon_pos.txt", 'w') as fp_out:for transcript_id, pos in count_exon.items():print("\t".join([transcript_id, pos]) + "\n")fp_out.write("\t".join([transcript_id, pos]) + "\n")def gene_exon_pos(list_gene, list_transcript, list_exon):passif __name__ == "__main__":main(args)

代码运行

python save.py input.gtf

小记

暑假在编写脚本的过程中,感觉自己Python其实进步了不少,但是还没能把数据结构、面向对象编程很好的整合起来。

因为本科阶段确实没有什么自己编写脚本去分析数据的需求,就算自己创造需求了,也没有实际应用到工作当中,因此刻意练习是很重要的。

有意思的故事是,去年有幸听到了坦哥面试学生问的问题,“解释一下类”,

要是当时的我,碰到了这个问题,那我是真答不上来。

参考资料

[1] http://www.biotrainee.com/thread-626-1-1.html【作者:dongye】

「像读文献一样读代码」第一期:如何解析GTF文件进行统计分析?相关推荐

  1. 读文献先读图——主成分分析 PCA 图

    上周五彩斑斓的气泡图 有让你眼花缭乱吗? 本周,化繁为简的PCA图 你值得拥有!  数据分析| 科研制图﹒PCA 图 关键词:主成分分析.降维 1665 年的鼠疫 牛顿停课在家提出了万有引力 ; 18 ...

  2. 基于蚂蚁金服「如何管理好10万行代码」搭建了 Vue 项目架构

    此文是对蚂蚁金服文章的解读,所以要看懂此文一定要先去看原文:如何管理好10万行代码的前端单页面应用. 当时看到蚂蚁金服这篇文章有点茅塞顿开,只不过他们是基于 React 技术栈开发的,但是架构是一种思 ...

  3. 人人都能读懂的「以太坊2.0分片设计」

    讨论 | 吴为龙.李画 撰文 | 李画 来源 | 碳链价值 封图由 CSDN 下载于东方 IC 当我们在7-11买早餐的时候,如果只有一个收银员,就要排很长的队等待结帐:如果有两个收银员,立刻就会快一 ...

  4. 用 Electron 打造 Win/Mac 应用,从「代码」到可下载的「安装包」,可能比你想得麻烦一点...

    首发于酷家乐前端博客,作者@摘星(segmentfault @StinsonZhao) 我们能从很多地方学习到怎么起一个 Electron 项目,有些还会介绍怎么打包或构建你的代码,但距离「真正地发行 ...

  5. 用 Electron 打造 Win/Mac 应用,从「代码」到可下载的「安装包」,可能比你想得麻烦一点... 1

    2019独角兽企业重金招聘Python工程师标准>>> 首发于酷家乐前端博客 我们能从很多地方学习到怎么起一个 Electron 项目,有些还会介绍怎么打包或构建你的代码,但距离「真 ...

  6. 王垠的「40 行代码」真如他说的那么厉害吗?

    "我有什么资格说话呢?如果你要了解我的本事,真的很简单:我最精要的代码都放在 GitHub 上了.但是除非接受过专门的训练,你绝对不会理解它们的价值.你会很难想象,这样一片普通人看起来像是玩 ...

  7. 王垠的「40 行代码」

    "我有什么资格说话呢?如果你要了解我的本事,真的很简单:我最精要的代码都放在 GitHub 上了.但是除非接受过专门的训练,你绝对不会理解它们的价值.你会很难想象,这样一片普通人看起来像是玩 ...

  8. 用 Electron 打造 Win/Mac 应用,从「代码」到可下载的「安装包」,可能比你想得麻烦一点

    首发于酷家乐前端博客,作者@摘星(segmentfault @StinsonZhao) 我们能从很多地方学习到怎么起一个 Electron 项目,有些还会介绍怎么打包或构建你的代码,但距离「真正地发行 ...

  9. 【读文献笔记】图神经网络加速结构综述

    [读文献笔记]图神经网络加速结构综述 前言 一.图神经网络来源 1.图神经网络用途 2.图神经网络特点 3.图神经网络主要阶段 4.图神经网络加速面临的挑战 5.本笔记内容包含内容 二.图与图神经网络 ...

最新文章

  1. 使用TensorFlow实现余弦距离/欧氏距离(Euclideandistance)以及Attention矩阵的计算
  2. 互联网还留给我们这些出路
  3. 【Android 应用开发】Paint 图形组合 Xfermod 简介 ( 图形组合集合描述 | Xfermod 简介 | PorterDuff 简介 )
  4. Windows下的bat文件的@echo off 作用
  5. Spring Boot 注解大全,一键收藏了!
  6. redis 类型、方法
  7. 【2017年第3期】专题:面向社会治理和服务的大数据
  8. 天天写业务代码,如何成为技术大牛
  9. linux命令:软件更新 sudo apt-get update 和 sudo apt-get upgrade
  10. gitlib命令的使用
  11. 使用jquery 动态操作添加/删除tr td
  12. rhel linux 自动 fsck,red hat as 4 启动报错:checking filesystems fsck.ext3: bad magic number ......
  13. Linux fstab文件详解
  14. Intellij IDEA 插件下载慢或无法查询
  15. Android系统模拟位置的使用方法
  16. Redis统计用户访问量
  17. 解决Chrome浏览器主页被篡改(劫持)hh899899.com的问题
  18. 我新开的淘宝店铺怎么增加访客和销量
  19. 青椒跳槽三线高校后,副教授变教授、140平房子到手、老婆入编...
  20. 网线线序及网线转RS232—— DB9线序

热门文章

  1. EXCEL中设置后面单元格的数据由前面单元格的数据带出
  2. CFI 选项:-fsanitize=cfi-nvcall
  3. 【Python之Numpy篇】数组重塑
  4. kubernetes(五)------taint(排斥)和toleration(亲和)
  5. 相关性分析热点图_高分文章中物种与代谢物相关性热图是怎么画的?
  6. 11.网络编程的学习总结
  7. 11.Flink ProcessFunction介绍及KeyedProcessFunction实例
  8. python爬虫网站 词云_Python爬虫之爬取情话网站并绘制词云
  9. Odoo 16 企业版手册 - 财务管理之会计仪表板
  10. 微信小程序去掉user agent style