原创:hxj7

前言

序列比对是生信领域的一个古老课题,在这一波NGS的浪潮中重新引起大家的广泛关注。由于生物序列的特殊性,在比对的时候允许插入缺失,所以往往是一种不精确匹配。从本文开始,我们陆续学习前人开发出的流行算法。

全局比对算法

所谓全局比对算法,就是根据一个打分矩阵(替换矩阵)计算出两个序列比对最高得分的算法。关于它的介绍网上已经非常多了,我们只需看看其中的关键点及实现代码。

关键点

1. 打分矩阵:

选用不同的打分矩阵或者罚分分值会导致比对结果不同,常用BLAST打分矩阵。

2. 计算比对最高得分的算法:

常用动态规划算法(Needleman-Wunsch算法)。

image

图片引自https://www.jianshu.com/p/2b99d0d224a2

3. 打印出最高得分相应的序列比对结果:

根据得分矩阵回溯,如果最优比对结果有多个,全部打印出来。

4. 理解打分系统背后的概率论模型:

比对分值可以理解为匹配模型和随机模型的对数几率比(log-odds ratio)。

实现代码(C代码及示例)

网上的教程给出的代码大多不全,所以我决定还是自己造轮子了。

需要说明的是:

1. 没有对输入进行检查,如果有非AGCT的字符程序可能会出错。

2. 对空位的罚分是线性的,即penalty=gd,其中g为空位长度,d为一个空位的罚分。

在以后的文章中,我们会给出仿射型罚分的代码,即

penalty=d+(g-1)e,其中g为连续空位的长度,d为连续空位中第一个空位的罚分,e为连续空位中第2个及以后空位的罚分。

3. 其他未提及的错误或者不足。

示例

image

代码

#include

#include

#include

#define MAXSEQ 1000

#define GAP_CHAR '-'

// 对空位的罚分是线性的

struct Unit {

int W1; // 是否往上回溯一格

int W2; // 是否往左上回溯一格

int W3; // 是否往左回溯一格

float M; // 得分矩阵第(i, j)这个单元的分值,即序列s(1,...,i)与序列r(1,...,j)比对的最高得分

};

typedef struct Unit *pUnit;

void strUpper(char *s);

float max3(float a, float b, float c);

float getFScore(char a, char b);

void printAlign(pUnit** a, const int i, const int j, char* s, char* r, char* saln, char* raln, int n);

void align(char *s, char *r);

int main() {

char s[MAXSEQ];

char r[MAXSEQ];

printf("The 1st seq: ");

scanf("%s", s);

printf("The 2nd seq: ");

scanf("%s", r);

align(s, r);

return 0;

}

void strUpper(char *s) {

while (*s != '\0') {

if (*s >= 'a' && *s <= 'z') {

*s -= 32;

}

s++;

}

}

float max3(float a, float b, float c) {

float f = a > b ? a : b;

return f > c ? f : c;

}

// 替换矩阵:match分值为5,mismatch分值为-4

// 数组下标是两个字符的ascii码减去65之后的和

float FMatrix[] = {

5, 0, -4, 0, 5, 0, -4, 0, -4, 0,

0, 0, 5, 0, 0, 0, 0, 0, 0, -4,

0, -4, 0, 0, 0, -4, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 5

};

float getFScore(char a, char b) {

return FMatrix[a + b - 'A' - 'A'];

}

void printAlign(pUnit** a, const int i, const int j, char* s, char* r, char* saln, char* raln, int n) {

int k;

pUnit p = a[i][j];

if (! (i || j)) { // 到矩阵单元(0, 0)才算结束,这代表初始的两个字符串的每个字符都被比对到了

for (k = n - 1; k >= 0; k--)

printf("%c", saln[k]);

printf("\n");

for (k = n - 1; k >= 0; k--)

printf("%c", raln[k]);

printf("\n\n");

return;

}

if (p->W1) { // 向上回溯一格

saln[n] = s[i - 1];

raln[n] = GAP_CHAR;

printAlign(a, i - 1, j, s, r, saln, raln, n + 1);

}

if (p->W2) { // 向左上回溯一格

saln[n] = s[i - 1];

raln[n] = r[j - 1];

printAlign(a, i - 1, j - 1, s, r, saln, raln, n + 1);

}

if (p->W3) { // 向左回溯一格

saln[n] = GAP_CHAR;

raln[n] = r[j - 1];

printAlign(a, i, j - 1, s, r, saln, raln, n + 1);

}

}

