Alignement d’une séquence
avec une banque
Problématique générale
Localiser des alignements significatifs entre une séquence requête x dans une banque de p
séquences Y = {y0,y1,…,yp1}.
La solution par programmation dynamique en O(mn) si m = |x| et n = Σ|yi| est trop coûteuse.
Il faut donc développer des heuristiques.
FASTA (alignement global avec brêche) [Pearson & Lipman 1988]
On traite les yi séparément les unes à la suite des autres.
On considère deux entiers : k,ℓ > 0.
3 phases :
• localisation des facteurs de longueur ℓ de x dans y ;
• sélection de la diagonale d contenant le plus de facteurs de longueur ℓ ;
• alignement par programmation dynamique sur une bande de largeur 2k autour de la diagonale d.
n = |y|
On définit la diagonale d sur
{1,0,1,…,m1} x {1,0,1,…,n1} comme étant l’ensemble des couples (i,j) tels que j i = d.
On définit l’ensemble Zℓ par
Zℓ = { (i,j) | 0 ≤ i ≤ mℓ, 0 ≤ j ≤ nℓ et x[i..i+ℓ1] = y[j..j+ℓ1]}
Autrement dit, l’ensemble Zℓ contient tous les couples (i,j) tel que le facteur de longueur ℓ qui commence à la position i sur x est égal au facteur de longueur ℓ qui commence à la position j sur y.
Pour chaque diagonale –m ≤ d ≤ n on considère le nombre d’éléments de Zℓ se trouvant sur
cette diagonale :
compte[d] = card { (i,j) ∈ Zℓ | ji = d }
Pour calculer les valeurs de la table compte :
on associe de manière bijective un rang à chaque lettre a de l’alphabet A :
0 ≤ rang(a) ≤ card A 1 pour a ∈ A
On pose
code(w[0.. ℓ1]) =
Σ
rang(w[i]) x (card A)i pour w ∈ A* et |w| = ℓ.i = 0 ℓ1
Ainsi
code(w[i..i+ℓ1]) = code(w[i1..i+ℓ2]) / card A + rang(w[i+ℓ1]) x (card A)ℓ1
Les codes des facteurs de longueur ℓ de x sont calculés en une seule passe et on accumule les facteurs dans une table position à (card A)ℓ
éléments :
position[c] = { i | code(x[i.. i+ℓ1]) = c }
algo HACHAGE(x,m,ℓ)
pour c ← 0 à (card A)ℓ1 faire position[c] ← ∅
exp ← 1 code ← 0
pour i ← 0 à ℓ1 faire
code ← code + rang(x[i]) x exp exp ← exp x card A
position[code] ← { 0 } pour i ← ℓ à m1 faire
code ← code div card A + rang(x[i]) x exp position[code] ← position[code] U { iℓ+1 } retourner position
algo DIAGONALE(x,m,y,n,ℓ) pour d ← m à n faire
compte[d] 0← exp ← 1
code ← 0
pour j ← 0 à ℓ1 faire
code ← code + rang(y[j]) x exp exp ← exp x card A
pour chaque i ∈ position[code] faire compte[i] ← 1
pour j ← ℓ à n1 faire
code ← code div card A + rang(y[j]) x exp pour chaque i ∈ position[code] faire
compte[jℓ+1i] ← compte[jℓ+1i] + 1 retourner compte
Il suffit alors de repérer la diagonale d ayant le compte le plus élevé pour ensuite effectuer un alignement par programmation dynamique
autour de cette diagonale.
algo ALIGNEMENTBANDE(x,m,y,n,d,k) i’ ← max {1,d1k}
i’’ ← min {d1+k,m1}
j’ ← max {1,d1k}
j’’ ← min {d1+k,n1}
c ← g
pour i ← i’ à i’’ faire T[i,1] ← c c ← c+g c ← g
pour j ← j’ à j’’ faire T[1,j] ← c c ← c+g
pour i ← 0 à m1 faire
pour j ← i+dk à i+d+k faire si 0 ≤ j ≤ n1 alors
T[i,j] ← T[i1,j1] + Sub(x[i],y[j]) si |ji1d| ≤ k alors
T[i,j] min {← T[i,j],T[i,j1]+g } si |ji+1d| ≤ k alors
T[i,j] min {← T[i,j],T[i1,j]+g } retourner T
Exemple
x = YWCQPGK, m = 7
y = LAWYQQKPGKA, n = 11 ℓ = 2
k = 2
card A = 20
19 18
13 12
9 8
5 1
0
rang(a)
Y W
Q P
L K
G C
A a
165 112
253 261
38 379
code(x[i..i+ℓ1])
GK PG
QP CQ
WC YW
x[i..i+ℓ1]
5 4
3 2
1 0
i
0 2
3 5
4 1
position[c]
379 261
253 165
112 38
c
8 165
112 248
173 273
279 399
360 9
code(y[j..j+ℓ1)]
KA GK
PG KP
QK QQ
YQ WY
AW LA
y[j..j+ℓ1]
9 8
7 6
5 4
3 2
1 0
j
8 165
112 248
173 273
279 399
360 9
code(y[j..j+ℓ1)]
KA GK
PG KP
QK QQ
YQ WY
AW LA
y[j..j+ℓ1]
9 8
7 6
5 4
3 2
1 0
j
2
compte [d]
11 10
9 8
7 6
5 4
3 2
1 0
1
2
3
4
5
6
d 7
K 6
G 5
P 4
Q 3
C 2
W 1
Y 0
1
A K
G P
K Q
Q Y
W A
L
10 9
8 7
6 5
4 3
2 1
0
1 T
K 6
G 5
P 4
Q 3
C 2
W 1
Y 0
1
A K
G P
K Q
Q Y
W A
L
10 9
8 7
6 5
4 3
2 1
0
1 T
19
13
16
13 K
6
19
16
13
14
11 G
5
19
16
13
12
9 P
4
19
16
13
10
7 Q
3
19
16
13
10
7 C
2
17
14
11
8
5 W
1
15
12
9
8
5 Y
0
15
12
9
6
3
1
A K
G P
K Q
Q Y
W A
L
10 9
8 7
6 5
4 3
2 1
0
1 T
19
13
16
13 K
6
19
16
13
14
11 G
5
19
16
13
12
9 P
4
19
16
13
10
7 Q
3
19
16
13
10
7 C
2
17
14
11
8
5 W
1
15
12
9
8
5 Y
0
15
12
9
6
3
1
A K
G P
K Q
Q Y
W A
L
10 9
8 7
6 5
4 3
2 1
0
1 T
YWCQPGK AWYQQKPGK YWCQPGK AWYQQKPGK YWCQPGK AWYQQKPGK
ℓ : kTup
6 pour les acides nucléiques 2 pour les acides aminés
BLAST (Alignement local sans brêche) [Altschul et al 1990]
On considère deux entiers k et ℓ. On considère le score s défini par
s(u,v) =
Σ
Sub(u[i],v[i])pour deux mots u et v de même longueur.
i=0
|u|1
On va construire l’ensemble des voisins fréquentables de tous les facteurs de x de longueur ℓ.
Factℓ(x) = { w | w ≼fact x et |w| = ℓ } Vk(Factℓ(x)) = { z ∈ Aℓ | s(w,z) ≥ k
pour w ∈ Fact (x) }
L’ensemble Vk(Factℓ(x)) peut être construit en temps O(card Vk(Factℓ(x)) ) si on dispose pour chaque lettre a ∈ A de la liste des lettres de
l’alphabet triée dans l’ordre décroissant des scores de leur substitution à a.
Les éléments de cette liste sont des couples (b, Sub(a,b))
lettre score
Ces listes sont rangées dans une table à deux dimensions notée L.
algo GENERERVOISINS(ℓ) V ← ∅
seuil[ℓ1] ← k
pour i ← 0 à mℓ faire
pour j ← ℓ1 à 1 faire
seuil[j1] ← seuil[j]score(L[x[i+j],0]) GV(i,ε,0,0,0)
retourner V
algo GV (i’,v,j’,p,t) si j’ = ℓ alors
V ← V U { v } sinon
si t < card A alors c ← L[x[i’],t]
si p + score[c] ≥ seuil[j’] alors v ← v ∙ lettre[c]
GV(i’+1,v[0..j’],j’+1,p+score[c],0) GV(i’,v[0..j’1],j’,p,t+1)
L’appel GV(i,ε,0,0,0) calcule tous les voisins fréquentables de x[i..i+ℓ1].
Au début de GV(i’,v,j’,p,t)
p = s(v[0..j’1],x[i’j..i’1]) ≥ k
et on essaie d’étendre v par la lettre de L[x[i’],t].
(Y,5) (R,3)
(K,3) (E,3)
(A,3) (Q,5)
Q
(Y,5) (Q,3)
(K,3) (E,3)
(A,3) (K,5)
K
(Y,5) (R,3)
(Q,3) (K,3)
(A,2) (E,5)
E
(Y,5) (R,4)
(Q,3) (K,3)
(E,2) (A,5)
A
5 4
3 2
1 0
L
x = EAAQK, k = 8, ℓ = 3 seuil[2] ← 8
i ← (0,1,2) j ← (2,1)
i = 0, j = 2, seuil[1] ← 3 i = 0, j = 1, seuil[0] ← 2 GV(0,ε,0,0,0)
GV(1,E,1,5,0)
GV(2,EA,2,10,0)
GV(3,EAA,3,15,0) GV(2,EA,2,10,1)
GV(3,EAE,3,8,0)
GV(2,EA,2,10,2) EAK,7 < seuil[j’=2]
GV(1,E,1,5,1)
GV(2,EE,2,3,0)
GV(3,EEA,3,8,0)
GV(2,EE,2,3,1) EEE,1 < seuil[j’=2]
GV(1,E,1,5,2) EK,2 < seuil[j’=1]
GV(0,ε,0,0,1)
GV(1,A,1,2,0)
GV(2,AA,2,3,0)
GV(3,AAA,3,8,0)
GV(2,AA,2,3,1) AAE,1 < seuil[j’=2]
GV(1,A,1,2,1) AE,4 < seuil[j’=1]
GV(1,ε,0,0,0) GV(2,A,1,5,0)
GV(3,AA,2,10,0)
GV(4,AAQ,3,15,0)
GV(3,AA,2,10,1) AAA,7 < seuil[j’=2]
GV(2,A,1,5,1)
GV(3,AE,2,3,0)
GV(4,AEQ,3,8,0)
GV(3,AE,2,3,1) AEA,1 < seuil[j’=2]
GV(2,A,1,5,2) AK,2 < seuil[j’=1]
GV(1,ε,0,0,1)
GV(2,E,1,2,0)
GV(3,EA,2,3,0)
GV(4,EAQ,3,8,0)
GV(3,EA,2,3,1) EAA,0 < seuil[j’=2]
GV(2,E,1,2,1) EE,4 < seuil[j’=1]
GV(1,ε,0,0,2) K,3 < seuil[j’=0]
GV(2,ε,0,0,0) GV(3,A,1,5,0)
GV(4,AQ,2,10,0)
GV(5,AQK,3,15,0)
GV(4,AQ,2,10,1) AQA,7 < seuil[j’=2]
GV(3,A,1,5,1) AA,2 < seuil[j’=1]
GV(2,ε,0,0,1)
GV(3,E,1,2,0)
GV(4,EQ,2,3,0)
GV(5,EQK,3,8,0)
GV(4,EQ,2,3,1) EQA,0 < seuil[j’=2]
GV(3,E,1,2,1) EA,5 < seuil[j’=1]
GV(2,ε,0,0,2) K,3 < seuil[j’=0]
Ensuite on construit un AFD (automate fini déterministe)
A
tel queL
(A
) = A*Vk(Factℓ(x)) et on analyse y avecA
.Puis on étend (par programmation dynamique) vers la droite et vers la gauche les facteurs de y contenant des éléments de Vk(Factℓ(x)).
k : T (word score threshold) ℓ : W (word size)
Différentes versions
nucléique (traduction) nucléique
(traduction) TBLASTX
protéine nucléique
(traduction) TBLASTN
nucléique (traduction) protéine
BLASTX
nucléique nucléique
BLASTN
protéine protéine
BLASTP
banque requête
Améliorations
PSIBLAST : PositionSpecific Iterative : crée un profil pendant la recherche et le raffine au fur et à mesure des itérations.