cours

publicité
Thème: Génomique et Analyse de séquences biologiques (Semaines 6 à
7)
L'analyse des séquences biologiques a connu ces dix dernières années un essor considérable avec
l’apparition du séquençage massif d'organismes, et de grandes bases de données génomiques.
L’exploitation de ces gigantesques bases a motivé le développement de modèles mathématiques ou
informatiques pour l’analyse automatique de ces séquences. Après une présentation des principales
macromolécules biologiques et leur fonction dans la cellule, ce cours décrit les méthodes et les outils
les plus communément utilisés pour analyser les séquences biologiques : recherche de signaux et de
zones codantes, techniques d’alignement (programmation dynamique), recherche de similarités
locales entre séquences. L’utilisation de ces outils sera illustrée sur des problèmes types comme la
comparaison de séquences, la recherche d’homologies, la prédiction. Différents programmes
d’analyse sont aujourd’hui accessibles par le web et seront utilisés aux TP.
Le cours illustrera quelques-uns des développements informatiques nouveaux nécessaires au
traitement et à la manipulation des données correspondantes.
PréTP (initiation à python)
(note: passer sous tcsh au CICRP !!!)
Générer un tableau de distance entre villes (plusieurs catégories de villes)
Programmation dynamique – Camions (tranches)
Présentation du langage Python – langage interprété interactif
Variables: type implicite
liste, tuple et string sont des séquences.
Indentation délimite les blocs d'instructions – instruction vide "pass"
Listes:
a = [] # déclaration d'une liste
Les listes commencent à 0, coordonnées négatives == permutations circulaires –1 == dernière case
(maximum négatif = -longueur, dernière case +1 : erreur,, types différents autorisés. Donc les
coordonnées vont de –longueur à +(longueur –1)
>>> a.append(3)
>>> a.append("toto")
>>> a.append("tutu")
>>> a.append("titi")
>>> a
[3, 'toto','tutu','titi']
a[1:3] # extrait sous liste éléments 1 à 3
['toto','tutu']
a = {} # création d'un tableau associatif qui peut être indexé par string,
entier ou tuple
a["toto"] = "TITI"
a[("toto","titi")] = "TOTOTITI"
a[("toto","tutu")] = "TOTOTUTU"
for i in liste:
# i prend successivement les valeurs de la liste
for i in xrange(debut, fin, step):
# i prend les valeurs de "debut à ("fin"-1) par pas de "step".
>>> for i in xrange(1,6,2):
... print i
...
1
3
5
while <test> :
def foo(arguments):
# indentation nécessaire
def plus(a,b):
return a+b
def carre(a):
return a*a
liste=range(4)
liste
[0, 1, 2, 3]
# lister les methodes liees a un objet
dir(liste)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__eq__',
'__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',
'__hash__', '__iadd__', '__imul__', '__init__', '__le__', '__len__', '__lt__',
'__mul__', '__ne__', '__new__', '__reduce__', '__repr__', '__rmul__',
'__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count',
'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
reduce(plus,liste) # f(f(f(liste[0],liste[1]),liste[2]), liste[3])..etc
6
map(carre,liste)
[0, 1, 4, 9]
map(plus, liste,liste)
[0, 2, 4, 6]
map(None, liste1,liste2): applique None aux doublets d'une liste constituée de
chacune des paires des éléments de liste1 et liste2
filter(f,liste): retourne la sous liste de liste constituée de chacun des
éléments pour lesquels f est vraie.
## Lecture fichiers:
>>>f=open('nom_fichier','r') # ouvre le fichier en lecture avec descripteur f
>>>l=f.readlines() # lit toutes les lignes et crée une liste
## Ecriture fichiers:
f=open("nom_fichier","w")
f.write("%d %f " % (1, random.random()))
## Librairie "string"
>>>import string
>>>l = "toto titi tutu"
>>> string.split(l)
['toto', 'titi', 'tutu']
## Nombres aléatoires
>>> import random
>>> random.random()
0.0119499521299
# préparation du fichier de villes
g=open("villes","w")
lv=string.split("a b1 b2 b3 b4 c1 c2 c3 c4 d1 d2 d3 e1 e2 e3 e4 e f1 f2 f3 g")
c={}
c["a"]=1
c["b"]=2
c["c"]=3
c["d"]=4
c["e"]=5
c["f"]=6
c["g"]=7
for x in lv:
for y in lv:
if c[x[0]]==c[y[0]]-1:
g.write("%s %s %f " % (x,y,int(100*random.random()))
g.close()
bubble, mergesort
ouvrir un texte (nedit) pour le programme "tri.py"
import tri # la première fois
reload(tri) # les autres fois
import random # création du fichier de nombres aléatoires
f=open("random","w")
i = 0
while i < 100:
f.write("%d %f " % (i, random.random()))
i=i+1
f.close()
f=open("random","r") # lecture du fichier de nombres aléatoires
ll=f.readline() # ll est une string avec toutes les valeurs
t=[] # création du tableau de valeurs
for x in string.split(ll):
t.append(string.atof(x))
Excercice: programmation dynamique
camions (programmation dynamique). liens avec les séquences
fichier "lv"
paris lyon 23
paris dijon 32
paris clermont 29
paris bordeaux 34
lyon valence 13
dijon valence 34
clermont valence 29
bordeaux valence 22
lyon cahors 22
dijon cahors 14
clermont cahors 19
bordeaux cahors 17
lyon millau 22
dijon millau 16
clermont millau 23
bordeaux millau 19
valence marseille 21
cahors marseille 27
millau marseille 18
#!/usr/local/bin/python2.1
import string
import copy
def camion():
f=open('lv','r')
lignes=f.readlines() # lignes: liste de string
t=[]
for l in lignes:
t.append(string.split(l))
distance={}
for i in t:
distance[(i[0],i[1])]=int(i[2])
print distance
tranche=[]
vd=string.split(l[0])[0]
tranche=[[vd]]
print tranche
courant=tranche[0]
while len(courant)!=0:
tmp=[]
for x in distance.keys():
if x[0]==courant[0]:
tmp.append(x[1])
if len(tmp)!=0:
tranche.append(tmp)
courant=tmp
print tranche
chemin=[(0,[vd])]
for x in tranche[1:]:
# x: tranches successives
newchem=[]
for k in x: # k: villes successives
mini=distance[(chemin[0][1][-1],k)]+chemin[0][0]
for z in chemin: # z: chemins successifs
if (distance[(z[1][-1],k)]+z[0]<=mini):
mini=distance[(z[1][-1],k)]+z[0]
y=copy.deepcopy(z)
y[1].append(k)
newchem.append((mini,y[1]))
chemin=newchem
print newchem
Cours 1 (2 heures):
1ère partie: le problème biologique (1h15)
Cellules procaryotes et eucaryotes : différences, ressemblances, chromosomes, machinerie cellulaire
Les macromolécules biologiques (polymères), structure, forme et information : reconnaissance
moléculaire (acides nucléiques, protéines), localisation cellulaire, fonctions.
Mécanismes génétiques fondamentaux :
- ADN support de l'information génétique : structure de l'ADN,
- polymère de nucléotides
-
double hélice complémentaire, orientation des brins
réplication de l'ADN
réparation de l'ADN, mutations, mécanismes de la recombinaison génétique, sélection, évolution
- ARN (ARM messagers et ARN de transfert) transcription, expression de l'information
génétique
- Synthèse protéique : traduction, code génétique, codage. Protéines: structure primaire,
structure secondaire, structure tertiaire, structure quaternaire.
Le passage du gène à la protéine se fait en deux étapes : tout d'abord le segment de la molécule
d'ADN correspondant au gène est copié sur un brin d'ARN, que l'on appelle ARN messager (ou
ARNm), c'est la transcription. Puis ce brin d'ARNm est à son tour recopié, mais dans un langage
différent, celui des acides aminés, pour donner la séquence correspondant à la protéine synthétisée,
c'est la traduction. La séquence polypeptidique ainsi constituée prend alors une forme spatiale qui
lui est spécifique pour devenir à proprement parler la protéine.
D'un point de vue plus formel, ces deux étapes sont très différentes. En effet pour la première on
garde le même alphabet, il s'agit donc simplement d'une recopie du gène. Cette recopie a
essentiellement deux intérêts : elle permet de recopier le gène sur un seul brin, forme certes moins
stable mais qui rendra plus simple le processus de traduction. En outre, chez les cellules eucaryotes,
seul l'ARNm se déplace hors du noyau ce qui protège la molécule d'ADN. L'étape de recopie peut
donc être vue comme une préservation de la molécule d'ADN, vitale pour la cellule. La seconde
étape, par contre, est une vraie traduction car on passe de l'alphabet à quatre lettres de l'ADN à
l'alphabet à vingt lettres des acides aminés. Voyons à présent plus en détail ces deux étapes.
Comme nous l'avons déjà évoqué plus haut, l'étape de transcription consiste en la recopie d'un
segment de brin d'ADN sur une molécule d'ARNm. Cette recopie se fait par l'intermédiaire d'une
enzyme appelée ARN-polymérase. Les fonctions de cette enzyme sont multiples. Tout d'abord, elle
doit reconnaître le commencement du gène portant l'information permettant de synthétiser la protéine
voulue. Ceci se fait grâce à un site spécifique sur la molécule d'ADN appelé promoteur, qui se situe
juste avant le début du gène. Un promoteur typique comporte une soixantaine de paires de base. Une
fois que la polymérase s'est liée au promoteur, elle commence la transcription du gène : elle ouvre
d'abord la double hélice (au niveau des liaisons hydrogène qui sont des liaisons faibles) puis elle
avance le long d'un des deux brins en synthétisant au fur et à mesure le brin complémentaire. Arrivée
à la fin du gène, une séquence spécifique provoque le détachement de la polymérase et le brin d'ARN
ainsi construit est libéré.
La molécule d'ARNm ainsi constituée sort ensuite du noyau (chez les cellules eucaryotes) pour subir
l'étape de traduction dans le milieu intracellulaire. L'alphabet utilisé reste identique, mis-à-part la
base T qui est remplacée par l'uracile U. Selon la polarité de la molécule d'ADN, le brin recopié ainsi
que le sens de recopie sont fixés pour chaque gène.
Notons ici que la transcription est dans les faits plus complexe car elle est suivie d'autres traitements,
qui ne retiennent du gène que sa partie effectivement codante (on parle d'épissage)
La traduction est une étape légèrement plus complexe, au moins d'un point de vue formel, car il s'agit
de passer de l'alphabet à quatre lettres à l'alphabet des acides aminés qui sont plus d'une vingtaine. Il
faut donc plusieurs bases pour pouvoir coder un acide aminé. Un rapide calcul montre qu'utiliser des
triplets de bases suffit à tous les déterminer. On code alors 43=64 mots ou codons, ce qui implique
que ce codage est redondant.
Figure : schéma simplifié de la traduction
La traduction se déroule dans le milieu intracellulaire, grâce à des agents appelés ribosomes. l'ARN
messager est lu par le ribosome qui associe à chaque codon, par l'intermédiaire d'une molécule
d'ARN particulière (l'ARN de transfert), l'acide aminé qui lui correspond. La chaîne polypeptidique
ainsi constituée subit à son tour quelques traitements (dont la prise de sa forme, souvent très
complexe) pour devenir la protéine désirée..
Le Code Génétique Universel
|
T
|
C
|
A
|
G
|
--+-------------+-------------+-------------+-------------+-| TTT Phe F | TCT Ser S | TAT Tyr Y | TGT Cys C |T
T | TTC Phe F | TCC Ser S | TAC Tyr Y | TGC Cys C |C
| TTA Leu L | TCA Ser S | TAA Stop
| TGA Stop
|A
| TTG Leu L | TCG Ser S | TAG Stop
| TGG Trp W |G
--+-------------+-------------+-------------+-------------+-| CTT Leu L | CCT Pro P | CAT His H | CGT Arg R |T
C | CTC Leu L | CCC Pro P | CAC His H | CGC Arg R |C
| CTA Leu L | CCA Pro P | CAA Gln Q | CGA Arg R |A
| CTG Leu L | CCG Pro P | CAG Gln Q | CGG Arg R |G
--+-------------+-------------+-------------+-------------+-| ATT Ile I | ACT Thr T | AAT Asn N | AGT Ser S |T
A | ATC Ile I | ACC Thr T | AAC Asn N | AGC Ser S |C
| ATA Ile I | ACA Thr T | AAA Lys K | AGA Arg R |A
| AUG Met M | ACG Thr T | AAG Lys K | AGG Arg R |G
--+-------------+-------------+-------------+-------------+-| GTT Val V | GCT Ala A | GAT Asp D | GGT Gly G |T
G | GTC Val V | GCC Ala A | GAC Asp D | GGC Gly G |C
| GTA Val V | GCA Ala A | GAA Glu E | GGA Gly G |A
| GTG Val V | GCG Ala A | GAG Glu E | GGG Gly G |G
--+-------------+-------------+-------------+-------------+--
Dogme central: ADN -> ARN -> Protéines
Organisation fonctionnelle de l'ADN :
- taille des génomes (procaryotes, eucaryotes) : nombres de gènes, pourcentage de codant.
- gènes (procaryotes, eucaryotes), opérons
- synthèse et maturation de l'ARN, éléments de base dans le contrôle de l'expression génique
(CAT box, TATA box, terminateurs), mécanismes de régulation des gènes.
Analyse des génomes – annotation :
Le problème crucial de l'analyse de séquences génomiques est l'identification des séquences codantes
(processus d'annotation). Chez les procaryotes, cette identification est grandement facilitée par la
quasi absence de séquences non codantes et l'absence d'introns, et par la possibilité de reconnaître
assez facilement les phases ouvertes de lecture, les promoteurs et les terminaisons des gènes. Chez
les bactéries E. coli ou H. influenzae, plus de 85% du génome est transcrit. De plus, des signaux
indicateurs de gènes existent souvent chez les procaryotes (ex: RBS ribosome binding site, sequence
Shine-Dalgarno, TATA box, boite de Pribnov).
Deux caractéristiques compliquent radicalement l'identification des séquences codantes chez les
eucaryotes : le découpage des gènes en introns et exons, et la présence de régions intergéniques
parfois très vastes (et les répétitions, LINE: "long interspersed elements", SINE: "short interspersed
elements").
Organisme
Nombre de gènes % de codant
taille (Kb)
Procaryote
Mycoplasma genitalium
580
480
91
Helicobacter pilori
1668
~1600
91
Bacillus subtilis
E. coli
Eucaryotes
S. cerevisiaie (levure)
C. elegans
H. sapiens
4215
4639
~4000
~4300
86
88
13 Mb (16 chromosomes)
~100 Mb
~3Gb
~6400
~18000
~30000
70
<5
L'identification des unités transcriptionnelles reste possible grâce à des outils informatiques capables
d'identifier un gène sur plusieurs critères : la présence d'une phase ouverte de lecture, de signaux
d'épissage, la composition en bases. On utilise aussi pour déterminer si une séquence est codante la
comparaison à l'ensemble des données acquises par les programmes de séquençage d'ADN. Une
similarité entre une séquence génomique et une séquence ADNc permet de conclure que cette
séquence est transcrite (voir la recherche sur banque).
On utilise l'information à priori concernant l'organisme pour identifier les gènes et l'organisation des
chromosomes : usage des mono et dinucléotides, biais de codage, biais dans l'usage du code (recstat,
codon preference).
Banques de séquences:
Il existe de nombreuses banques de séquences : il s'agit de base "à plat" (les séquences sont à la suite
les unes des autres, des identificateurs existent en début de ligne.
SwissProt : banque "propre" de séquences protéiques (environ 100 000 séquences en 2000)
EMBL/GenBank: banque de séquence nucléiques (106 séquences). TrEMBL/Genpept : séquences
protéiques transcrites de GenBank.
PIR: banque protéique
NR: "non redondante", assemblage de Swissprot, Genpept + PIR
Autres banques :
Prosite: banque de motifs biologiques (famille)
PRODOM: banque de domaines associés à des familles
PDB: banque de structures cristallographiques/RMN (environ 6000 structures en 2000, mais trsè
redondant (environ 100 lysozymes, dont beaucoup de mutants ponctuels dont la structure 3D ne
change pas).
2ème partie: formalisation de quelques problèmes de reconnaissance
Recherche de signaux : 2 types :
- recherche de pattern (motif): ex: recherche de promoteurs de la transcription (CAT ou TATA
box), Ribosome binding site (RBS)
- recherche de "consensus" : matrice score position / Bayes
Recherche de signaux:
On utilise des algorithmes courants sur les chaînes de caractères (Boyer-More, Aho Corasick) et les
expressions régulières.
Matrice de poids score-position (PSSM):
La méthode [Trifonov, 1985] consiste à définir, à partir d'un lot de séquences alignées, une matrice de
poids décrivant, en chaque position, la fréquence d'apparition de chaque type de résidus dans
l'alignement multiple. On cherche ensuite des signaux potentiels sur une nouvelle séquence en
appliquant la matrice considérée sur une fenêtre glissant le long de la séquence. A chaque pas, on
calcule un score égal à la somme des poids associés aux résidus délimités par la fenêtre, en fonction
de leur nature et de la position consensus que l'on considère. Pour ce qui est de la détection de
signaux sur des séquences protéiques cette méthode souffre du fait qu'elle ne permet pas de
considérer les relations de proximité entre acides aminés (voir prochain cours sur les système de
score et les matrices de substitution entre acides aminés). Gribskov et collaborateurs proposent une
méthode également fondée sur la définition d'une matrice de poids, mais permettant en plus la prise
en compte d'une matrice de distance entre acides aminés [Gribskov et coll., 1987]. Cette matrice de poids
est appelée "profile" ou "position-specific scoring matrix" (PSSM), un terme équivalent étant le
terme "position-dependent weight matrix". Une PSSM consiste en plusieurs colonnes de scores pour
chaque aminoacide, dérivées des positions correspondantes d'un alignement multiple (une colonne
peut aussi inclure un score pour un gap). Un "profile" est une PSSM construite en utilisant la
moyenne des scores.
Le calcul du score d'une position d'une PSSM est basée sur les probabilités de Bayes (rappel:
P(A et B) = P(A/B)*P(B) = P(B/A)*P(A)). Pour chaque "morceau" de la séquence examinée, on veut
que le score représente la probabilité d'avoir une instance du motif cherché étant donnée ce
"morceau" de séquence, donc P(motif/séquence). Or ce qu'on aurait dans la matrice
fréquence/position (qui serait calculée directement à partir de l'alignement multiple qui représente le
motif), c'est exactement la probabilité symétrique, c'est à dire la probabilité d'avoir la séquence si on
est dans une instance du motif, donc P(séquence/motif). Le théorème de Bayes nous permet de tirer
la probabilité cherchée P(motif/séquence) à partir de la probabilité P(séquence/motif).
Méthode : on peut facilement à partir d'un alignement multiple générer les fréquences associées à
chacun des acides aminés à chacune des positions dans une matrice 20 * longueur du motif
(20: nombre des acides aminés). Cette matrice représente les probabilité d'avoir tel ou tel acide aminé
à telle position si on a un motif, donc P(séquence/motif). Vu qu'on cherche P(motif/séquence), en
utilisant Bayes, on obtient:
P( séquence | motif ) × P( motif )
P( motif | séquence) =
P( séquence)
Si on suppose l'indépendance des positions successives, on peut écrire:
P( séquence) = ∏ P( aai )
i
et P( séquence | motif ) = ∏ P( aai | motif )
i
avec P(aai) probabilité dans la banque du i-ème acide aminé de la séquence
Donc, on obtient:
∏i P(aai | motif ) × P(motif )  P(aai | motif ) 
= ∏
P( motif | séquence) =
 × P( motif )
P( aai ) 
i 
∏ P(aai )
i
On retrouve bien le fait que si les acides aminés constituant la séquence du motif sont très abondants
dans la banque de séquence - i.e. les P(aa(i)) sont grands - cela réduira d'autant la probabilité d'avoir
effectivement un motif si on trouve une séquence ressemblant à celle du motif.
On ne connaît pas a priori la probabilité du motif (ce n'est pas très grave dans la mesure où elle sera
la même, quelle que soit la région considérée). Par contre, on connaît les P(aa(i)/motif), c'est la
fréquence (entre 0 et 1) de l'acide aminé à la position i dans le motif (dans les séquences pré-alignées
qui nous ont servi à caractériser ce motif). De même, on connaît P(aa(i)), c'est la probabilité d'avoir
l'acide aminé sur toutes les séquences (fréquence de aa(i) dans la séquence examinée, ou dans la
banque). Comme indiqué ci dessus, on va prendre comme score P(motif/aa(i)) =
P(aa(i)/motif)/P(aa(i)), ce qui revient à pondérer la fréquence de l'acide aminé dans la colonne de
l'alignement par sa fréquence dans la banque. Le score associé à une position sur une séquence
examinée sera donc le produit des P(motif/aa(i)) (ou la somme des log). Note: il faudra
éventuellement s'arranger pour ne pas avoir de P(motif/aa(i)) égal à 0, sinon dès qu'un acide aminé
présent sur la séquence n'est pas du tout présent dans la colonne correspondante de l'alignement,
P(motif/séquence) sera nul, même si les acides aminés à côté de celui ci sont tous présents dans le
motif avec une grande probabilité (ceci peut être fait en utilisant une matrice de similarité avec
laquelle on redistribuera la probabilité d'un acide aminé présent sur les autres acides aminés
éventuellement absents grâce au score de similarité entre eux).
Recherche de zones codantes (ce point sera détaillé au TD1):
- méthodes statistiques : comptage de mots, chaînes de Markov, analyse factorielle, mesure du
biais d'usage du code
- apprentissage : réseaux neuronaux, Hidden Markov Model, caractérisation de site (RBS).
(tous ces points ne seront pas traités en détail – cela dépendra du temps)
Modèles de Markov, IMM (interpolated Markov Model)
Les programmes d'annotation Genmark (Borodovski) et Glimmer (Salzberg) utilisent de tels modèles
pour la détection de zones codantes.
Rappel sur les chaînes de Markov:
Processus de génération d'une séquence dans lequel on tient compte des états précédents pour
"émettre" l'état courant. Ce modèle est utilisé en bioinformatique comme modèle de séquence
aléatoire d'ADN (par exemple, comme modèle hypothèse nulle, H0, dans la détermination des mots
sous ou sur-exprimés). L'ordre d'une chaîne de Markov est le nombre d'états précédents dont on a
tenu compte pour émettre l'état courant.
Ordre 0: indépendance des positions (P(X1X2) = P(X1)*P(X2)
Ordre 1: P(X/X1) 42=16 paramètres P(A/A), P(A/G), P(A/C), P(A/T), P(C/A)....
Ordre 2: P(X/X1X2) 43=64 paramètres P(A/AA), P(A/AC), P(A/AG),...
Ordre k: 4k+1 paramètres
Utilisation pour calculer la fréquence théorique des mots de taille m dans une séquence:
on veut calculer P(X1X2...Xm) en tenant compte des fréquences connues des sous mots de taille k.
Remarque : si m est la taille, le plus petit ordre k possible est m-2.
mots de taille m=2
k = 0 P(X1X2)=P(X1)P(X2) fréquence des dinucléotides dans l'hypothèse d'indépendance des
mononucléotides
mots de taille m=3
k = 1 P(X1X2X3)= P(X1).P(X2/X1).P(X3/X2)
or on a P(AB)=P(B/A).P(A) donc P(B/A) = P(AB)/P(A)
d'où P(X1X2X3)= P(X1).P(X1X2)/P(X1).P(X3/X2)/P(X2) = P(X1X2).P(X2X3) / P(X2), fréquence des tri en
tenant comte des di (et des monos).
k = 0, P(X1X2X3)= P(X1).P(X2).P(X3)
Le principe de calcul général est simple:
- fixer les k premiers nucléotides P(X1...Xk)
- rajouter (produit) les probas de transition suivantes P(Y/X1...Xk)
- - utiliser la formule P(B/A) = P(AB)/P(A) pour simplifier
m \ 0 (mono)
1 (di)
2 (tri)
m-2 (m-1mère)
ordre
2
P(X1).P(X2)
P
(
X
X
).
P
(
X
X
)
3
P(X1).P(X2).P(X3)
1 2
2 3
P( X 2 )
P( X1 X2 X3 ).P( X2 X3 X4 )
4
P(X1).P(X2).P(X3).P(X4) P( X1 X2 ).P( X2 X3 ).P( X3 X4 )
P( X2 ).P( X3 )
P( X2 X3 )
m
P( X1 X2 ).P( X2 X3 )....P( Xm −1 Xm )
P( X1 ... Xm −1 ).P
m
P( Xi )
∏
P( X2 ).P( X3 )...P( Xm −1 )
P( X2 ... X
i =1
Applications :
Statistique sur les mots
Permet de calculer E(Nw), l'espérance du nombre de mot w, w étant un mot X1...Xm . Note: le calcul
de Var(Nw) est beaucoup plus compliqué (Schbath et al. JCB, 1995)
Utilisation pour la détection de zones codantes:
2 étapes:
- apprentissage sur des exemples de gènes (ex: longues ORF), c'est à dire estimation des probas
de transition suivant différents ordres)
- comparaison sur la séquence étudiée des fréquences observées à celles attendues.
En général, le score est calculé sur une fenêtre glissante sur les 3 phases directes et les 3 phases
inverses (puis normalisé à 1 sur l'ensemble des phases).
Intérêt et problèmes:
-
-
à l'heure actuelle, c'est la méthode la plus efficace pour procaryotes (et certains eucaryotes)
utiliser l'ordre le plus élevé possible lorsque l'apprentissage est réalisé sur un grand ensemble
(problème de l'évaluation des paramètres, il faut un nombre d'exemple suffisant d'exemple
pour calculer les 4k paramètres)
problème des classes d'expression des gènes (tous les gènes n'ont pas les mêmes fréquences
d'apparition des mots)
problème des gènes chevauchants
Calcul des probabilités dans Genmark (Borodovski et al., Comp. Chem. 1993) :
Fragment F = AGGCAT
P(F) = P(AG).P(G/AG).P(C/GG).P(A/GC)... (pour un modèle de Markov d'ordre 2).
En fait, ceci est calculé pour les 7 cas exclusifs suivants:
Cod1 Cod2 Cod3 Cod-1 Cod-2 Cod-3 NonCod
<--- codant 6 phases ---------------> Non codant
Pour l'exemple plus haut, on a donc : F = A1G2G3C4A5T6
P(F/Cod1) = P01(AG).P1(G/AG).P2(C/GG).P3(A/CG).P1(T/CA)...(chaîne de Markov non homogène :
périodique). Les Pi sont estimés sur les données d'apprentissage (matrice de transition (pour les 7
cas)).
Par exemple, P1(G/AG) = N1AGG / N1x
En réalité, on ne cherche pas P(F/Cod1) mais P(Cod1/F) (formule de Bayes)
P(Cod1/F) = P(F/Cod1).P(Cod1)/∑P(F/Codi).P(Codi) (la somme est sur les 7 cas ci dessus, Cod1...-3 et
NonCod). On peut prendre P(Cod1) = 1/7 ou tenir compte du % de codant de l'organisme.
Dans les IMM ("interpolated markov models", programme Glimmer), la profondeur du modèle utilisé
va dépendre de la région examinée. Par exemple, si on est dans un génome riche en bases A et T, le
modèle de Markov utilisé dans la détection de gènes dans les zones AT riches sera d'ordre plus élevé
que celui utilisé dans les régions GC riches (car on a évidemment plus d'exemples pour le créer).
TD 1 / TP 1 (2 * 2h):
Partie TP: recherche de régions codantes par chaînes de Markov (sur un brin).
- système d'apprentissage (3 tables des mots phasés -> calcul des matrices de transition (ex:
proba(T suivant A) pour un modèle d'ordre 1, calculé sur les mots de longueur 2, on prend
ordre 0 pour le non-codant par exemple. Matrice de transition de 12 par 4^n, n étant l'ordre du
modèle, 12 car 4 bases*3phases).
- système d'évaluation des scores (calcul de la proba en appliquant la matrice avec une fenêtre
glissante par pas de 3-> 3 probas -> application de Bayes (ex: procaryotes: 90% de codant)).
Expressions régulières:
métacaractères classiques :
• . n’importe quel caractère
• ? 0 ou 1 fois le caractère précédent
• * 0 ou plusieurs fois le caractère précédent
• + 1 ou plusieurs fois le caractère précédent (pas toujours présent selon le programme°
o A+ équivaut à AA*
• [] désigne une classe de caractères considérés comme équivalents. Dans les crochets deux
caractères acquièrent une signification particulière :
o – intervalle [0-9 A-Z]
o ^nie une classe de caractères [^0-9] ne concorde avec aucun nombre
• ^ début de ligne
• $ fin de ligne ^$ concorde avec les lignes vides c’est-à-dire les lignes avec seulement un
retour chariot (pas d’espace)
• \ annule la signification du métacaractère suivant \\ correspond au caractère \ lui-même.
Métacaractères des expression étendues
• {} indique un certain nombre d’occurrences du caractère précédent b{2,5} correspond à
bb, bbb,bbbb,bbbbb
• () groupement d’expression vu avec le | qui signifie ou
A(ATG|TTG)G signifie A sui vi de ATG ou TTG puis G
Exercice : trouver une expression régulière qui permette de trouver les ORFs dans une séquence avec
- commence par ATG, TTG, ou GTG
- fini par TAA et TAG (TGA n'est pas un stop chez les mycoplasmes, mais un TRP)
- entre les deux au moins 20 codons qui ne soient pas des stops.
Correction:
L’expression est la suivante :
commence par ATG, TTG ou GTG: [ATG]TG
au moins 20 codons "non stop":
La seule difficulté est de donner le pattern pour « pas codon stop », donc ni TAA ni TAG.
[^¨T] . .
[^A] .
T
A[^AG]
([^T]..|T([^A].|A[^AG])){20,}
un codon stop TAA ou TAG : TA[AG]
d'où l'expression totale suivante :
[ATG]TG([^T]..|T([^A].|A[^AG])){20,}TA[AG]
Pour chercher sur la séquence complémentaire inversée (sans avoir à inverser-complémenter la
séquence, on prend l'expression suivante (on commence par un stop complémentaire inversé, TTA ou
CTA, puis par un non stop complémentaire inversé, puis on finit par un start complémentaire inversé
(CAT, CAA ou CAC):
([AC]TA)(([AG]..)|([CT][^T].)|([CT]T[^A])){300,}CA[TAC]
En fait, on peut "oublier" les stops pour ne pas les compter dans les statistiques.
## expr reguliere
import re
##compile(fabrique l'automate): orf=re.compil('expre_reguliere')
##findall: list=re.findall(orf,seq)
##function de concaténation de chaines
def concat(l):
return reduce(lambda x,y:x+y,l).upper()
##lit et rend une sequence, ne pas oublier l'affectation devant
def readseq(f):
return concat(map(lambda x:x[0:-1],open(f).readlines()))
##passe une chaine 5-3 en une chaine 3-5 attention mauvaise complexité
def reverse(l):
l=list(l)
l.reverse()
return concat(l)
##passe d'un brin a l'autre
def complement(l):
return concat(map(lambda x:{"A":"T","G":"C","T":"A","C":"G"}[x],l))
##associe complement et reverse sans les utiliser
def antiparallele(l):
l = map(lambda x:{"A":"T","G":"C","T":"A","C":"G"}[x],l)
l.reverse()
return concat(l)
##function findorf et rend une liste de string correspondant aux orf's
def find_orf(seq):
orf=re.compile('[ATG]TG(([^T]..)|(T[^A].)|(TA[CT])){300,}')
orfc=re.compile('(([AG]..)|([CT][^T].)|([CT]T[^A])){300,}CA[TAC]')
m=re.search(orf,seq)
mc=re.search(orfc,seq)
fin=m.end(0)
finc=mc.end(0)
l_orf=[]
l_orfc=[]
while (m):
l_orf.append(m.group(0))
fin=fin+m.end(0)+1
m=re.search(orf,seq[fin:])
while (mc):
l_orfc.append(mc.group(0))
finc=finc+mc.end(0)+1
mc=re.search(orfc,seq[finc:])
return l_orf + map(antiparallele,l_orfc)
Cours 2:
formalisation de quelques problèmes biologiques : ressemblance entre les séquences
Alignement de séquences : intérêt biologique : comparaison (étude de l'évolution), annotation des
génomes, recherche de la fonction d'une protéine.
Alignement optimal de 2 séquences:
- qu'est ce qu'un alignement – impératifs "biologiques" – distance d'édition
- complexité de l'algorithme "brute force"
- programmation dynamique ("divide and conquer"): alignement global de 2 séquences (NWS),
variantes, alignement local de 2 séquences (Smith et Waterman), complexité quadratique.
- les différents systèmes de scores employés (basés sur l'aspect "biologique" du problème) :
matrices de distances/similarité/substitutions (exemples : PAM, BLOSUM)
(suite à voir en TD)
Recherche sur banque – recherche de similarités locales :
- nécessité d'une heuristique (problème de complexité)
- algorithmes basiques (hashing table, FASTA, BLAST)
TD 2 / TP 2 (2 * 2h):
(fin du cours de recherche sur banque)
Partie TP : Alignement : réalisation sous Scilab d'un programme d'alignement NWS (algorithme de
programmation dynamique), si temps suffisant: modification en ses variantes (bestfit, Smith et
Waterman)
Téléchargement