void align(char *s, char *r) {

int i, j;

int m = strlen(s);

int n = strlen(r);

float gap = -2.5; // 对空位的罚分

float m1, m2, m3, maxm;

pUnit **aUnit;

char* salign;

char* ralign;

// 初始化

if ((aUnit = (pUnit **) malloc(sizeof(pUnit*) * (m + 1))) == NULL) {

fputs("Error: Out of space!\n", stderr);

exit(1);

}

for (i = 0; i <= m; i++) {

if ((aUnit[i] = (pUnit *) malloc(sizeof(pUnit) * (n + 1))) == NULL) {

fputs("Error: Out of space!\n", stderr);

exit(1);

}

for (j = 0; j <= n; j++) {

if ((aUnit[i][j] = (pUnit) malloc(sizeof(struct Unit))) == NULL) {

fputs("Error: Out of space!\n", stderr);

exit(1);

}

aUnit[i][j]->W1 = 0;

aUnit[i][j]->W2 = 0;

aUnit[i][j]->W3 = 0;

}

}

aUnit[0][0]->M = 0;

for (i = 1; i <= m; i++) {

aUnit[i][0]->M = gap * i;

aUnit[i][0]->W1 = 1;

}

for (j = 1; j <= n; j++) {

aUnit[0][j]->M = gap * j;

aUnit[0][j]->W3 = 1;

}

// 将字符串都变成大写

strUpper(s);

strUpper(r);

// 动态规划算法计算得分矩阵每个单元的分值

for (i = 1; i <= m; i++) {

for (j = 1; j <= n; j++) {

m1 = aUnit[i - 1][j]->M + gap;

m2 = aUnit[i - 1][j - 1]->M + getFScore(s[i - 1], r[j - 1]);

m3 = aUnit[i][j - 1]->M + gap;

maxm = max3(m1, m2, m3);

aUnit[i][j]->M = maxm;

if (m1 == maxm) aUnit[i][j]->W1 = 1;

if (m2 == maxm) aUnit[i][j]->W2 = 1;

if (m3 == maxm) aUnit[i][j]->W3 = 1;

}

}

/*

// 打印得分矩阵

for (i = 0; i <= m; i++) {

for (j = 0; j <= n; j++)

printf("%f ", aUnit[i][j]->M);

printf("\n");

}

*/

printf("max score: %f\n", aUnit[m][n]->M);

// 打印最优比对结果,如果有多个,全部打印

// 递归法

if ((salign = (char*) malloc(sizeof(char) * (m + n + 1))) == NULL) {

fputs("Error: Out of space!\n", stderr);

exit(1);

}

if ((ralign = (char*) malloc(sizeof(char) * (m + n + 1))) == NULL) {

fputs("Error: Out of space!\n", stderr);

exit(1);

}

printAlign(aUnit, m, n, s, r, salign, ralign, 0);

// 释放内存

free(salign);

free(ralign);

for (i = 0; i <= m; i++) {

for (j = 0; j <= n; j++) {

free(aUnit[i][j]);

}

free(aUnit[i]);

}

free(aUnit);

}

(公众号:生信了)

