BioJava:CookbookFrench:DP:PairWise2

Comment faire pour créer un alignement global (algorithme de Needleman-Wunsh) ou local (algorithme de Smith-Waterman)

Les alignements de deux séquences ont traditionnellement été obtenues par des approches de programmation dynamique déterministique. Deux algorithmes de cette nature sont utilisés: l’algorithme de Needleman-Wunsch est utilisé pour des alignements globaux alors que l’algorithme de Smith-Waterman a été développé pour les alignements locaux. L’exemple ci-dessous vous montre comment faire l’un ou l’autre grâce aux implémentations de chacun de ces algorithmes retrouvées dans le package org.biojava.bio.alignment. Ces classes ne sont disponibles qu’á partir de la version 1.5.

L’idée derrière ces approches est de maintenir un représentation matricielle d’un graphe d’édition, avec des fonctions d’insertion, de délétion, de substitution et d’extension de gap; en pratique, l’insertion et la délétion sont des opérations d’ouverture de gaps au sein de la séquence connue de l’un, de la séquence inconnue de l’autre. Par programmation dynamique, les éléments contenus dans la matrice, qui sont des valeurs représentant la valeur de l’opération à effectuer, sont calculés. Le parcours permettant d’obtenir le meilleur score produit le meilleur alignement.

Les implémentations de ces algorithmes doivent être initialisées avec des pénalités pour chaque opération d’édition. Cependant, les matrices de substitution utilisent des scores (points) qui sont tout l’opposé des pénalités. Ceci signifie qu’on peut obtenir les pénalités en multipliant les scores par la valeur -1. L’utilisation de pénalités plutôt que des points permet de calculer une distance d’édition pour les alignements globaux. Une telle distance n’est pas utile dans le cas des alignements locaux car dans les cas extrêmes, l’alignement local entre deux séquences pourrait n’avoir qu’un seul symbole de chaque séquence et par conséquent avoir une valeur de distance de zéro. Voilà pourquoi les alignements locaux utilisent les points plutôt que les pénalités. Néanmoins, le constructeur de SmithWaterman demande des pénalités et pas des points.

Les alignements utilisant des valeurs différentes pour la pénalité d’une ouverture et son élongation consomment une plus grande quantité de mémoire et de temps de traitement par rapport à des valeurs identiques pour les deux. C’est parce qu’il faut maintenir trois matrices pour préserver l’information nécessaire afin de retrouver le meilleur chemin sur le graphe. Il est nécessaire de maintenir deux matrices pour les identités et les substitutions dans la séquence connue et la séquence inconnue respectivement et une troisieme mattrice pour préserver les valeurs optimales de ces deux premières ainsi que des opérations de match/remplacement; toutes ces matrices ont une dimensions de query.length() par target.length().

Il est possible d’utiliser une des nombreuses matrices de substitution existantes ainf de faire la calcul des alignements; elles permettent de calculer la valeur de transition d’un acide aminé à un autre. Elles peuvent être téléchargées à partir du NCBI et sont nécessaires pour cet exemple. Si cela vous est nécessaire, il est possible de créer vos propres matrices grâce à la classe SubstitutionMatrix. Cette dernière vous donne accès à un constructeur permettant de créer votre propre matrice avec des valeurs égales pour chaque identité et chaque substitution.

La superclasse SequenceAlignment de chaque algorithme possède une méthode pour formatter la sortie de l’alignement. Par conséquent, si vous désirez écrire votre propre algorithme d’alignment ou si vous voulez utiliser l’algorithme basé sur les modèles de Markov, vous pouvez dériver votre classe à partir de la super-classe et appliquer la méthode.

Une démo des classes d’alignement global et local

```java import java.io.File;

import org.biojava.bio.alignment.NeedlemanWunsch; import org.biojava.bio.alignment.SequenceAlignment; import org.biojava.bio.alignment.SmithWaterman; import org.biojava.bio.alignment.SubstitutionMatrix; import org.biojava.bio.seq.DNATools; import org.biojava.bio.seq.Sequence; import org.biojava.bio.symbol.AlphabetManager; import org.biojava.bio.symbol.FiniteAlphabet;

/*

* Created on Mar 28, 2006
*/

/** Demo effectuant l’alignement global et local, successivement,

 * de deux sequences avec affichage des resultats a l'ecran. 
 * L'usage d'une matrice de substitution est necessaire, facilement obtenues via
 * ftp://ftp.ncbi.nlm.nih.gov/blast/matrices/
 * Cette demo ne fonctionne qu'avec des sequences d'ADN. Cependant, les algorithmes fonctionnent 
 * avec n'importe quel Alphabet pourvu qu'une matrice valable existe 
 * Dans cet exemple, la matrice NUC.4.4 est adequate.
 *
 * @author Andreas Dräger
 */

public class DeterministicAlignmentDemo {

 /** Cette classe permet l'alignement de deux sequences 
   * pour affichage a l'ecran.
   * @param args: une sequence inconnue et une sequence connue, 
   *   un fichier avec les valeurs de la matrice de subsitution a utiliser.
   * @link ftp://ftp.ncbi.nlm.nih.gov/blast/matrices/
   */
 public static void main (String args[]) {
   if (args.length < 3)
     throw new Error("Usage: DeterministicAlignmentDemo " +
                     "querySeq targetSeq substitutionMatrixFile");
   try {
     /* Specification de l'Alphabet des sequences, DNA dans cet exemple.
     *  Pour des sequences proteiques, simplement utiliser
     *  AlphabetManager.alphabetForName("Protein");
     */      
     FiniteAlphabet alphabet = (FiniteAlphabet) AlphabetManager.alphabetForName("DNA");
     
     // Lecture du fichier de la matrice de substitution. 
     // Pour cet exemple, la matrice NUC.4.4 est correcte.
     SubstitutionMatrix matrix = new SubstitutionMatrix(alphabet, new File(args[2]));
     
     // Definition les valeurs des couts par defaut pour l'alignement global.
     SequenceAlignment aligner = new NeedlemanWunsch( 
       (short)0,   // match
       (short)3,   // remplacement
       (short)2,      // insertion
       (short)2,   // deletion
       (short)1,      // gapExtend
       matrix  // Matrice de substitution
     );

     Sequence query  = DNATools.createDNASequence(args[0], "query");
     Sequence target = DNATools.createDNASequence(args[1], "target");

     // Faire l'alignement et perserver les resultats.
     aligner.pairwiseAlignment(
       query,  // sources
       target  // sequenceDB
     );

     // Imprimer l'alignement obtenu a l'ecran
     System.out.println("Global alignment with Needleman-Wunsch:\n"+
       aligner.getAlignmentString());    
     
     // Effectuer l'alignement local. 
     // Primo, definir la valeur du cout de chaque operation.
     aligner = new SmithWaterman(
       (short)-1,      // match
       (short)3,       // remplacement 
       (short)2,       // insertion
       (short)2,       // deletion
       (short)1,       // gapExtend
       matrix   // Matrice de substitution
     );
     // Faire l'alignement et perserver les resultats.
     aligner.pairwiseAlignment(query, target);

     // Imprimer l'alignement obtenu a l'ecran
     System.out.println("\nLocal alignment with Smith-Waterman:\n"+
       aligner.getAlignmentString());
   } catch (Exception exc) {
     exc.printStackTrace();
   }
 }

} </java>