Cet article a pour but de vous montrer une application pratique de BLAST, le fameux programme d'alignement de séquences détenant un record de citations, avec certains problèmes qu'on peut rencontrer et ce qu'on peut tirer de son résultat. BLAST a au moins deux usages typiques en génomique :
- Trouver les occurrences similaires à une séquence de bases ou d'acides aminés donnée ("query") dans une séquence de référence, par exemple un génome entier.
- Comparer deux séquences supposées semblables (par exemple des gènes orthologues ou leurs protéines) pour mesurer leur similarité et repérer ce qui est conservé/muté.
Pour les initiés, le premier point est à ne pas confondre avec ce qu'on utilise en séquençage à haut débit pour aligner des millions de petites séquences. BLAST recherche des séquences similaires, et pas l'emplacement de la séquence exacte (à erreurs de séquençage près). Il alignera une ou plusieurs parties de la séquence, éventuellement séparées par des "trous" ("gaps"). Le principal critère pour qu'il reporte un alignement est qu'il arrive à trouver au moins un "mot" de taille 11 (par défaut, on peut le changer) présent exactement dans la référence, puis il étend l'alignement autour de ce mot.
BLAST possède une interface web facile d'utilisation, même s'il faudra comprendre l'algorithme de Smith-Waterman pour être en mesure d'ajuster ses paramètres avancés. Mais nous allons l'utiliser en ligne de commande pour plus d'efficacité et de stabilité, et voir comment retirer du résultat les infos qui nous intéressent.
Un exemple pratique
Je vous propose l'application suivante, tirée d'un cas réel récent :
- On recherche près des télomères (à moins de 500Kb) des domaines appelés CRISPR, qui serviront de cible pour insérer artificiellement des fragments d'ADN dans l'organisme. En voilà un exemple : GCGGGTCCTGTAGTGCCGGG.
- Les régions télomériques de l'assemblage de référence habituel (de NCBI) sont incorrectes, et le "client" possède sa propre séquence de référence, plus précise.
- Le client veut trouver, parmi une douzaine de CRISPR, lequel à la fois se trouve sur un maximum de régions télomériques, et est absent du reste du génome. C'est-à-dire, lequel est le plus spécifique aux régions d'intérêt (pour éviter d'insérer de l'ADN codant n'importe où ailleurs).
Partons du principe que vous avez installé BLAST. Commençons par préparer la "query" : les séquences CRISPR à rechercher. Pour cela on crée un fichier "crispr.fasta", de ce type :
>seq1
GTGCCCCGGCGCCACGANGG
>seq2
GTGCCCGGCTGCAAGCANGG
>seq3
CGCCCCCTCGTGGCGCCNGG
Notez le nucléotide "N" (="n'importe quelle base"). En principe, BLAST devrait gérer les consensus IUPAC, mais en fait ça peut être très limitant en pratique (voir ici, 7.2).Ensuite, comme nous fournissons nous-mêmes la référence "reference.fasta" (pour l'exemple, on pourrait prendre le chromosome 20 de l'humain : chr20.fa.gz, à décompresser et renommer), il faut créer l'index correspondant avec la commande "formatdb" en ligne de commande :
formatdb -p F -i reference.fasta -o T
ce qui créera plein de petits fichiers mystérieux, que vous préférerez peut-être grouper dans un dossier propre. Le "-p F" indique qu'on aligne des nucléotides ("-p T" pour les protéines). Le "-o T" est moins clair, lié au format des headers du fasta, mais conseillé tant que ça marche.Enfin on peut lancer BLAST en lui donnant la query et la référence, comme ça :
blastall -p blastn -d reference.fasta -i crispr.fasta -o alignments.txt
"blastall" est le programme générique, puis on peut choisir le type d'alignement : "blastn"/"nc_megablast"/"megablast" (nucléotides), "blastp" (acides aminés), etc. Nous utilisons le standard "blastn", très permissif, mais si on cherchait des séquences très proches de la nôtre, on préférerait "megablast" ou "nc_megablast" (nc_ pour non-continuous) - voir ici comment choisir le bon.Le résultat, "alignments.txt", peut être assez lourd. Pour chaque séquence (par ex. chromosome) de la référence, il donne tous les alignements trouvés de chaque séquence de crispr.fasta. Un extrait correspondant à la query "seq3" (en utilisant le chromosome 20 de l'humain - hg19 - comme référence) :
[...]>chr20
Length = 63025520Score = 30.2 bits (15), Expect = 7.4
Identities = 15/15 (100%)
Strand = Plus / MinusQuery: 1 cgccccctcgtggcg 15
|||||||||||||||
Sbjct: 1946483 cgccccctcgtggcg 1946469Score = 30.2 bits (15), Expect = 7.4
Identities = 15/15 (100%)
Strand = Plus / PlusQuery: 3 ccccctcgtggcgcc 17
|||||||||||||||
Sbjct: 34330497 ccccctcgtggcgcc 34330511[...]
On voit que "seq3" a trouvé deux homologues sur le chromosome 20 : les bases 1-15 en position 1946483-1946469, et les bases 3-17 en 34330497-34330511. Un score d'enrichissement est donné, ainsi que le nombre de matches sans erreur ("Identities"). Tout en haut est indiquée la taille du chromosome ; on voit ainsi que ces deux alignements particuliers sont loin des télomères, donc pas du tout ce qui nous intéresse.Mais quand il y a des milliers de lignes comme celles-ci, on se dit qu'il faut un moyen plus systématique d'examiner les résultats. De toute évidence, le parser soi-même est un cauchemar ; heureusement, des outils sont déjà disponibles. J'ai choisi Biopython, la librairie bioinfo du langage Python. Voilà comment examiner le contenu du fichier :
from Bio import SearchIO
records = SearchIO.parse("alignments.txt", "blast-text") # iterateur
for record in records: # record est un objet QueryResult
for hit in record: # hit est un objet Hit
for hsp in hit: # hsp est un objet HSP
print hsp
Les objets QueryResult, Hit et HSP contiennent et rendent accessible toute l'info du fichier à travers leurs attributs. Un QueryResult concerne une query, en particulier :record.hit_keys # les references touchees par cette query
record.hsps # raccourci pour iterer sur les HSPs
record.id # nom de la query (comme "seq1")
record.program # programme utilise (comme "blastn")
record.seq_len # longueur de la query (20)
record.target # nom de la sequence de reference
Un Hit est l'ensemble des alignements de la query sur une certaine référence, en particulier :hit.hsps # liste des HSPs
hit.id # nom de la reference touchee (comme "chr1")
hit.query_id # nom de la query
hit.seq_len # longueur de la reference touchee
Un HSP est un alignement particulier. Il a de nombreux attributs qui parlent d'eux-mêmes pour la plupart :>>> dir(hsp)
[..., 'aln', 'aln_all', 'aln_annotation', 'aln_annotation_all',
'aln_span', 'alphabet', 'bitscore', 'bitscore_raw', 'evalue',
'fragment', 'fragments', 'gap_num', 'hit', 'hit_all',
'hit_description', 'hit_end', 'hit_end_all', 'hit_features',
'hit_features_all', 'hit_frame', 'hit_frame_all', 'hit_id',
'hit_inter_ranges', 'hit_inter_spans', 'hit_range', 'hit_range_all',
'hit_span', 'hit_span_all', 'hit_start', 'hit_start_all',
'hit_strand', 'hit_strand_all', 'ident_num', 'is_fragmented',
'pos_num', 'query', 'query_all', 'query_description', 'query_end',
'query_end_all', 'query_features', 'query_features_all',
'query_frame', 'query_frame_all', 'query_id', 'query_inter_ranges',
'query_inter_spans', 'query_range', 'query_range_all',
'query_span', 'query_span_all', 'query_start', 'query_start_all',
'query_strand', 'query_strand_all']
Ce qui nous permet de compter par exemple combien de fois "seq1" s'aligne à plus de 500Kb des télomères :from Bio import SearchIO
records = SearchIO.parse("alignments.txt", "blast-text")
record = records.next() # la premiere query
intergenomic = 0
telomeric = 0
for hit in record:
for hsp in hit:
if hsp.hit_range[1] > 500000 and hsp.hit_range[0] < hit.seq_len-500000:
intergenomic += 1
else:
telomeric += 1
Résultat :>>> print "Nombre de hits intergenomiques:", intergenomic
0
>>> print "Nombre de hits telomeriques", telomeric
1
>>> print hsp # le seul alignement, encore dans cette variable
Query: seq1
Hit: chr20
Query range: [1:14] (1)
Hit range: [62917482:62917495] (1)
Quick stats: evalue 4.7; bitscore 26.30
Fragments: 1 (13 columns)
Query - tgccccggcgcca
|||||||||||||
Hit - tgccccggcgcca
Sur ce chromosome au moins, tout va bien ! "seq1" n'est présente qu'une fois près du télomère, et nulle part ailleurs, même si seulement 13 nucléotides s'alignent.A vous ensuite d'adapter le script à vos besoins particuliers.
Remarques :
- On peut aussi demander à BLAST une sortie en format XML.
- On peut aussi lancer BLAST directement depuis Biopython !
Merci à Sylvain P., Clem_, ook4mi et Yoann M. pour leur relecture.
Laisser un commentaire