全局序列比对 c语言实现,序列比对(一)——全局比对Needleman-Wunsch算法相关推荐

  1. python全排列字典序输出 递归_全排列-字典序列、递归方法c语言实现

    当前位置:我的异常网» C语言 » 全排列-字典序列.递归方法c语言实现 全排列-字典序列.递归方法c语言实现 www.MyException.Cn  网友分享于:2014-04-20  浏览:4次 ...

  2. 实验2-3-7 求平方与倒数序列的部分和 (C语言)

    实验2-3-7 求平方与倒数序列的部分和 (C语言) 本题要求对两个正整数m和n(m≤n)编写程序,计算序列和m2+1/m+(m+1)2+1/(m+1)+⋯+n2+1/n. 输入格式: 输入在一行中给 ...

  3. c语言兔子序列第8年不繁殖,基于链表的兔子序列生成研究.pdf

    文章编号 :1674-7070(2012)06~555-04 基于链表的兔子序列生成 成亚萍 , 马瑞 , 摘要 0 引言 针对兔子序列的生成提 出了一种基 于链表的实现方法,并采用c语言编程 意大利 ...

  4. SQL语言之序列(Oracle)

    序列(sequence) 用户创建的数据库对象,序列会产生唯一的整数.序列的一个典型的用途是创建一个主键的值,它对于每一行必须是唯一的.序列有一个Oracle内部程序产生并增加或减少. 一个节省时 ...

  5. 将顺序二叉树存储序列转化为链式存储序列-c语言

    将顺序二叉树存储序列转化为链式存储序列 - 题目描述: 将给定顺序二叉树存储序列转换为链式二叉树存储序列显示 char data[13] = {'0','A','B','C','0','D','E', ...

  6. VLN: 基于全局对比训练的视觉-语言导航方法

    每天给你送来NLP技术干货! 来自:CAAI认知系统与信息处理专委会 视觉-语言导航任务(Vision-Language Navigation, VLN)是指在陌生环境中,无人系统依据语言指示和观测图 ...

  7. oracle两表链接序列跳序,Oracle学习之 序列(Sequence)

    Oracle学习之 序列(Sequence) [Oracle学习]之 序列(Sequence) oracle文档:https://docs.oracle.com/cd/B28359_01/server ...

  8. 栈 - 关于出栈序列,判断合法的出栈序列

    文章目录 1 引例 2 做题方法 3 原因 3.1 选项D(4 3 1 2)的模拟 1 引例 (例)设栈的入栈序列是 1 2 3 4,则下列不可能是其出栈序列的是( ). A. 1 2 4 3 B. ...

  9. 【数字信号处理】傅里叶变换性质 ( 序列傅里叶变换共轭对称性质 | 序列实偶 傅里叶变换 实偶 | 序列实奇 傅里叶变换 虚奇 | 证明 “ 序列实奇 傅里叶变换 虚奇 “ )

    文章目录 一.序列实偶 傅里叶变换 实偶 二.序列实奇 傅里叶变换 虚奇 三.证明 " 序列实奇 傅里叶变换 虚奇 " 1.前置公式定理 ①.序列实部傅里叶变换 ②.序列虚部傅里叶 ...

  10. 【数字信号处理】傅里叶变换性质 ( 序列对称分解定理示例 | 共轭对称序列与原序列之间的关系 | 共轭反对称序列与原序列之间的关系 )

    文章目录 一.序列对称分解定理示例 1.序列对称分解定理 2.因果序列 3.求解过程 n < 0 情况 n = 0 情况 n > 0 情况 实因果序列的对称序列与原序列关系 一.序列对称分 ...

最新文章

  1. IBM IMM默认ID 及修改默认IP 方法
  2. OKRS如何进行目标的对齐?
  3. 苹果正式推iOS 4.2可使iPad支持多任务
  4. Spring 系列,第 3 部分: 进入 Spring MVC
  5. java替换图片中文字_Java 添加、替换、删除Word中的图片
  6. MySQL的几个character_set变量的说明
  7. 超级棒的免费前端学习路线
  8. python语法简图
  9. python怎么修改默认路径_Python小知识之JupyterLab默认启动路径修改
  10. .mat转成.npy文件+Python(Pytorch)压缩裁剪图片
  11. 必看 logit回归分析步骤汇总
  12. mysql jena rdf_Jena 操作 RDF 文件
  13. 智能手环guard日志获取-兔盯云
  14. Newline —— CRLF、LF、CR回车和换行
  15. 解读CUDA Compiler Driver NVCC - Ch.3
  16. 所属云服务器无效,常见错误码及解决方案
  17. 【今日CV 计算机视觉论文速览 第128期】Mon, 10 Jun 2019
  18. 计算点到道路的距离_在ArcMap中完成
  19. 营销活动此起彼伏,KTV加盟宝乐迪再掀新浪潮
  20. 2021年N1叉车司机考试及N1叉车司机模拟试题

热门文章

  1. 三极管流水灯电路设计
  2. 电偶极子的MATLAB场模拟
  3. 软件测试的概念与过程
  4. MT6589下载工具,MT6589刷机工具
  5. Storm概念详解和工作原理,topology、spout、bolt的细节和API讲解之一
  6. 【python做简单的数据分析、绘图】
  7. 修改ftp服务器地址,ftp服务器ip地址修改
  8. array unshift php,php – 用于多维数组的array_unshift
  9. Grid++Report报表开发工具介绍
  10. 邮件服务器mx记录,学习邮件服务器之MX记录