biostar handbook(六)|正则表达式和K-mers在模式匹配中的使用

2024-06-23 21:18

本文主要是介绍biostar handbook(六)|正则表达式和K-mers在模式匹配中的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

模式匹配中的正则表达式和k-mer

模式匹配指的是在看似杂乱无章的系统中找到符合要求的部分。比如说你想从基因组中寻找motif,转录因子结合位点,CDS, 或者检测测序结果里是否有接头等,这些行为都可以解读为根据已有的模式去寻找目标序列中符合要求的片段。后面介绍的序列模式匹配的两种方法,正则表达式和k-mers。

正则表达式的基础概念

正则表达式(regular expression)的概念,最初来自于20世纪40年代的两位神经学家(Warren McCulloch, Walter Pitts)研究神经元时提出的想法。后来数学家Stephen Kleene在代数学中正式描述了这种被他称之为“正则集合”的模型。并且,他还发明了一套简洁的方法表示正则集合,也就是正则表达式。

目前最快速的文本搜索工具grep就内置了正则表达式。grep起源于Unix中的ed编辑器的一条命令g/Regular Expression/p, 读作“Global Reular Expression Print”,即运用正则表达式的全局输出。由于这个功能太过实用,于是就从ed中独立出来,演变成了grep以及扩展版本的egrep。都知道grep因为有正则表达式所以很强大,但是正则表达式为何如此强大呢?

正则表达式的强大之处在于它是一套语法,分为两个部分,元字符(metacharacters)普通文本字符(normal text characters)

以语言类比,“我爱正则表达式”这句话可以抽象成“主谓宾”结构,主语是"我",谓语是"爱",宾语是“正则表达式”。这种语法还适用于其他语言,比如说英语就是"I love regular expression". 这种语法结构就是元字符,而构成句子的语言就是普通文字字符。

正则表达式的通用元字符

正则表达式有很多流派,不同流派之间的差异在于对元字符的支持程度。以下的元字符适用于GNU版本的grep, sed, awk. mac自带的是BSD版本。

匹配单个字符的元字符

元字符匹配对象
.匹配单个任意字符
[...]匹配单个列出的字符
[^...]匹配单个未列出的字符
\char转义元字符成普通字符

提供计数功能的元字符:

元字符匹配对象
匹配0或1次
*匹配0到n次
+至少一次,最多不限
{min,max}至少min次, 最多max次

匹配位置的元字符:

元字符匹配对象
^匹配一行的开头
$匹配一行的结尾

其他元字符:

元字符匹配对象
|匹配任意分割的表达式
(...)限定多选结构的范围,标注量词的作用范围,为反向引用捕获元素
\1, \2反向引用元素

知道以上规则之后,推荐去http://regexpal.com/进行练习,以便更好的掌握。

使用正则表达式进行模式匹配

这一部分使用*nix系统自带的grep和Emboss工具集中的dreg,fuzznuc进行练习,所用练习数据为人类基因组的第22号染色体的DNA序列(fasta)以及高通量测序结果(fastq).

使用grep进行模式匹配

grep的强大之处它所做的事情就只有在文本搜索”正则表达式“定义的模式(pattern),如果找到就打印出来。可以使用man egrep查看所支持的参数。

egrep [options] pattern [file]
egrep [options] [-e pattern]... [-f FILE]... [FILE...]
# 参数参数
-e PATTERN: 定义多个模式
-f FILE: 从文本中读取模式
-w: 匹配整个单词
-v: 反向匹配
-i: 忽略大小写
-x: 仅仅选择整行匹配结果
-c: 计数
-n: 输出表明行号
-A/-B NUM: 同时输出后/前几行

: grep有基础和扩展两个模式,基础模式支持的元字符较少,而egrep表示扩展的grep,支持的元字符较多。

利用grep搜索fastq文件中的序列:

# 获取fastq序列
fastq-dump --split-files SRR519926
# 寻找以ATG开头的序列
cat SRR519926_1.fastq | egrep "^ATG" --color=always | head
# 寻找以ATG结尾的序列
cat SRR519926_1.fastq | egrep "ATG\$" --color=always | head
# 寻找TAATA或TATTA
cat SRR519926_1.fastq | egrep "TA[A,T]TA" --color=always | head
# 寻找TAAATA或TACCTA
cat SRR519926_1.fastq | egrep "TA(AA|CC)TA" --color=always | head
## 比较[]和(|)的区别
# 寻找TA后面多个A或没有,随后是TA的序列
cat SRR519926_1.fastq | egrep "TA(A*)TA" --color=always | head
# 寻找TA后面接着1个以上A,之后是TA的序列
cat SRR519926_1.fastq | egrep "TA(A+)TA" --color=always | head
# 寻找TA后面跟着2到5个的序列,随后是TA
cat SRR519926_1.fastq | egrep "TAA{2,5}TA" --color=always | head
# 找找illumina的接头序列AGATCGG
cat SRR519926_1.fastq | egrep "AGATCGG.*" --color=always | head

使用dreg和fuzznuc对核酸数据进行匹配

一般而言,对于fastq文件,*nix提供的grep基本已经够用了。但是对于fasta文件而言,可能会存在一些问题,比如说下面这段序列,你是绝对匹配不到TAATA,尽管你用肉眼都能看的出来,TAA后面就是TA,但是grep就是找不到。

