4V748 – 09/04/2014 – Python, C, R

publicité
4V748 – 09/04/2014 – Python, C, R
Introduction
Nous allons écrire un programme qui calcule le repliement optimal d'un ARN simple brin, et détermine dans
quelle mesure ce repliement est crédible.
Repliement d'ARN
Une macro-molécule d'ARN peut se replier spontanément en solution, en réalisant des auto-appariements entre
ses bases ribo-nucléotidiques. Elle adopte alors une structure secondaire qui correspond à un optimum
énergétique (énergie libre minimale). On dispose de méthodes informatiques pour prédire le repliement optimal
d'une molécule en connaissant sa séquence.
Crédibilité : une question de statistiques
Certaines molécules d'ARN se replient, d'autres restent préférentiellement sous forme linéaire, ou dans un état
peu structuré mais dynamique, caractérisé par des états de repliement partiel labiles. Dans les deux cas, un
programme de calcul de structure secondaire peut proposer un repliement optimal : il existe toujours un état
replié d'énergie minimum. Comment savoir si le résultat du calcul correspond vraiment à l'état qu'adopte la
molécule, ou au contraire à une structure fortuite ?
Une observation permet de répondre à cette question de façon statistique : si l'on calcule le repliement optimal
de molécules d'ARN de séquence aléatoire, l'énergie libre de repliement est elle-même une variable aléatoire.
Cette variable suit une loi normale, dont les paramètres (moyenne et écart-type) dépendent uniquement de la
longueur et de la composition en bases de la séquence. Mais une molécule d'ARN qui existe véritablement sous
forme repliée a une énergie libre de repliement significativement plus basse que celle de la plupart des
séquences aléatoires de même longueur et composition. On peut en déduire une méthode de test de la validité
d'une structure (méthode du z-score) :
– Calculer l'énergie de repliement de l'ARN étudié : E 0 ;
– Créer un grand nombre (N) de séquences fictives, de même longueur et composition ;
– Calculer la distribution des énergies de repliement E i ,1i N de ces N séquences ;
– M et S étant respectivement la moyenne et l'écart-type de cette distribution, le z-score est défini par
E −M
. Plus z est négatif, et plus l'énergie de repliement de la structure calculée diffère de celle
z= 0
S
des structures aléatoires.
– La probabilité que la structure de l'ARN étudié soit fortuite est la proportion de séquences pour
lesquelles E i E 0 . On la calcule comme suit : P  E i E 0= P N uz  où PN désigne la probabilité
selon la loi normale centrée-réduite.
Nous allons mettre en œuvre cette méthode dans un programme en Python, avec l'aide de deux autres langages :
C et R.
1. Le C, un lointain souvenir ?
La bibliothèque de fonctions de référence pour le repliement d'ARN est le « Vienna Package » développé par
Ivo Hoffacker et ses collègues de l'Université de Vienne. En pratique, il s'agit d'une ensemble de fonctions
écrites en C, distribuées sous forme de fichiers sources dans un répertoire nommé ViennaRNA. La fonction
centrale que nous allons utiliser est fold, dont l'en-tête (qui se trouve dans le fichier fold.h) est :
float fold(const char *sequence, char *structure);
Cette fonction prend deux arguments : l'adresse de la chaîne sequence, qui contient la séquence à replier, et
l'adresse de la chaîne structure, dans laquelle elle va stocker le repliement, représenté par des parenthèses.
Par exemple :
De plus la fonction fold retourne un nombre de type float, qui est l'énergie libre de repliement en kJ.mol-1.
Ainsi, en supposant que nous ayons déclaré une variable de type float nommée mfe, et deux chaînes de
caractères de même longueur, seq et str, et que seq contienne la séquence à replier, nous pouvons effectuer
le repliement à l'aide de l'instruction :
mfe=fold(seq,str);
après exécution de cet appel, str contient la structure sous forme parenthésée, et mfe contient l'énergie libre
du repliement.
► Écrire en C le programme foldseq, qui contient une fonction dont l'en-tête est :
char *seq2str(const char *seq);
Cette fonction doit prendre en paramètre la chaîne de caractères seq qui contient la séquence à replier, et
retourner une chaîne de caractère qui contient la structure sous forme parenthésée. Pour ce faire, elle utilise la
fonction fold du package ViennaRNA, et le source C doit donc inclure fold.h, fold_vars.h, et
utils.h qui se trouvent dans /usr/local/include/ViennaRNA (cette localisation peut dépendre de
l'installation)
La fonction main() de foldseq appelle seq2str pour calculer et afficher le repliement optimal de la
séquence passée en argument lors de l'appel1. Exemple :
[prompt] ./foldseq GCCUCGAUAGCUCAGUUGGGAGAGCG
GCCUCGAUAGCUCAGUUGGGAGAGCG
(((((..((((...)))).))).)).
► Modifier seq2str pour que la chaîne retournée contienne de plus l'énergie libre de repliement (au
maximum 10 caractères de plus, dont 2 chiffres après la virgule). On obtient alors :
[prompt] ./foldseq GCCUCGAUAGCUCAGUUGGGAGAGCG
GCCUCGAUAGCUCAGUUGGGAGAGCG
(((((..((((...)))).))).)).
-5.90
2. Revenons à Python
Pour utiliser la fonction seq2str depuis Python, il faut la compiler à l'aide de SWIG, ce qui nécessite d'écrire
le fichier foldseq.i (s'inspirer de l'exemple du cours). La compilation elle-même se fait avec :
[prompt] swig -python foldseq.i
[prompt] gcc -shared -fpic foldseq.c foldseq_wrap.c -I
/usr/include/python2.6 -lRNA -lm -Xlinker -rpath
/usr/local/include/ViennaRNA -o _foldseq.so
La première de ces deux instructions génère les fichiers foldseq_wrap.c et foldseq.py.
foldseq_wrap.c est ensuite utilisé pour compiler foldseq.c et générer la bibliothèque partagée
_foldseq.so. Le fichier foldseq.py doit être importé pour que Python dispose des fonctions de la
1. Pour utiliser un tel argument, la convention est de déclarer int main(int argc, char *agrv), où argc
contient le nombre de mots de la ligne de commande, ici 2 : le premier (argv[0]) est le chemin vers le programme (ici
./foldseq) et le suivant (argv[1]) est le premier argument de la commande (ici la séquence à replier).
bibliothèque (ici, une seule fonction : seq2str). Par exemple, en mode interactif :
>>> import foldseq
>>> print foldseq.seq2str("GCCUCGAUAGCUCAGUUGGGAGAGCG")
(((((..((((...)))).))).)).
-5.90
► Créer une première version de pyfold.py, qui affiche la structure optimale et l'énergie libre d'une
séquence d'ARN, en utilisant seq2str.
3. Mélange
De même que pour le package ViennaRNA, une bibliothèque écrite en C nous permet de générer des séquences
aléatoires de même longueur et composition qu'une séquence de référence. Pour ce faire, le plus simple et de
mélanger (« shuffle ») les nucléotides de la séquence. C'est ce que réalise la fonction ushuffle de la
bibliothèque uShuffle. (cf http://digital.cs.usu.edu/~mjiang/ushuffle/). Cette dernière
est plutôt assez facile à installer, la procédure est expliquée dans le fichier Ushuffle_howto.txt.
► Installer la bibliothèque uShuffle. Après installation, on doit pouvoir obtenir :
>>> import ushuffle
>>> ushuffle.shuffle('aabaa', 5, 2)
'aaaba'
► Télécharger tRNAPhe.f depuis abiens.snv.jussieu.fr/mv448/doc/. Modifier pyfold.py,
pour générer 100 séquences mélangées à partir de tRNAPhe.f, et afficher pour chacune la structure optimale
et son énergie libre.
4. Et maintenant, du R
► Afin d'avoir des données à traiter par R, modifier pyfold.py pour qu'il écrive dans le fichier MFE.dat
uniquement les valeurs d'énergie libre pour la séquence tRNAPhe, puis pour les 100 séquences mélangées.
On peut alors tester les instructions R en mode interactif :
> E <- read.table("MFE.dat")
> E0 <- E[1,]
> E <- E[-1,]
> M=mean(E)
> S=sd(E)
> z=(E0-M)/S
> print(z)
-3.00755
> print(pnorm(z))
0.001316814
#
#
#
#
#
#
Lecture du fichier, stockage dans E
énergie du tRNAPhe = 1e ligne (NB pas 0)
seulement les 100 séquences mélangées
moyenne
écart-type
z-score
# probabilité P(x[i]<z) (loi normale)
► En s'inspirant de la séquence de commandes précédentes, et de l'exemple du cours, incorporer dans
pyfold.py les commandes R permettant de calculer z et la probabilité (utiliser la bibliothèque Rpy2).
► Ajouter les commandes R qui permettent de générer un graphique au format png (voir la fonction R png,
dont l'aide s'obtient par help(png)). Ce graphique doit représenter la distribution des énergies libres dans les
séquences mélangées (fonction hist), la courbe de la loi normale ajustée (utiliser dnorm et lines), et la
position de l'énergie libre de l'ARNt-Phe (avec abline).
Exemple :
Téléchargement