## 22号染色体数据
curl http://hgdownload.cse.ucsc.edu/goldenPath/hg38/chromosomes/chr22.fa.gz | gunzip > chr22.fa
## 查看序列
tail -n 1000 chr22.fa | head -n 5
CTGCCTGCGGGGAGGGGGTGGGGAAGGTGTTAATGATGCTGATCCCTACT
TCTGCTTCAAGGAGATCTGGTGGGGAATTCTTCCACCAGTCCAGAGTTTG
CTGGTGCTGACCTCATCCCTGTATCACGGGCCTAGAATGTGGGAGGCTAA
TAGGATGGGTGGGTTGCAGGAGGTAGAAGAGGGGATGGCCTAGAGAGTTT
CTCCATTCAGAGCTGGAGAGTTGTTGAAGGGAAGGGTATTTTAAAAGGGC
tail -n 1000 char22.fa | head -n5 | grep TAATA

真相只有一个,这段序列为了显示方便,存放的时候被折叠了,所以TAA和TA之间其实存在一个换行符。解决方法有两个,第一个是去掉序列中的换行符tail -n 1000 chr22.fa | head -n 20 | tr -d '\n' | egrep -o -i 'TAATA',第二个就是使用emboss工具集的dregfuzznuc

# 安装emboss工具集
conda install -c bioconda emboss # for linux
brew install emboss # for Macos
# 使用方法见官方说明
# http://emboss.sourceforge.net/apps/cvs/emboss/apps/fuzznuc.html
# http://emboss.sourceforge.net/apps/cvs/emboss/apps/dreg.html

dreg和funzznuc功能基本上一摸一样,使用方法也是几乎一样,但是dreg比funzznuc支持的正则表达式多,因此通常使用dreg。

# 首先去找之前的TAATA
tail -n 1000 chr22.fa | head -n 5 | dreg -filter -pattern 'TAATA'
# 寻找TTAGGG重复的序列
cat chr22.fa | dreg -filter -pattern '(TTAGG){20,30}'

dreg的用法和grep基本上一致的,这里不再赘述。对于氨基酸序列和翻译后的蛋白序列,则有pregfuzzprt,fuzztran

K-Mers

k-mer指的是一个字符串中所有长度为k的子字符串的集合。如ATCGA的所有k-mer如下:

  • 2-mers: AT, TG, GC and CA
  • 3-mers: ATG, TGC and GCA
  • 4-mers: ATGC, TGCA
  • 5-mers: ATGCA

k-mers的主要使用场景是基因组组装,如下图所示

2013053-fc28319069c0582e.jpg
图片来自于维基百科

当然他还能用于:

  • 纠错:那些稀有不常见的k-mers,可能仅仅是测序错误.
  • 分类:基因组中特异性的k-mers可以用来区分不同物种。 Classification: certain k-mers may uniquely identify genomes.
  • Pseudo-alignment(伪比对): 目前RNA-Seq定量分析中出现了一类alignment-free工具,其原理就是先准备不同基因的k-mers的索引,通过将read的k-mers和k-mers索引比较,从而对基因进行计数。

案例一: 使用jellyfish统计k-mers

# 安装jellyfish
conda install -c bioconda jellyfish # for linux
brew install jellyfish # for MacOS
# 获取序列数据
efetch -id KU182908 -db nucleotide -format fasta > KU182908.fa
# 对fasta里面的k-mers计数,-C表示双端, -m表示k的长度,-s10M表示初始hash为10M,根据数据量大小而定。
jellyfish count -C -m 10 -s10M KU182908.fa
# k-mers 频次展示
jellyfish histo mer_counts.jf
#1 17736
#2 539
#3 26
#4 6
#6 1
#7 4
# 出现7次的k-mers
jellyfish dump -L 7 mer_counts.jf
>7
ATGAAGATTA
>7
TTAAGAAAAA
>7
AATCTTCATC
>7
ATTAAGAAAA

根据出现7次10-mers序列对原来序列进行模式匹配

cat KU182908.fa | dreg -filter -pattern ATGAAGATTA
2013053-53330c6d65b6a882.jpg
image

案例二:利用k-mers估计基因组

这一部分内容属于基因组survey的一部分。在组装基因组前需要对基因组有一个评估,比如说杂合率,重复率,基因组大小等内容,这些就需要用到jellyfish。

# 自行找双端测序的测试文件, 假设是A_1.fq.gz和A_2.fq.gz
# 数据的19-mer计数
jellyfish count -m 19 -s 300M -t 4 -C <(zcat A_1.fq.gz) <(zcat A_2.fq.gz)
jellyfish histo mer_counts.jf > counts.txt
# 用R作图
histo <- read.delim("counts.txt", sep = " ",header = FALSE)
plot(histo[3:200,], type="l")
2013053-06b115f3ea88e9ad.jpg
image

根据上图找到单峰区间,并计算总k-mers数

plot(histo[3:200,], type="l")
points(histo[6:50,]) # 根据点图确认单峰区间在6到50
sum(as.numeric(histo[3:9597,1] * histo[3:9597,2])) # 5477901244

确定峰所在位置,并且计算基因组大小

histo[6:50,] # 24
sum(as.numeric(histo[3:9597,1] * histo[3:9597,2])) / 24 / 1000 /1000 # 约为 208M

参考资料: https://bioinformatics.uconn.edu/genome-size-estimation-tutorial/

一些更加方便的脚本工具:

  • estimate_genome_size.pl: https://github.com/josephryan/estimate_genome_size.pl
  • KmerGenie: http://kmergenie.bx.psu.edu/
  • 华大的GCE: ftp://ftp.genomics.org.cn/pub/gce
  • ALLPATHS-LG的 findErrors模块。

最后还有一个问题:FastQC的结果里面也有一个k-mers,应该如何看待呢?答:一笑而已,请用jellyfish统计

这篇关于biostar handbook(六)|正则表达式和K-mers在模式匹配中的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1088303

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他