0.298 38 0.348 0.013 0.1 -0.019 0.641 -0.125 -0.782 0.026 -0.419 0.257 -0.281 0.03 -0.695 0.197 0.721 -1.093 NA 0.35 -0.234 -4.369 0.678 0.525 -0.176 0.981 -0.468 NA 0.084 0.322 0.142 -0.234 0.32 -0.483 NA NA NA NA NA -0.23 0.109 0.376 39 0.773 0.123 0.655 0.42 0.195 0.503 0.781 1.141 -0.097 0.686 1.148 NA -0.569 0.363 0.944 0.031 NA 0.73 -0.463 0.309 0.385 1.525 0.994 0.473 0.252 NA 1.463 0.434 0.685 0.309 -0.151 0.246 NA NA NA NA NA 0.014 0.941 1.265 40 -0.012 -0.843 -1.277 -0.377 -1.084 -0.838 -1.634 -1.041 -1.072 0.004 0.045 -0.758 -1.692 -1.653 -0.928 -1.939 NA -0.419 -0.984 -2.233 -1.285 -1.392 -2.033 -0.306 -1.601 NA -0.143 0 -1.237 0.096 -0.751 -1.585 NA NA NA NA NA -0.327 -1.015 -1.528

Classification hiérarchique (CAH)

Le programme neighbor de PHYLIP peut être utilisé pour construire une hiérarchie.

Cartes de Kohonen (SOM)

L'algorithme d'apprentissage de cartes auto-organisatrices peut être résumé de la manière suivante :

1. Initialisation des vecteurs de poids
2. Présentation d'un vecteur de données (individu) à la couche d'entrée
3. Détermination du neurone "gagnant", c'est-à-dire le plus proche du vecteur de données
4. Modification des neurones voisins du gagnant, par descente de gradient
5. Retour à l'étape 2 jusqu'a ce qu'un critère d'arrêt soit atteint (nombre d'itérations, plus de changement d'affectation, etc)

L'implémentation ne nécessite pas de routines particulières, et peut tout a fait être réalisée en Perl, malgré ses faibles performances en terme de vitesse d'éxécution. Voici une implémentation de l'algorithme de Kohonen en Perl :




#!/usr/bin/perl

use Getopt::Long;

my $x_classes    = 5;
my $y_classes    = 5;
my $nb_iter      = 30;

my $num_indiv    = 0;
my $num_vars     = 0;

my $alpha0       = 0.1;
my $rad0         = 2.5;
my $radf         = 0.0;

# classes 5x5
my @neuron = ();

# données 
my @data    = ();

# distances
my @dist    = ();


# definit le style de sortie
my $output = 'html'; 
GetOptions ('output=s' => \$output,
	    'xdim=s'   => \$x_classes,
	    'ydim=s'   => \$y_classes,
	    'iter=s'   => \$nb_iter
	    );



# lit les données
my @values = ();             
while ($line = <STDIN>) {
    chomp $line;

    @values    = split(/[\t\s]+/, $line);
    my @indiv  = ();
    my $nb     = scalar @values;

    for (my $i=0; $i<$nb; $i++) {
	$indiv[$i] = $values[$i];
    }

    push(@data, \@indiv);
    $num_indiv++;
}


# evalue le nombre de cols
$num_vars = scalar(@{$data[0]});


# initialise les classes de manière aléatoire 
srand();
my @utilises = ();
for (my $i=0; $i<$x_classes; $i++) {
    for (my $j=0; $j<$y_classes; $j++) {
	
	# nombre aléatoire entre 0 et $num_indiv
	my $r = int(rand($num_indiv));
	
	while ($utilises[$r] == 1) {
	    $r = int(rand($num_indiv));
	}
	
	$utilises[$r]     = 1;

	my @neutmp = @{$data[$r]};
	$neuron[$i][$j]   = \@neutmp;
	
    }

    

}


for ($t=0; $t<$nb_iter; $t++) {

    for ($k=0; $k<$num_indiv; $k++) {
	
	$mindist = 100000.0;
	# pour chaque individu, determine le gagnant
	
	
	for ($i=0; $i<$x_classes; $i++) {
	    for ($j=0; $j<$y_classes; $j++) {

		$dist = distance($data[$k], $neuron[$i][$j]);
			    
		# distance neurone (indiv $neuron[$i][$j])  -> individu $k
		if ($dist < $mindist) {
		    $xwin    = $i;
		    $ywin    = $j;
		    $mindist = $dist;
		}
		    		
	    }
	}

	# maj les prototypes = rapproche de l'indiv k

	for (my $i=0; $i<$x_classes; $i++) {
	    for (my $j=0; $j<$y_classes; $j++) {
		
		$alp = alpha ($t, $nb_iter, $alpha0);
		$rad = radius($t, $nb_iter, $rad0, $radf);
		$dwi = distOnMap($i, $j, $xwin, $ywin);
		$hwi = neigh($dwi, $rad);
		

		for (my $l=0; $l<$num_vars; $l++) {

		    $neuron[$i][$j]->[$l] = $neuron[$i][$j]->[$l] + $alp * $hwi * ($data[$k]->[$l] - $neuron[$i][$j]->[$l]);
		 
		}
		
	    }
	}
    }




        
    
}




# initialise le tableau d'affectations
for ($i=0; $i<$x_classes; $i++) {
    for ($j=0; $j<$y_classes; $j++) {
	my @a_tmp = ();
	$affect[$i][$j] = \@a_tmp;
    }
}

# pour chaque individu, determine le gagnant
for ($k=0; $k<$num_indiv; $k++) {
        
    $mindist = 100000.0;
    # pour chaque individu, determine le gagnant
    
    for ($i=0; $i<$x_classes; $i++) {
	for ($j=0; $j<$y_classes; $j++) {
	    	    
	    $dist = distance($data[$k], $neuron[$i][$j]);
	
	    # distance neurone (indiv $neuron[$i][$j])  -> individu $k
	    
	    if ($dist < $mindist) {
		$xwin    = $i;
		$ywin    = $j;
		$mindist = $dist;
	    }
	    
	}
    }
    
    push(@{$affect[$xwin][$ywin]},  $k);
}




if ($output eq "html") {
   # fait peter le HTML !
    print "<table>\n";
    for (my $i=0; $i<$x_classes; $i++) {
	print "<tr>\n";
	for (my $j=0; $j<$y_classes; $j++) {
	    print "<td>\n";
	    $n = scalar @{$affect[$i][$j]};
	    for (my $k=0; $k<$n; $k++) {
		print $affect[$i][$j]->[$k] . "<br>"; 
	    }
	    print "</td>\n";
	    
	    
	}
	print "</tr>\n";
	
    }
    print "</table>\n";


} else {
 
    # affiche les prototypes
    for ($i=0; $i<$x_classes; $i++) {
	for ($j=0; $j<$y_classes; $j++) {
	    print(join " ", @{$neuron[$i][$j]});
	    print "\n";
	}
    }
    
}

# fonction alpha
sub alpha {
    my ($iter, $length, $alp0) = @_;
    
    return ($alp0 * ($length - $iter) / $length);
}


# fonction de rayon "Gaussian"
sub neigh {
    
    my ($d, $s) = @_;

    return (exp(- ($d * $d) / (2.0 * $s * $s)));

}

# fonction de diminution du rayon
sub radius {
    my ($iter, $length, $rad0, $radf) = @_;
    
    return ($radf + ($rad0 - $radf) * ($length - $iter) / $length);
}


# distance entre 2 individus (ou neurones)
sub distance {
    
    my ($ind1, $ind2) = @_;

    my $sum = 0.0;
    for (my $i=0; $i<scalar(@$ind1); $i++) {
	$sum += ($ind2->[$i] - $ind1->[$i]) * ($ind2->[$i] - $ind1->[$i]); 
    }

    return sqrt($sum);
    
}


# calcule une distance entre deux neurones sur la grille
sub distOnMap {
    
    my ($x1, $y1, $x2, $y2) = @_;
    
    return sqrt (($x2 - $x1) * ($x2 - $x1) + ($y2 - $y1) * ($y2 - $y1));
    
}






La ligne de commande permettant de construire une carte de Kohonen 5x5 sous forme de tableau HTML, sur 10 itérations, est la suivante :



perl kohonen.pl --output=html --xdim=5 --ydim=5 --iter=10 < an50.txt


Afin de vérifier la qualité de la carte obtenue, et notamment la présence de défaut toplogiques, on peut projeter la grille sur le plan obtenu par une ACP, et afficher le résultat grâce à GNUPLOT :



perl kohonorm.pl --output=html --xdim=5 --ydim=5 --iter=10 < an50.txt | perl pca.pl 3 | perl outgnu.pl 5 5 > data3d.txt && gnuplot plot.plt > kohonen.png


Voici le contenu du script outgnu.pl :



$x = $ARGV[0];
$y = $ARGV[1];



$cnt = 1;
while ($line = <STDIN>) {
    
    print $line;
    print "\n" if (($cnt % $y) == 0);
    
    $cnt++;
}

Celui de plot.plt :

set terminal png
set view 0, 0
splot "data3d.txt" with lines

Voici le fichier PNG obtenu :

Figure 6.1. Kohonen

Le problème des cartes de Kohonen est qu'elles permettent uniquement de regrouper les profils similaires. Elles ne permettent pas de détecter les profils décalés dans le temps, ou les profils inversés (régulation négative).

K-means / Nuées dynamiques

L'algorithme des nuées dynamiques est une généralisation de l'algorithme des k-means. Le grand interet de cette méthode de classification est sa simplicité, notamment à la mise en oeuvre. En outre, il existe une variante des nuées dynamiques permettant de travailler à partir d'un tableau de distances. Le défaut de cette méthode est qu'il faut obligatoirement fixer le nombre de classes à-priori. Les grandes étapes sont les suivantes :
Voici le code source en Perl de l'algorithme des nuées dynamiques :


#!/usr/bin/perl
use strict;

my @data         = (); # stocke les données (individus)
my @classes      = (); # stocke les classes
my @effectifs    = (); # stocke les effectifs de chaque classe
my @affectations = (); # stocke l'appartenance d'un indiv a une classe

my $num_classes  = 5;
my $num_indiv    = 0;

# charge les données
my $line = <STDIN>;       
my @values = ();             
while ($line = <STDIN>) {
    chomp $line;

    @values    = split(/[\t\s]+/, $line);
    my @indiv  = ();
    my $nb     = scalar @values;

    for (my $i=1; $i<$nb; $i++) {
	$indiv[$i-1] = $values[$i];
    }

    push(@data, \@indiv);

}

srand();

$num_indiv  = scalar @data;
my $num_vars   = scalar @{$data[0]};

# initialise les classes avec des individus

my @utilises = ();
for (my $i=0; $i<$num_classes; $i++) {
    # nombre aléatoire entre 0 et $num_indiv
    my $r = int(rand($num_indiv));

    while ($utilises[$r] == 1) {
	$r = int(rand($num_indiv));
    }
    $utilises[$r] = 1;

    # copie l'individu $r vers la classe $i
    for (my $j=0; $j<$num_vars; $j++) {
	$classes[$i]->[$j] = $data[$r]->[$j];
    }


    #print "Classe $i initialisée avec individu $r\n";
}



# itère tant qu'il y a des changements d'affectations
my $change = 1;
while ($change) {
    $change = 0;
    @effectifs = ();
    # regarde, pour chaque individu, la  classe a laquelle il appartient
    for (my $i=0; $i<$num_indiv; $i++) {
	my $affect  = -1;
	my $mindist = 100000.0;
	for (my $j=0; $j<$num_classes; $j++) {
	    my $dist = euclidDist($classes[$j], $data[$i]);
	    if ($dist < $mindist) {
		$affect  = $j;
		$mindist = $dist;
	    }
	}

	
	$change = 1 if ($affectations[$i] != $affect); 
	#print "Individu $i va dans la classe $affect\n";
	$affectations[$i] = $affect;
	$effectifs[$affect]++;
    }

    #for (my $i=0; $i<$num_classes; $i++) {
    #	print "effectif de la classe $i = " . $effectifs[$i] . "\n";
    #}

    # recalcule les centres des classes
    @classes = ();
    for (my $i=0; $i<$num_indiv; $i++) {
	# ajoute l'individu a sa classe
	
	for (my $j=0; $j<$num_vars; $j++) {
	   $classes[$affectations[$i]]->[$j] += $data[$i]->[$j];
	}
    }

    for (my $i=0; $i<$num_classes; $i++) {
		
	for (my $j=0; $j<$num_vars; $j++) {
	    $classes[$i]->[$j] /= $effectifs[$i];
	}
    }

    # divise les composantes de chaque classe par leur effectif
}

my @resultat = ();
for (my $i=0; $i<$num_indiv; $i++) {
    $resultat[$affectations[$i]] .= "$i ";
}

for (my $i=0; $i<$num_classes; $i++) {
	# affiche les prototypes
	#for (my $j=0; $j<$num_vars; $j++) {
	#print $classes[$i]->[$j] . " ";
	#}
    print "Classe " . ($i+1) . " : " . $resultat[$i] . "\n";
}


# distance euclidienne
sub euclidDist {
    my ($din1, $din2) = @_;

    my ($nb1, $nb2, $sum);
    $nb1 = scalar @{$din1};
    
    

    $nb2 = 0;
    for (my $i=0; $i<$nb1; $i++) {
	$sum += ($din1->[$i] - $din2->[$i]) * ($din1->[$i] - $din2->[$i]);
	$nb2 ++;
    }
    
    $sum = $sum / $nb2;
    return sqrt($sum);
}




Analyse en Composantes Principales (ACP)

L'ACP nécessite notamment l'accès à des routines de calcul de valeurs et vecteurs propres d'une matrice. Pour cela, nous utiliserons le module Perl PDL (http://pdl.perl.org), qui fournit entre autres un ensemble de routines de manipulations de matrices. Le code Perl permettant de réaliser une réduction de dimensionalité de N dimensions vers 2 dimensions est le suivant. Il prend en entrée une matrice de n individus décrits par k variables, et renvoie une matrice de ces mêmes individus décrits par 2 variables, car projetés sur le plan formé par les 2 premiers vecteurs propres.

#!/usr/bin/perl -W
# effectue la projection en 2D d'un nuage de points n Dimensions
# inspiré de http://stein.cshl.org/genome_informatics/expression/express_pl.txt
use PDL;

my @input = <STDIN>;

my @data  = ();

# nombre de lignes
my $nrow = scalar(@input);

# evalue le nombre de cols
@line = split(/\s+/, $input[0]);
my $ncol = scalar(@line);


# crée une nouvelle matrice 
my $data = PDL->zeroes($nrow,$ncol);

# charge la matrice de points
for (my $i = 0; $i < $nrow; $i++) {
    @line = split(/\s+/, $input[$i]);
    
    for (my $j = 0; $j < $ncol; $j++) {
	set($data, $i, $j, $line[$j]);
    }
}

# calcule la matrice de covariance (devrait utiliser PDL plutôt)
my $covar = PDL->zeroes($ncol,$ncol);


# calcule la moyenne pour chaque colonne
for ($j = 0; $j < $ncol; $j++) {
    $mean[$j] = 0.0;
    
    for ($i = 0; $i < $nrow; $i++) {
	$mean[$j] += at($data, $i, $j);
    }
    $mean[$j] /= $nrow;
}


# centre les données
for ($i = 0; $i < $nrow; $i++) {
    for ($j = 0; $j < $ncol; $j++) {
	set($data, $i, $j,  at($data, $i, $j) - $mean[$j]);
    }
}

# calcule la matrice de cov
for ($j1 = 0; $j1 < $ncol; $j1++) {
    for ($j2 = $j1; $j2 < $ncol; $j2++) {
	set($covar, $j1, $j2, 0.0);
	for ($i = 0; $i < $nrow; $i++) {
	    set($covar, $j1, $j2, at($covar, $j1, $j2) + at($data, $i, $j1) *  at($data, $i, $j2));
	}
	
	set($covar, $j1, $j2, at($covar, $j1, $j2) / $nrow);
	set($covar, $j2, $j1, at($covar, $j1, $j2));
	
    }
}


  
# dé-centre les données
for ($i = 0; $i < $nrow; $i++) {
    for ($j = 0; $j < $ncol; $j++) {
	set($data, $i, $j,  at($data, $i, $j) + $mean[$j]);
    }
}


# calcule eigenvalues et eigenvecteurs
my ($e, $lambda) = PDL::Math::eigens($covar);
my $ix = qsorti($lambda);

# quelques affichages 
print "Eigenvalues :\n";
for (my $i = $ncol-1; $i >= 0; $i--) {
    print at($lambda,at($ix,$i)) . " ";
}
print "\n";

print "Eigenvectors (3 premiers) :\n";
print $e->slice(":,(" . at($ix, $ncol - 0 - 1) . ")"); print "\n";
print $e->slice(":,(" . at($ix, $ncol - 1 - 1) . ")"); print "\n";
print $e->slice(":,(" . at($ix, $ncol - 2 - 1) . ")"); print "\n";


# cree une matrice de points projetés en 2D
$proj = PDL->zeroes($nrow, 2);


for (my $i = 0; $i < $nrow; $i++) {
    for (my $k = 0; $k < 2; $k++) {
	for (my $k2 = 0; $k2 < $ncol; $k2++) {
	    set($proj, $i, $k,  at($proj, $i, $k) +at($data, $i, $k2) * at($e, $k2, at($ix, $ncol - $k - 1)));
	}
    }
}



# affiche les points projetés
for (my $i = 0; $i < $nrow; $i++) {
    for (my $k = 0; $k < 2; $k++) {
	print at($proj, $i, $k) . " ";
    }
    print "\n";

}



Suite à ce programme, il est possible, toujours avec gnuplot d'afficher les points projetés sur le plan formé par les 2 premiers axes ACP :

pca.pl 2 < an50.txt > data2d.txt && gnuplot plot2D.plt > 2D.png

Voici le contenu du script GNUPLOT plot2D.plt :
set terminal png
plot "data2d.txt"
Voici le fichier PNG obtenu :

Figure 6.2. Projection

Programmes d'analyse des données d'expression

Parmi les programmes permettant d'analyser l'expression de gènes provenant de microarrays se trouve J-Express (http://www.ii.uib.no/~bjarted/jexpress/). Celui-ci offre les techniques suivantes : CAH, SOMs, PCA, K-means, Profile search, ainsi que différents outils de visualisation (par exemple 3D grace a VRML).

On notera que chacun possède son propre format de sauvegarde des données d'expression. Il existe cependant des tentatives de standardisation, ainsi que des propositions/implémentations de bases de données de données d'expressions de gènes. Ressources:

mini tutorial sur GeneCluster
Interpreting patterns of gene expression with self-organizing maps: methods and application to hematopoietic differentiation par Tamayo et al
Gene network inference
Gene Expression Informatics par Joel S. Bader, Ph.D.
Algorithms for gene expression and proreomics

Chapter 7. Programmer en Perl

Table of Contents

Introduction à Perl et premiers pas
concepts fondamentaux de la syntaxe Perl
Applications en bioinformatique
BioPerl
programmer en C
Quels sont les points clé du langage C?
Quel environnement de programmation?
Utiliser les Makefiles
Chasser les erreurs de programmation (débugger)
Résolution de problèmes bioinformatique en C
programmer en Java
Installer un kit de développement Java
Compiler et éxécuter un programme Java
Construire un programme en langage Java
Exemple de code Java pour la bioinformatique
programmer avec XML
Utiliser un parseur XML en Perl
programmation Corba
programmation parallèle
PVM : Parallel Virtual Machine
MPI : Message Passing Interface
Distribuer ses programmes

Introduction à Perl et premiers pas

Perl possède plusieurs avantages : tout d'abord, il est installé sur la quasi-totalité des environnements Unix. Ensuite, les scripts ne nécessitent pas de compilation, et sont donc parfaitement portables d'un système à l'autre (Windows vers Linux par exemple). Perl implémente également de nombreux types de données très utiles comme les tables de hachage (tableaux associatifs), qui évitent au programmeurs de réinventer la roue. Il supporte les expressions régulières, ce qui lui permet d'effectuer des traitements compliqués sur les chaines de caractères (recherche et remplacement de texte par exemple). Perl possède maintenant un nombre incalculable de modules, tous disponibles dans le doamine public, et couvre ainsi tous les domaines de l'informatique. Il est facile de débuter la programmation avec Perl.

Ouvrir avec Emacs un fichier nommé hello.pl, puis taper la ligne suivante, sauver le fichier puis sortir d'Emacs.

[olly@mplpc16 bioinfo]$ emacs hello.pl& 
print "Hello!\n";

[olly@mplpc16 bioinfo]$ perl hello.pl

Maintenant, ouvrez le fichier avec emacs et ajoutez-y la ligne suivante :

#!/usr/bin/perl
$str = "Hello";
print "$str tout le monde!\n";

Ensuite, rendez le fichier éxécutable

[olly@mplpc16 bioinfo]$ chmod +x hello.pl

Vérifions que le fchier est bien executable (il contient trois "x")

[olly@mplpc16 dtgen]$ ll hello.pl 
-rwxr-xr-x   1 olly     olly           18 Jun  5 23:19 hello.pl*

Et maitenant, on éxécute ce script!

[olly@mplpc16 dtgen]$ hello.pl

concepts fondamentaux de la syntaxe Perl

La syntaxe du Perl est relativement proche de celle du C (pour ceux qui connaissent ce langage). Ainsi, Perl est sensible à la casse (print est différent de PRINT par exemple). En Perl, chaque ligne est terminée par un point-virgule. Tous ce qui suit le caractère # est considére comme des commentaires.

Il existe trois types de variables en Perl : les scalaires, les listes et les hachages. Une variable de type scalaire débute par le signe $ (par exemple $count), une variable de type liste débute par le signe @ (par exemple @tableau), tandis qu'une variable de type hachage débute par le signe % (par exemple %hash).

Une variable de type scalaire peut contenir un nombre (entier ou réel) ou bien une chaîne de caractères. Par exemple :
$num = 12;
$taille = 3.3;
$str = "salut";
Perl réalise l'interpolation de variable scalaire dans les chaînes de caractère. Par exemple le script suivant affiche le message "je mesure 1.87 m" :
$taille = 1.87;
print "je mesure $taille m";
Il n'y a pas de typage en Perl, cela signifie qu'une variable prend le type de ce qui lui est affectée. Par exemple il est possible de faire les opérations suivantes :
$var = 3
$var = "salut";
print $var;
ce qui affichera "salut" et non pas 3. Comme dans de construction de réferences Après avoir passé en revue les constructions de bases, : Perl possède également comme particularité de définir une série variables spéciales : $_ que veut dire "my" syntaxe générale Une liste (ou un tableau) est une variable contenant elle-même une série d'objets (variables, listes, etc.). Chaque objet (ou élément) d'un tableau est repéré par sa position au sein du tableau. Par exemple, le premier élément d'un tableau est à la position 0. Le cinquième élément est à la position 4.
@tableau = (12, "abc", 56, "rtt");
 
print $tableau[0];       # affiche 12
print $tableau[3];	 # affiche rtt
Il est possible avec la fonction map d'effectuer une ou plusieurs opérations sur chacun des éléments d' un tableau @tab2 = map {$_ * 2} @tab; ou @tab2 = map(function, @tab); On peut également parcourir les éléments d'un tableau grace à l'instruction foreach :
foreach $item (@tableau) {
  print $item;
}
Les tableaux associatifs De même qu'un tableau, un tableau associatif associe une clé à un élément. En revanche la clé n'est pas restreinte à un chifrre, il peut d'agir d'une chaine de caractères. Pour parcourir un tableau associatif nommé %asso, on procèdera de la manière suivante :
foreach $item (%asso) {
  # instructions ...
  print $item;
}
Il existe une notion de contexte en Perl, c'est à dire qu'il n'est pas toujours utile de spécifier explicitement les paramètres d'une fonction d'abord les regexp, puis les fichiers Par exemple, la ligne suivante affichera la séquence contenue dans $seq si celle-ci contient le motif TTATA :
print $seq if ($seq =~ /TTATA/)
L'interactivité avec l'utilisateur est nécéssaire pour bien des programmes conviviaux. Néanmoins elle Il y a deux moyens d'interagir avec des données externes. La première consiste à ouvrir et créer des fichiers externes, la seconde à utiliser les entrées et sorties standard. Perl gère de manière simple les entrées sorties standards... très utile pour réaliser des traitements rapides sur des fichiers texte. Par exemple, supposons que l'on souhaite extraire les accession numbers du fichier suivant, nommé nucleo.seq :
>X14543
AATTTATGCGCTATATATATTTTG
>X14544
AATTTATGCGCTATGTATATTTTG
>X14545
AATTTATGCGCGATATATATTTTG
Le script numacc.pl permettant de réaliser cette tache est le suivant :

while (<STDIN>) {
  # affiche l'accession number si la ligne commence par >
  print $1 if (/^>(.*)$/);
}

L'usage de ce programme est le suivant :
cat nucleo.seq | numacc.pl
écrire une nouvelle routine :

sub maRoutine {
  my ($arg1, $arg2) = @_;

  print "argument passés : $arg1 et $arg2";

  return $arg1+ $arg2;
}
parser les options de la ligne de commande avec le module Getopt::Long. Supposons que l'on souhaite demander à l'utilisateur le type de sortie qu'il souhaite, et ce au travers de la ligne de commande :
script.pl --output=html

use Getopt::Long;


# definit le style de sortie, html par défaut
my $output = ''; 
GetOptions ('output=s' => \$output);
$output = "html" if ($output eq ''); 

if ($output eq "html") {
   print "<b>Hello !</b>";
} else {
   print "Hello !"; 
}
Par exemple, essayons d'extraire des séquences les portions comprises entre les motifs TTA et TTC Pour extraire les 10 premiers acides aminées de chaque séquence, on utilisera la fonction substr. Par exemple : substr($seq, 0, 10) Les expressions régulières Redirection des E/S Définition et utilisation des descripteurs de fichiers APPLICATION DE MOTIFS ET OPÉRATEURS Expressions régulières Perl Extraction d'informations textuelles importantes Utilisation d'expressions régulières UNIX Modification des données avec des substitutions Décodage des extensions "egimosx" $ fin de ligne ? 0 ou 1 fois ^ début de ligne Installer un module Perl Parser la sortie de Blast gràce à Perl Si le module CPAN.pm est installé sur votre machine, il est possible d'installer de nouveaux modules de manière quasi-automatique. Par exemple, pour installer le module SOAP::Lite, il suffit de taper la commande suivante (en tant que super-utilisateur):
perl -MCPAN -e 'install SOAP::Lite'
Notons que l'interface CPAN permet de chercher des modules Perl parmi ceux installables. Ainsi, pour chercher tous les modules contenant la chaîne
perl -MCPAN -e 'shell'
i /Bio/
Autrement, il est nécessaire de télécharger l'archive en .tar.gz, de la decompresser, et de taper les commandes suivantes dans le répertoire créé :
perl Makefile.PL
make
make test
su
make install
Ressources: tutorial Perl en français chez ftls.org http://www.ftls.org/fr/initiation/perl/ Un excellent Learning Perl O'Reilly Perl permet de créer et d'accéder à la librairie GNU Database Manager. Il s'agit d'une librairie installée sur tous les systèmes Linux, dont les routines permettent de gérer des fichiers contenant des paires clé/données. On l'utilise couramment pour stocker des données et pour pouvoir les récupérer rapidement. Utile par exemple pour construire un petit moteur de recherche. GNU dbm is a library of routines that manages data files that contain key/data pairs. The access provided is that of storing, retrieval, and deletion by key and a non-sorted traver­ sal of all keys. A process is allowed to use multiple data files at the same time. Ecrire une base de données:
use GDBM_File;
tie(my(%indexdb),'GDBM_File',"index.db", &GDBM_WRCREAT, 0644);
$indexdb{"bioinformatique"} = "file.html";
untie(%indexdb);
Lire une base de données:
use GDBM_File;
tie(my(%indexdb),'GDBM_File',"index.db", &GDBM_WRCREAT, 0644);
$indexdb{"bioinformatique"} = "file.html";
untie(%indexdb);
La fonction sort permet de trier un tableau, c'est à dire de ranger les éléments de ce tableau dans un ordre spécifié. Par exemple, supposons que l'on souhaite trier le fichier suivant, nommé specif.txt par ordre lexicographique :
Phenyl[1-(1-N-succinylamino)pentyl] phosphonate
Neuraminidase [influenza virus]; residues: 82-468
Lysozyme [hen egg white](HEL) EC:3.2.1.17 D18A
Cyclopentadienyl ferrocene (exo Diels-Alder reaction inhibitor)
Human rhinovirus (serotype 2) VP2 (viral capsid protein) peptide; residues: 156-170
Transition State Analogue (Bicyclo[2.2.2]octene derivative)
4-hydroxy-3-nitrophenyl acetate
4-hydroxy-5-iodo-3-nitrophenyl acetate
Aspartame
HIV-1 gp120; residues: 308-332
Autoantigen IgG4 Fc Rea
HIV-1 p24 (capsid protein); residues: 1-151
Thromboplastin (synonym: tissue factor, TF, coagulation factor III) extracellular domain
HIV-1 V3 loop constrained peptide analogue (Aib142)
5-(para-nitrophenyl phosphonate)-pentanoic acid
Cytochrome c oxidase [Paracoccus denitrificans] EC:1.9.3.1
2,2,6,6-tetramethyl-1-piperidinyloxy-dinitrophenyl
HIV-1 p24 epitope-homologous peptide
Lysozyme [bobwhite quail egg white] EC:3.2.1.17
Lysozyme [hen egg white]
Rnase A
Lysozyme [hen egg white] (HEL) EC:3.2.1.17
Traseolide [musk odorant fragrance] (hydrophobic hapten)
HIV-1 reverse transcriptase (HIV-1 RT) EC:2.7.7.49 M184I/double-stranded DNA (ds) complex
Le tri de ce fichier se fait en utilisant le programme Perl suivant :

#!/usr/bin/perl -w

@fichier = <STDIN>;
@result = sort @fichier;
print STDOUT @result;

Ligne de commande :

sort.pl < specif.txt > specif_triees.txt

Par défaut, le tri est effectué par ordre lexicographique, mais sort peut faire appel à une fonction de comparaison externe. Par exemple, pour trier les lignes de ce fichier par ordre de repX croissant :

  6  50
rep1      CTGACATTGGAAAGTACTTTATACGACAAGACAAACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
rep5      CTGACACCGGAAAGTACTTTATACGTCAAGACAAACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
rep2      CTGACATTGGAAAGTACTTTATACGTCGAGACGGACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
rep6      CTGACACCGGGGAGTACTTTATACGACAAGACAAACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
rep4      CTGACATTGGAAAGTACTTTATACGACAAGACAAACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
rep3      CTGACATTGGAAAGTACTTTATACGACAAGACAAACTGAAGGTGCAAGTCCTTTTTGTCATACTATTCAT
On utilisera le programme suivant :
#!/usr/bin/perl

#recupère la première ligne
$ln = <STDIN>;

#recupère les autres lignes
@lines = <STDIN>;


#sortie
print $ln;
@sorted_lines = sort sortlines @lines;
foreach $line (@sorted_lines) {
    print "$line"; 
}

sub sortlines {
    $a =~ /^rep(\d+)/;
    $a1 = $1;
    $b =~ /^rep(\d+)/;
    $b1 = $1;
    return $a1 <=> $b1;
}

Applications en bioinformatique

Mettre de l'information au format souhaité

exemple : format bizarre -> format fasta

Récupérer l'information à partir de fichiers de sorties de programmes externes

Construction automatique de pages web

Le programme le plus simple possible est le suivant :
print "Bonjour je m'appelle Olivier\n";
Tout comme il est possible d'écrire du texte à l'écran, il est également possible d'écrire du HTML :

print "<html><body>\n";
print "font color=\"red\">Bonjour je m'appelle Olivier</font>\n";
print "</body></html>\n";

Redirigeons la sortie de ce script vers un fichier nommé page.html (avec la commande print.pl > page.html), puis visualisons ce dernier avec netscape. Notons que Perl permet de séparer certaines données du code HTML proprement dit, grace a l'usage de variables. Par exemple :

$couleur = "red";
$texte   = "Bonjour je m'appelle Olivier";

print "<html><body>\n";
print "font color=\"$couleur\">$texte</font>\n";
print "</body></html>\n";

BioPerl

BioPerl correspond à une série de modules destinés à automatiser certaines taches communes en bioinformatique. Par exemple, il permet de lire des fichiers FASTA, de lancer des BLAST et de récupérer des séquences à partir des bases de données online.

Installation

L'installation de BioPerl peut se faire de la manière suivante, via le module CPAN.pm :

[root@MPLPC18 olly]# perl -MCPAN -e shell

cpan shell -- CPAN exploration and modules installation (v1.52)
ReadLine support enabled

cpan> install "B/BI/BIRNEY/bioperl-0.7.1.tar.gz"

Un tutorial complet sur BioPerl est disponible à l'adresse http://bio.perl.org/Core/POD/bptutorial.html

Récupérer des séquences à partir de fichiers FASTA, EMBL, etc.

Exemple : lire et afficher les séquences d'n fichier FASTA :
use Bio::SeqIO;

$seqio  = Bio::SeqIO->new ( '-format' => 'Fasta' , -file => $ARGV[0]);
while $seq = $seqio->next_seq;


Autre exemple : lire et afficher les séquences d'n fichierau format EMBL :
use Bio::SeqIO;

$seqio  = Bio::SeqIO->new ( '-format' => 'embl' , -file => '../new_seq.dat');

while ($seqobj = $seqio->next_seq()) {
        print ">" . $seqobj->accession_number . "\n";
        print $seqobj->seq . "\n";
}
Meme chose, mais avec stockage des sequences dans une base GDBM :


use Bio::SeqIO;


use GDBM_File;

tie(my(%indexdb),'GDBM_File',"sequences.db", &GDBM_WRCREAT, 0644);

$seqio  = Bio::SeqIO->new ( '-format' => 'embl' , -file => '../new_seq.dat');
           
$cnt = 0;
while (($seqobj = $seqio->next_seq()) && ($cnt++ < 100)) {
        print ">" . $seqobj->accession_number . "\n";
        print $seqobj->seq . "\n";
        $indexdb{$seqobj->accession_number} = $seqobj->seq;
}

untie(%indexdb);


Lecture des infos stockées :


use GDBM_File;

tie(my(%indexdb),'GDBM_File',"sequences.db", &GDBM_WRCREAT, 0644);

           
while (($k, $v) = each %indexdb) {
        print ">" . $k . "\n";
        print $v . "\n";
}

untie(%indexdb);


Récuperer des séquences dans GenBank

use Bio::DB::GenBank;

$gb = new Bio::DB::GenBank;
$seq = $gb->get_Seq_by_acc($ARGV[0]);

print $seq->seq;

Utiliser le module d'alignement multiple (SW)

#!/usr/bin/perl



use Bio::Tools::pSW;
use Bio::Seq;


$factory = new Bio::Tools::pSW( '-matrix' => 'blosum62.bla',
                                   '-gap' => 12,
                                   '-ext' => 2, );
                                                                                                    

$seq1    = Bio::Seq->new( -seq => 'WLGQRNLVSSTGGNLLNVWLKDW');
$seq2    = Bio::Seq->new( -seq => 'WMGNRNVVNLLNVWFRDW');

$factory->align_and_show($seq1, $seq2, STDOUT);
                                                                                                         
    
$aln = $factory->pairwise_alignment($seq1, $seq2);



Ce qui devrait donner la sortie suivante :

seq1        1     WLGQRNLVSSTGGNLLNVWLKDW                           
                  W+G RN+V     NLLNVW +DW                           
seq2        1     WMGNRNVV-----NLLNVWFRDW 

Batir une interface graphique avec TK
#!/usr/bin/perl -w
use Tk;
use strict;
new MainWindow -> Button(-text => 'Press me!', -command => sub{print "Merci\n"})
 -> pack;
MainLoop;
comp.lang.perl.tk FAQ
Ressources:
Débuter en Perl par François Dagorn et Olivier Salaun
Practical Perl Programming par A. D. Marshall, 1999

programmer en C

Quels sont les points clé du langage C?

Le premier point-clé est la portabilité du code sous différents systèmes : en effet le langage C correspond à un standard, standard respecté par la majeure partie des compilateurs. Le code objet performant puisque qu'il s'agit de langage machine, directement interprétable par le noyau système. Il s'agit d'un langage de programmation structurée, c'est à dire que. En fin la compilation des modules peut être faite de manière séparée, ce qui réduit considérablement les temps de recompilation par rapport à une compilation globale.Les compilateurs C fournissent des bibliothèques de fonction standard, c'est à dire communes du point de vue interface d'un compilateur à l'autre. Enfin le C permet l'accès aisé aux fonctions matériel et système, ce qui présente néanmoins peu d'importance pour le bioinformaticien.

Quel environnement de programmation?

Les compilateurs

Un exemple de programme (bonjour.c)
#include <stdio.h>

void main(void) {
   int age = 25;
   printf("Bonjour tout le monde, j'ai %d ans!", age);
}
Pour compiler ce programme, on utilise la commande suivante :
cc bonjour.c -o bonjour
Cela aura pour effet de créer l'éxécutable bonjour.

Les éditeurs et outils logiciels

parler de KDevelop : permet de naviguer facilement entre les fichiers, les fonctions, les classes et les méthodes, permet de lancer la compilation de manière simple, génère un ensemble de fichiers "squelettes". emacs (ou xemacs) permet de lancer les compilations grâce à des raccourcis clavier. emacs interface également RCS, qui permet de gérer plusieurs versions successives d'un même fichier (revenir à des versions antérieures par exemple)

strtok ou comment récupérer un fichier de données séparées par des espace ou des points-virgules...

Utiliser les Makefiles

http://home.tvd.be/cr25754/make.htm construire une Makefile simple les macros Makefile (macro?) $@ est remplacé par la cible courante (a gauche du :) $< est remplacé par le fichier source de la dépendance courante

Chasser les erreurs de programmation (débugger)

Il existe de très nombreuses erreurs de programmations chaque fonction doit être testée. Le plus difficile est généralement de cerner l'endroit ou se produit l'erreur. Un débugage simple consiste à placer des instructions Exemple de programme produisant une erreur: free() On pourra également utiliser une fonction C qui permet de tester une condition et d'arrêter le programme si la condition n'est pas remplie : la fonction assert() Exemple:

#include <assert.h>

void assert (int expression);

gdb, kdbg,

Résolution de problèmes bioinformatique en C

Génération de nombres aléatoires en C

#include <stdio.h>
#include <time.h>

int main(void) {
        srand(time(NULL));
        printf("%d\n", rand()); 
        return 0;
}

Pour générer des nombres aléatoires provenant de distribution plus complexes (Gamma, exponentielle, etc.), on utilisera la ranlib, ou encore la GSL (GNU Scientific Library). ex : identifier les TATA box?

programmer en Java

Les bases de la programmation et de l'algorithmique par Robert Cori et Jean-Jacques Lévy et François Morain, école Polytechnique

Installer un kit de développement Java

Il faut ensuite mettre a jour son CLASSPATH sous bash,
export CLASSPATH=$CLASSPATH:.
on peut ajouter cette ligne dans le fichier .bashrc (sous $HOME), puis faire source $HOME/.bashrc pour mettre à jour les variables d'environnement.

Compiler et éxécuter un programme Java

Un programme peut faire partie d'un ce qu'on appelle un package. Dans ce cas-là, il faut placer le fichier en .class dans un répertoire portant le nom du package. Par exemple, supposons que l'on ait le code source suivant. Ce programme doit être placé dans le répertoire nommé Bioinfo.
package Bioinfo;

class HelloWorld {
  public static void Main(String []) {
    System.out.println("Bioinfo!");
  }

} 
Ce fichier peut etre compilé a partir du repertoire ou il se trouve :
javac HelloWorld.java
Pour l'éxécuter, il faut se placer dans le répertoire contenant le répertoire Bioinfo, puis taper la commande :
java Bioinfo.HelloWorld

Construire un programme en langage Java

HashTable StreamFormater? (possède un algorithme de tri en 0(n2)) StringTokenize Vector Comment trier un Vector? les objets stockés doivent avoir des méthodes supérieur et inférieur

Exemple de code Java pour la bioinformatique

http://www.biojava.org il s'agit d'un projet "open source" destiné à fournir des outils Java pour la manipulation de séquences et des divers formats rencontrés en bioinformatique, la programmation dynamique, et des routines statistiques simples Récuperer une séquence dans GenBank à partir de son "accession number"
import java.net.*;
import java.io.*;

public class GenBank {
    public GenBank() {

    }

   
    public String get_Seq_by_acc(String uid) {
	StringBuffer seq = new StringBuffer();
	try {
	    URL ncbi = new URL("http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query?db=n&form=6&dopt=f&html=no&title=no&uid=" + uid);
	    BufferedReader in = new BufferedReader(new InputStreamReader(ncbi.openStream()));
	    
	    String inputLine;
	    while ((inputLine = in.readLine()) != null)
		seq.append(inputLine);
	    in.close();

	  
	} catch (Exception e) { System.out.println(e); }
	return seq.toString();
    }
    
    
    static void main(String [] argv) {
	GenBank gb = new GenBank();
	String seq = gb.get_Seq_by_acc("X92210");
	System.out.println(seq);
    }
    
}

programmer avec XML

Etant donné que de plus en plus de données sont disponibles au format XML, il devient nécessaire de savoir développer des programmes et interfaces utilisant ou générant du XML. La génération de XML ne nécéssite pas d'outil particulier, il s'agit d'une tache similaire à la génération de pages HTML. En revanche l'utilsation de données XML dans un programmme peut se voir facilité par certains outils. L'outil de base est le parseur XML.

Utiliser un parseur XML en Perl

xmldb.pl

programmation Corba

Néanmoins CORBA est en grosse perte de vitesse et de nouveau standard basé sur XML permettent de faire dialoguer deux Ressources:

CORBA Tutorial

programmation parallèle

Discussions sur la mise en place d'un cluster Beowulf de machines faisant tourner Blast

utile lors de calcul de bootstrap

PVM : Parallel Virtual Machine

Installer PVM

Créer et compiler un programme simple

Il s'agit d'un système organisé en maitre-esclave, cad qu'une machine dite "maitre" demande a une série d'autres machine d'effectuer leur part de calcul. Elle envoie les données et recupère le résultat.

MPI : Message Passing Interface

Distribuer ses programmes

scritps, licencses...

Chapter 8. La programmation d'applications web

Table of Contents

HTML
structure générale d'un fichier HTML
mise en page de divers éléments (images, textes)
Les tableaux
Création de formulaires HTML
Javascript pour la validation de formulaires HTML
Utiliser Perl pour le développement d'application web dynamiques
traitement de formulaires avec le module CGI
templates avec HTML::Template
sessions avec Apache::Session
interaction avec une base de données MySQL
Utiliser MySQL pour stocker les données

HTML

structure générale d'un fichier HTML

mise en page de divers éléments (images, textes)

Les tableaux

Notons qu'il est possible et souvent nécessaire d'imbriquer des tableaux afin d'obtenir des mises en pages. Pour des mises en pages plus raffinées, on utilisera directement des images, souvent incluses dans des tableaux afin de les positionner avec précision.

Création de formulaires HTML

Javascript pour la validation de formulaires HTML

Utiliser Perl pour le développement d'application web dynamiques

traitement de formulaires avec le module CGI

Bien pratique, $cgi->url() permet de récupérer l'URL du script.

templates avec HTML::Template

Les templates permettent de séparer complètement présentation et programmation. On pourra par exemple éditer des templates HTML avec des outils du style Dreamweaver, Webexpert ... sans avoir a modifier le fichier contenant la logique (le script Perl).
use Date::Manip;
use HTML::Template;

$template = HTML::Template->new(filename => 'template_selected.html');
$template->param(DATE    => UnixDate("today"));
$template->param(NOM     => "Elemento");
$template->param(PRENOM  => "Olivier");

print $template->output;
Et voici un template correspondant :



<TMPL_INCLUDE NAME="header.inc">
<table>
<tr>
<td>Annotateur : <TMPL_VAR     NAME="PRENOM"> <TMPL_VAR     NAME="NOM"></td><td align="right"><TMPL_VAR     NAME="DATE"></td></td>
</tr>

<tr>
<td colspan="2">
<form>
<textarea name="seq"></textarea>
<imput type="submit">
</form>
</td>
</tr> 
</table>

<TMPL_INCLUDE NAME="footer.inc">



Comme l'indique cet example, il est possible d'inclure des fichiers externes au sein de templates.

  # a couple of arrays of data to put in a loop:
          my @words = qw(I Am Cool);
          my @numbers = qw(1 2 3);

          my @loop_data = ();  # initialize an array to hold your loop

          while (@words and @numbers) {
            my %row_data;  # get a fresh hash for the row data

            # fill in this row
            $row_data{WORD} = shift @words;
            $row_data{NUMBER} = shift @numbers;

            # the crucial step - push a reference to this row into the loop!
            push(@loop_data, \%row_data);
          }

          # finally, assign the loop data to the loop param, again with a
          # reference:
          $template->param(THIS_LOOP => \@loop_data);

       The above example would work with a template like:

          <TMPL_LOOP NAME="THIS_LOOP">
             Word: <TMPL_VAR NAME="WORD">     <br>
             Number: <TMPL_VAR NAME="NUMBER"> <p>
          </TMPL_LOOP>


Par défaut, le module HTML::Template ne vous autorise pas à appeller la méthode $template->param(param_name => 'value') si 'param_name' n'existe pas dans le template correspondant. Pour pallier à cela, il faut mettre le paramètre die_on_bad_params à 0 lors de l'appel au module.
use HTML::Template;

$template = HTML::Template->new(filename          => 'template_selected.html'
                                die_on_bad_params => '0'
                               );

De même, les variables simples ne sont généralement pas valables à l'intérieur d'un loop. Pour que cela soit le cas et avoir des variables globales, il faut mettre le paramêtre global_vars à 1 :
use HTML::Template;

$template = HTML::Template->new(filename          => 'template_selected.html'
                                global_vars => '1'
                               );

sessions avec Apache::Session

Une session permet de stocker des paramètres, des variables liées à un de vos visiteurs, et ce tout au long de sa visite sur vos pages.
use Apache::Session::File;

my %session;
my $id = undef;


# numero de la session
$id = $query->cookie(-name=>"IMGT_SESSION");


# cree une session (cree un id dans $session{_session_id} si $id == undef )
tie %session, 'Apache::Session::File', $id, { 
    Directory => "/tmp/",
    LockDirectory => "/tmp/"
    };

    
# cree un cookie si il n'existe pas deja    
if ($id == undef) {
    $cookie = $query->cookie( -name=>'IMGT_SESSION',
			      -value=>$session{_session_id},
			      -expires=>'+1h');
}

# id de la session quoiqu'il en soit
$id = $session{_session_id};


interaction avec une base de données MySQL

Utiliser MySQL pour stocker les données

CGI applications can be written in any language that can be executed on a Web platform such as: C/C++, Perl, Tcl, Python, Shell Scripts(UNIX), Visual Basic and Applescript. Your choice depends on what you have to do because different languages may be specialized for different purposes. Perl, for instance, is great for string and file manipulation, while C is better for bigger, more complex programs. Perl and C are probably the most used languages for CGI programming. We all know how CGI interacts with Perl. In Perl, we used $queryString = $ENV{'QUERY_STRING'} to access the environmental variable. In C, you could call the library function "getenv()", which is defined in standard library . Here is a simple example of how to call this function: débugger un script CGI en Perl. On peut l'éxécuter en local. Pour fournir des paramêtres au CGI, on peut taper ces paramêtre sous la forme param=3 Pour terminer, on tape Ctrl D. Il est également possible d'examiner les logs du serveur web.

Chapter 9. Méthodes et algorithmes en bioinformatique

Table of Contents

Structures de données
Listes chainées
Tableaux
Arbres
Files
Graphes
Les algorithmes de tri
Algorithmes de recherche et optimisation
recuit simulé
algorithmes génétiques
monte-carlo
descente de gradient
tabu search
Modèles de Markov
Analyse de données et data mining
Analyse en Composantes Principales
Que sont les "règles d'association" (et comment les induire)?
Techniques de classification supervisée
Techniques de classification non supervisée

Structures de données

Listes chainées

Tableaux

Arbres

Files

Graphes

Détermination des composantes connexes d'un graphe

Les composantes connexes d'un graphe sont les ensembles de sommets accessibles les uns depuis les autres. On peut utiliser les algorithmes de parcours de graphes pour déterminer les composantes connexes d'un graphe. Pour cela, on utilise l'algorithme de parcours en profondeur d'abord et on colorie les sommets rencontrés avec une couleur correspondant à la composante connexe courante.

Composantes-Connexes
1. Partir d'un sommet s
2. S'il est colorié
      ne rien faire
   sinon
      choisir une couleur
      appliquer profondeur d'abord en marquant avec la couleur

Les algorithmes de tri

Le premier est très simple à implémenter mais généralement lent (sauf quand les données sont presque ordonnées), le second est plus rapide mais plus complexe. complexité des algorithmes de tri? - bubble sort
//tri simple de type bubble sort
void bubbleSort(short *a, int n) {
  int tmp, i, j;
  
  for (i=0; i<n-1; i++) {
    for (j=0; j<n-1-i; j++)
      if (a[j+1] < a[j]) {  /* compare the two neighbors */
	tmp = a[j];         /* swap a[j] and a[j+1]      */
	a[j] = a[j+1];
	a[j+1] = tmp;
      }
  }
- quicksort repérer les séquences croissantes...

Algorithmes de recherche et optimisation

http://www.cs.cf.ac.uk/User/S.U.Thiel/ra/section3_7.html#SECTION0007000000000000000 Quelle méthode d'optimisation pour quel problème?

recuit simulé

donner un exemple avec la GSL http://wwwinfo.cern.ch/pdp/ose/asis/products/GNU.MATH/gsl-0.3b/gsl-ref_7.html

algorithmes génétiques

monte-carlo

descente de gradient

tabu search

http://www.winforms.phil.tu-bs.de/winforms/research/tabu/tabu.html http://www.cs.sandia.gov/opt/survey/ts.html

Modèles de Markov

Les modèles de Markov cachés sont aujourd'hui largement utilisés pour la recherche de gènes et de divers signaux dans les séquences génétiques. Ils sont également le modèle de référence dans des domaines bien différents, comme la parole, et ils sont de plus en plus fréquemment utilisés pour le traitement de données textuelles. Dans toutes ces applications, le modèle appris possède une architecture (ensemble des transitions autorisées entre états) fixe. L'apprentissage se résume alors à l'optimisation d'un jeu de paramètres numériques, définissant les probabilités de transition et d'émission. Le problème de l'apprentissage de l'architecture est NP-difficile, et il n'existe que peu d'heuristiques efficaces. Pourtant, il a été démontré dans des articles récents que les architectures construites à la main sont souvent sous-optimales. HMMER est un programme implémentant ce que l'on appelle des "Profile HMM" pour séquences protéiques : ils permettent de réaliser des recherches dans les bases de données avec une bonne précision, à partir d'une description statistique d'un consensus d'une famille de séquences. HMMER est disponible à cette adresse.

Analyse de données et data mining

Analyse en Composantes Principales

Qu'est ce qu'un tableau de contingence?

Un tableau de contingence, ou tableau à double entrée, est un cas particulier de tableau élémentaire où les lignes et les colonnes jouent un rôle symétrique et où le contenu des cases correspond à des effectifs qui peuvent être sommés en ligne et en colonne. Tout tableau de contingence est en fait le résultat de la transformation d'un tableau élémentaire constitués de deux caractères discrets X et Y décrivant le même ensemble E. Le nombre de ligne d'un tableau de contingence (k) correspond au nombre de modalités du premier caractère discret (X) et le nombre de colonnes (p) correspond au nombre de modalités du second caractère discret (Y). L'effectif d?une case, noté Nij, correspond au "nombre d'éléments du tableau élémentaire E qui prennent simultanément la modalité i de X et la modalité j de Y".
probas, stats (estimation, régression, test d'hypothèses, méthodes multidimenseionnelles, visualisation

Que sont les "règles d'association" (et comment les induire)?

Techniques de classification supervisée

suppose que l'on puisse affecter chacun des individus a sa classe Réseaux de neurones, SVM phase d'apprentissage

Techniques de classification non supervisée

Qu'est-ce qu'une méthode divisive de classification?

C'est une méthode qui permet de faire de la classification hiérarchique tout en extrayant des règles à partir des jeux de données. En gros elles permettent de définir pourquoi tel données est classé dans tel cluster. Ce type de méthode est peu utilisé du fait de sa complexité (il peut être nécéssaire d'évaluer chaque bipartition d'une classe à chaque étape de l'algorithme). Au point de vue algorithmique, on part d'un cluster contenant tous les objets, qu'on subdivise progressivement en clusters plus petits, jusqu'à atteindre le nombre de classes voulues. Une telle méthode est dite monothétique, car elle utilise les caractèristiques des données une par une, à l'inverse de méthodes dites polythétique

Qu'est-ce qu'une méthode de classification agglomérative?

C'est une méthode dans laquelle on place chaque objet dans son cluster, puis on agglomére ces clusters en clusters plus larges

Qu'est ce qu'un arbre de décision?

Ce sont des arbres qui permettent d'extraire des règles à partir de données. Les algorithmes ID3, C5.0 permettent de créer des arbres de décisions

Qu'est ce qu'un arbre de régression?

CART permet de créer des arbres de régression
Quels sont les meilleurs logiciels "open source" ou gratuit d'analyse statistique? - the R package (l'équivalent GNU de S-Plus) Télécharger R-1.2.3.tgz (sources) - ADE-4 Ou trouver une initiation à S-plus (et donc à R)? - Initiation au langage Splus par André Carlier, Alain Croquette Ou trouver des documents sur la classification de données multidimensionnelles? - Analyse des Données Multidimensionnelles par André Carlier, Alain Croquette cela consiste a créer les classes
Ressources: http://ultralix.polytechnique.fr/~cori/Majeure/documents.html

Chapter 10. Prédiction de structure 3D

Table of Contents

Prédiction de structure
Utilisation du profil hydrophylique
Visualisation de structures 3D

Prédiction de structure

Utilisation du profil hydrophylique

Les principales caractèristiques physico-chimiques d'un acide aminé sont le volume, l'accessibilité au solvant, l'hydrophobicité, la taille (petit, gros), et l'aromaticité. Le profil hydrophylique (ou hydropathique) d'une séquence protéique permet d'obtenir quelques indices concernant la structure secondaire de la protéine correspondante. Par exemple, les acides aminés hydrophobiques tendent à se trouver à l'intérieur des protéines globulaires. Dans les protéines transmembranaires, ceux-ci ont tendance à se trouver au niveau de la membrane. Les péridicités au niveau du profil peuvent également indiquer la présence d'hélices alpha. Un tel profil permet également de prédire la présence d'épitopes antigéniques.

Figure 10.1. Profil hydrophobique de la Rhodopsin humaine (tiré de http://lectures.molgen.mpg.de/Individual/Intro/)

Le profil hydrophobique d'une protéine peut être généré à partir du programme toppred, dédié à la prédiction de topologie de protéines membranaires. Cet outil est disponible sous la forme d'une interface web à cette adresse.
IBM va batir un ordinateur parallèle extrèmement puissant dédié à la simulation du repliement protéique. Le projet folding@home a d'ors et deja permi de simuler le repliement d'une petite proteine en des temps record. Ce projet est basé sur la mise a disposition de milliers d'ordinateurs distants. Un autre projet du même type, le Intel-United Devices Cancer Research Project, a pour but de trouver des molécules cibles dans le traitement du cancer. Il s'agit d'un processus appelé "screening virtuel", basé sur un logiciel nommé THINK. THINK crée un modèle 3D de la molécule et tente, en changeant sa forme (conformation), d'en effectuer le "docking" au sein de la protéine cible. Quand une conformation y parvient, et declenche une interaction avec la protéine, on considère qu'il s'agit d'un "hit", et donc une molécule thérapeutique potentielle (si tant est que l'on peut la synthétiser). L'originilalité du projet tient dans le fait que le logiciel THINK est intégré a un economisateur d'ecran, et que celui-ci, librement telechargeable, permet d'utiliser les ressources non-utilisées d'un PC classique.

Visualisation de structures 3D

Il existe de nombreux logiciels permettant de visusaliser des fichiers PDB de coordonnées atomiques. Par exemple : - MolMol - Rasmol - cn3d dispobible sur le site FTP du NCBI - QuickPDB QuickPDB is a lightweight applet with two major functions: (i) Find a structure in the PDB based upon a text or sequence search. (ii) Render that structure with ability to mark up fragments in sequence and see them accordingly in structure view. QuickPDB accesses the most current (nightly updated) version of the PDB database located on San Diego Supercomputer Center (SDSC) servers and uses the new index-based database structure for fast search and retrieval which was developed at SDSC Pour obtenir de plus amples renseignements et éventuellement le droit d'utiliser le programme, contacter Phil Bourne (bourne@sdsc.edu). Le code de QuickPDB est quant à lui disponible à l'adresse http://www.sdsc.edu/pb/Software.html il s'agit d'une applet. Le fichier HTML permettant de faire appel à cette applet est le suivant :
<HTML>
<HEAD>
<TITLE> Applet QuickPDB </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER><H2> Applet QuickPDB </H2></CENTER><BR>
<CENTER><APPLET CODE="QuickPDB.class" WIDTH="200" HEIGHT="50">
<PARAM name="moose_db" value="/projects/nbcr/shindyal/db_2016/db_moose"> 
<PARAM name="html_url" value="http://cl.sdsc.edu"> 
<PARAM name="cgi_url" value="http://cl.sdsc.edu/cgi-bin"> 
<PARAM name="rcsb_explore_url" value="http://www.rcsb.org/pdb/cgi/import.cgi?pdbIds"> 
</APPLET></CENTER>
<BR><CENTER><I>Press button to start QuickPDB</I>
</CENTER>
</BODY>
</HTML>
les représentations WebMol sont un peu moins belles. CEpandant il est plus puissant et plus complet. Ressources Blue Gene: A vision for protein science using a petaflop supercomputer

Chapter 11. Le stockage des données et les bases de données

Table of Contents

Les bases de données
Les bases de données généralistes
Les format de données
XML
Passer d'un format XML à un autre grâce aux transformations XSLT
certaines de ces bases (SwissProt) sont disponibles de manière locale, ce à destination des entreprises qui ne souhaiteraient pas que leur requètes soient connues. Le problème qui se pose alors est la mise à jour automatique des mirroirs

Les bases de données

Les bases de données généralistes

GenBank

SwissProt

Les format de données

XML

XML fournit une moyen pour implementer des ontologies. Une ontologie est un vocabulaire structuré, in the form of a directed acyclic graph such that each term is descended from its parent by some defined relationship such as "part of." It is a network where the children can have many parents and, in turn, be parents themselves. The objectives of the Gene Ontology Consortium are to define these structured hierarchical vocabularies, to describe biological objects using these terms, and to provide computing tools to manipulate these ontologies and connect them to databases.

GEML : Gene Expression Markup Language

http://www.geml.org provide a standard method of exchanging gene expression data along with the associated gene and experiment annotation donner un exemple:

linkOut LinkOut est une fonctionalité d'Entrez permettant à des tiers de lier des entrées Entrez (donc des entrées PubMed, Protein, Nucleotide, Genome, Structure, PopSet, Taxonomy et OMIM) à des informations online externes. Dans ce cadre, IMGT pourrait intervenir comme fournisseur de ressources non-bibilographiques. Pour ceci il faut fournir au NCBI deux types de fichiers XML : - un fichier d'identité, décrivant le site fournisseur d'information externe (IMGT) Ce fichier serait de ce type :


<xml version="1.0"?> 
<!DOCTYPE Provider PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "LinkOut.dtd"> 
<Provider> 
    <ProviderId>777</ProviderId> 
    <Name>The International ImMunoGeneTics Database</Name> 
    <NameAbbr>IMGT</NameAbbr> 
    <SubjectType>curated immunogenetics data</SubjectType> 
    <Url>http://imgt.cines.fr</Url> 
    <IconUrl>http://imgt.cines.fr/logo.png</IconUrl> 
    <Brief>online provider of curated immunogenetics data ..</Brief> 
</Provider> 

le champ ProviderId est fourni par NCBI. - un (ou plusieurs ?) fichiers de ressources, permettant de décrire les objets NCBI sur lesquels ajouter les liens, et l'adresse complète du lien sur IMGT correspondant. En voici un exemple : le lien (link) du fichier XML suivant permet de lier 3 sequences de Genbank (numéros 3810674,1217583, 1181594) à la page "Locus representation: Human IGH" ... Il est semble-t-il possible de faire plus compliquer, c'est-a-dire d'associer des liens à des requètes Entrez complexes (ex : human [orgn] AND "IGHV")


<?xml version="1.0"?> 
<!DOCTYPE LinkSet PUBLIC "-//NLM//DTD LinkOut 1.0//EN" "LinkOut.dtd" 
 <!ENTITY icon.url "http://imgt.cines.fr/logo.png"> 
<!ENTITY base.url "http://imgt.cines.fr/cgi-bin/query.jv?">]> 
<LinkSet> 
<Link> 
    <LinkId>1</LinkId> 
    <ProviderId>777</ProviderId> 
    <IconUrl>&icon.url;</IconUrl> 
    <ObjectSelector> 
        <Database>Nucleotide</Database> 
        <ObjectList> 
            <ObjId>3810674</ObjId> 
            <ObjId>1217583</ObjId> 
            <ObjId>1181594</ObjId> 
        </ObjectList> 
    </ObjectSelector> 
    <ObjectUrl> 
        <Base>http://imgt.cines.fr:8104/textes/IMGTrepertoire/LocusGenes/locus/human/IGH/Hu_IGHmap.html</Base> 
        <Rule></Rule> 
    </ObjectUrl> 
</Link> 
</LinkSet> 


Ces 2 fichiers XML doivent etre transmis au NCBI par FTP à cette adresse ftp-private.ncbi.nih.gov SOURCES : - http://www.ncbi.nlm.nih.gov/entrez/linkout/doc/nonbiblinkout.html

Passer d'un format XML à un autre grâce aux transformations XSLT

Example concret : transformer la sortie XML de blast en fichier FASTA. Seul Blast NCBI fournit ce type de sortie.

<?xml version="1.0"?>
<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">
<BlastOutput>
  <BlastOutput_program>blastn</BlastOutput_program>
  <BlastOutput_version>blastn 2.2.2 [Dec-14-2001]</BlastOutput_version>
  <BlastOutput_reference>~Reference: Altschul, Stephen F., Thomas L. Madden, Alejandro A. Schaffer, ~Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), ~&quot;Gapped BLAST and PSI-BLAST: a new generation of protein database search~programs&quot;,  Nucleic Acids Res. 25:3389-3402.</BlastOutput_reference>
  <BlastOutput_db>drosoph</BlastOutput_db>
  <BlastOutput_query-ID>lcl|1_9533</BlastOutput_query-ID>
  <BlastOutput_query-def>R11 Ubi&gt;R11 UbiA repeat unit 11</BlastOutput_query-def>
  <BlastOutput_query-len>228</BlastOutput_query-len>
  <BlastOutput_param>
    <Parameters>
      <Parameters_expect>10</Parameters_expect>
      <Parameters_include>0</Parameters_include>
      <Parameters_sc-match>1</Parameters_sc-match>
      <Parameters_sc-mismatch>-3</Parameters_sc-mismatch>
      <Parameters_gap-open>5</Parameters_gap-open>
      <Parameters_gap-extend>2</Parameters_gap-extend>
      <Parameters_filter>L;</Parameters_filter>
    </Parameters>
  </BlastOutput_param>
  <BlastOutput_iterations>
    <Iteration>
      <Iteration_iter-num>1</Iteration_iter-num>
      <Iteration_hits>
        <Hit>
          <Hit_num>1</Hit_num>
          <Hit_id>gi|7292381|gb|AE003479.1|AE003479</Hit_id>
          <Hit_def>Drosophila melanogaster genomic scaffold 142000013386045 section 13 of 17, complete sequence</Hit_def>
          <Hit_accession>AE003479</Hit_accession>
          <Hit_len>309883</Hit_len>
          <Hit_hsps>
            <Hsp>
              <Hsp_num>1</Hsp_num>
              <Hsp_bit-score>214.587</Hsp_bit-score>
              <Hsp_score>108</Hsp_score>
              <Hsp_evalue>6.54084e-55</Hsp_evalue>
              <Hsp_query-from>204</Hsp_query-from>
              <Hsp_query-to>1</Hsp_query-to>
              <Hsp_hit-from>214917</Hsp_hit-from>
              <Hsp_hit-to>215120</Hsp_hit-to>
              <Hsp_pattern-from>0</Hsp_pattern-from>
              <Hsp_pattern-to>0</Hsp_pattern-to>
              <Hsp_query-frame>1</Hsp_query-frame>
              <Hsp_hit-frame>-1</Hsp_hit-frame>
              <Hsp_identity>180</Hsp_identity>
              <Hsp_positive>180</Hsp_positive>
              <Hsp_gaps>0</Hsp_gaps>
              <Hsp_align-len>204</Hsp_align-len>
              <Hsp_density>0</Hsp_density>
              <Hsp_qseq>TGAAGTGTCGACTGCTTTTGGATGTTGTAATCGGATAGAGTGCGTCCATCCTCGAGCTGCTTTCCAGCAAAGATCAAACGTTGCTGATCTGGTGGGATTCCCTCCTTATCCTGGATTTTGGCTTTGACATTCTCAATGGTGTCCGAAGCTTCGACCTCGAGAGTGATGGTTTTTCCAGTCAAAGTCTTGACGAAGATCTGCATA</Hsp_qseq>
              <Hsp_hseq>TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCAGCGAAGATCAGACGCTGCTGATCTGGGGGGATTCCCTCCTTATCCTGAATCTTGGCCTTCACATTCTCAATGGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA</Hsp_hseq>
              <Hsp_midline>||||| || |||| ||| ||||||||||||||||| || |||||||||||||| |||||||| ||||| ||||||| ||| ||||||||||| |||||||||||||||||||| || ||||| || |||||||||||||||||||| |  || |||||||| |||||||| ||||| ||||||||||| |||||||||||||||</Hsp_midline>
            </Hsp>
            <Hsp>
              <Hsp_num>2</Hsp_num>
              <Hsp_bit-score>198.729</Hsp_bit-score>
              <Hsp_score>100</Hsp_score>
              <Hsp_evalue>3.8871e-50</Hsp_evalue>
              <Hsp_query-from>204</Hsp_query-from>
              <Hsp_query-to>1</Hsp_query-to>
              <Hsp_hit-from>214005</Hsp_hit-from>
              <Hsp_hit-to>214208</Hsp_hit-to>
              <Hsp_pattern-from>0</Hsp_pattern-from>
              <Hsp_pattern-to>0</Hsp_pattern-to>
              <Hsp_query-frame>1</Hsp_query-frame>
              <Hsp_hit-frame>-1</Hsp_hit-frame>
              <Hsp_identity>178</Hsp_identity>
              <Hsp_positive>178</Hsp_positive>
              <Hsp_gaps>0</Hsp_gaps>
              <Hsp_align-len>204</Hsp_align-len>
              <Hsp_density>0</Hsp_density>
              <Hsp_qseq>TGAAGTGTCGACTGCTTTTGGATGTTGTAATCGGATAGAGTGCGTCCATCCTCGAGCTGCTTTCCAGCAAAGATCAAACGTTGCTGATCTGGTGGGATTCCCTCCTTATCCTGGATTTTGGCTTTGACATTCTCAATGGTGTCCGAAGCTTCGACCTCGAGAGTGATGGTTTTTCCAGTCAAAGTCTTGACGAAGATCTGCATA</Hsp_qseq>
              <Hsp_hseq>TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGGATTCCCTCCTTATCTTGAATCTTGGCCTTCACATTCTCAATGGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA</Hsp_hseq>
              <Hsp_midline>||||| || |||| ||| ||||||||||||||||| || |||||||||||||| |||||||| || || ||||||| ||| ||||||||||| ||||||||||||||||| || || ||||| || |||||||||||||||||||| |  || |||||||| |||||||| ||||| ||||||||||| |||||||||||||||</Hsp_midline>
            </Hsp>
            <Hsp>
              <Hsp_num>3</Hsp_num>
              <Hsp_bit-score>186.834</Hsp_bit-score>
              <Hsp_score>94</Hsp_score>
              <Hsp_evalue>1.47952e-46</Hsp_evalue>
              <Hsp_query-from>222</Hsp_query-from>
              <Hsp_query-to>1</Hsp_query-to>
              <Hsp_hit-from>214443</Hsp_hit-from>
              <Hsp_hit-to>214664</Hsp_hit-to>
              <Hsp_pattern-from>0</Hsp_pattern-from>
              <Hsp_pattern-to>0</Hsp_pattern-to>
              <Hsp_query-frame>1</Hsp_query-frame>
              <Hsp_hit-frame>-1</Hsp_hit-frame>
              <Hsp_identity>190</Hsp_identity>
              <Hsp_positive>190</Hsp_positive>
              <Hsp_gaps>0</Hsp_gaps>
              <Hsp_align-len>222</Hsp_align-len>
              <Hsp_density>0</Hsp_density>
              <Hsp_qseq>CGAAGACGAAGAACGAGATGAAGTGTCGACTGCTTTTGGATGTTGTAATCGGATAGAGTGCGTCCATCCTCGAGCTGCTTTCCAGCAAAGATCAAACGTTGCTGATCTGGTGGGATTCCCTCCTTATCCTGGATTTTGGCTTTGACATTCTCAATGGTGTCCGAAGCTTCGACCTCGAGAGTGATGGTTTTTCCAGTCAAAGTCTTGACGAAGATCTGCATA</Hsp_qseq>
              <Hsp_hseq>CGAAGACGAAGGACCAAGTGAAGGGTGGACTCCTTCTGAATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAAGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA</Hsp_hseq>
              <Hsp_midline>||||||||||| || |  ||||| || |||| ||| || |||||||||||||| || |||||||||||||| |||||||| || || ||||||| ||| ||||||||||| || ||||||||||| || ||||| || || || ||||||||||||||||||||||  || |||||||| |||||||| ||||| ||||||||||| |||||||||||||||</Hsp_midline>
            </Hsp>
	    ...




<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" encoding="iso-8859-1"/>

<xsl:template match="/"> 
<xsl:apply-templates select="BlastOutput/BlastOutput_iterations/Iteration/Iteration_hits/Hit">
</xsl:apply-templates>
</xsl:template> 

<xsl:template match="BlastOutput/BlastOutput_iterations/Iteration/Iteration_hits/Hit"> 
<xsl:if test="Hit_num=1">
<xsl:apply-templates select="Hit_hsps/Hsp">
<xsl:sort data-type="number" select="Hsp_hit-from"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template> 


<xsl:template match="Hit_hsps/Hsp"> 
>seq<xsl:value-of select="Hsp_num"/>-<xsl:value-of select="Hsp_hit-from"/>-<xsl:value-of select="Hsp_hit-to"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="Hsp_hseq"/>
</xsl:template> 

</xsl:stylesheet> 


 
>seq4-213091-213294
TGAAGGGTCGATTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAGGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq6-213319-213523
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATGCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAAGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq8-213548-213751
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATTGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq5-213758-213980
CGAAGACGAAGGACCAAGTGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACTGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAAGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq2-214005-214208
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGGATTCCCTCCTTATCTTGAATCTTGGCCTTCACATTCTCAATGGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq9-214233-214436
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATTGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq3-214443-214664
CGAAGACGAAGGACCAAGTGAAGGGTGGACTCCTTCTGAATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAAGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq7-214689-214892
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCCTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATTGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq1-214917-215120
TGAAGGGTGGACTCCTTCTGGATGTTGTAATCGGACAGGGTGCGTCCATCCTCAAGCTGCTTGCCAGCGAAGATCAGACGCTGCTGATCTGGGGGGATTCCCTCCTTATCCTGAATCTTGGCCTTCACATTCTCAATGGTGTCCGATGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACGAAGATCTGCATA 
>seq10-215145-215347
TGAAGGGTGGACTCCTTCTGAATGTTGTAATCGGACAGGGTGCGTCCGTCTTCCAGTTGCTTGCCGGCGAAGATCAGACGCTGCTGATCTGGGGGAATTCCTTCCTTGTCTTGGATCTTAGCCTTAACATTCTCAATGGTGTCCGAGGGCTCTACCTCGAGGGTGATGGTCTTTCCGGTCAAAGTCTTCACAAAGATCTGCAT
D'autres balises XSL :

<xsl:if test="truc="bleu"">

</xsl:if>


définir un attribut toto="gogo" pour la balise entourante

<table>
<xsl:attribute name="width">100%</xsl:attribute>
</table>
cela donne :
<table width="100%">

</table>


Xalan

Utilisation :

java org.apache.xalan.xslt.Process -in bioinfo.xml -xsl docbook.xsl -out bioinfo.html

Sablotron

sabcmd sheet.xsl arg:/the_input "the_input=<a/>" "$use_defaults=1"

Ressources: Documentation de Sablotron, Gingerall Inc.

Chapter 12. Construction de base de données

Table of Contents

Choix technologiques
Pourquoi Apache ?
Pourquoi Perl ?
Pourquoi MySQL ?
Création de la base de données
Conception Merise et diagrammes
Création de la base de données et des tables
Entrer des données dans la base
Entrer de nouvelles données via SQL
Entrer de nouvelles données via Perl et SQL
Définir un formulaire HTML d'entrée de donnée
Construire le script Perl correspondant
Constrôle des données entrées via le formulaire
Interroger la base
Bonus : utilisation des logs Apache et Perl
Comment trouver les erreurs dans les scripts Perl ?
Qui consulte votre base de données ?
Interfacer des outils externes : FASTA

Avant de commencer la construction d'une base de données d'objets biologiques, il est nécessaire de se poser un certain nombre de questions. Par exemple :

ce type de base existe-t-il deja? si oui, quel avantage y a-t-il à proposer une nouvelle base de données?

Comment se déroulera le recueil de l'information et l'entrée de ces informations dans la base ? d'ou viennent les données et qui va les rentrer? cela va-t-il se faire de manière automatique, ou bien faudra-t-il une armée d'annotateurs aux connaissances pointues? L'expérience montre que le tout automatique ne fournit pas des résultats de qualité, du fait de manque de standardisation, des imprécisions, ou des erreurs dans la chaîne de saisie. D'une manière générale, l'annotation automatique est aujourd'hui difficile voire impossible.

Quelles requètes et quels types de sorties seront nécéssaires ? à quel public se destine cette base de données? il faut pour cela étudier des interfaces utilisateurs conviviales, faciles à utiliser, et adaptées au public visé.

Pour illustrer , nous allons construire une simple base de données de protéines et d'interactions protéine-protéine. Ce type de base de données existe bien évidemment déjà (ProNet par exemple). Néanmoins, une telle base peut avoir un interet dans un domaine spécifique.

Une telle base de données définit un type principal d'objet : la protéine. Une protéine peut être décrite par un très grand nombre de critères. Dans le cadre de cette base, nous décrirons une protéine comme possédant un nom complet et un nom raccourci, une fonction sous la forme d'un texte descriptif, une séquence d'acides aminés, un code PDB correspondant à une structure associée dans la base de données PDB, ainsi qu'un numéro d'accès SWISSPROT.

Nous considérerons également qu'une protéine peut se voir associer un nombre variable de publications, représentées par leur numéro d'accès dans PUBMED.

Enfin, nous considérerons que les protéines peuvent interagir deux à deux, et que cette interaction peut faire l'objet d'une description ou commentaire dans la base.

Choix technologiques

  • le système de gestion de base de données : il s'agit du coeur des bases de données. Il existe trois types de bases de données: les bases de données relationnelles, les bases de données purement objet (ozone), et les bases de données relationnel-objet. Un quatrième type de base de données est néanmoins en train d'emerger, il s'agit de bases permettant de stocker des données au format XML de manière native.
  • la plateforme ou système d'exploitation
  • le serveur web, si cette base de données doit être accessible au travers d'un interface web (soumission de données ou interrogation)
  • le serveur d'application, dont le role est de permettre l'extraction de données à partir de la base en fonction des requètes effectuées par l'utilisateur, puis la construction automatique de pages HTML à partir de ces mêmes données.

Figure 12.1. PROTDB

Nous utiliserons, dans l'exemple qui suit, un serveur web Apache, le serveur applicatif Perl, ainsi qu'une base de données MySQL. Ces logiciels sont gratuits, très performants et utilisés dans de très nombreux projets de base de données. Autre argument important, tous ces logiciels sont disponibles pour les plateformes courantes (Windows, Linux, etc.).

Pourquoi Apache ?

En ce qui concerne le serveur web, le choix est plutot restreint. Outre sa gratuité et sa disponibilité, Apache a depuis longtemps fait les preuves de sa robustesse, de sa rapidité et de sa stabilité. En outre, il offre une sécurité maximale sous Windows comme sous Unix.

Pourquoi Perl ?

Très utilisé dans le domaine de la bioinformatique, Perl est certainement l'un langage de programmation les plus simples à apprendre. Il existe de nombreux modules Perl (Ex : BioPerl) dont le but est de simplifier les taches routinières du bioinformaticien. Perl possède également des modules permettant d'interroger la plupart des bases de données

Pourquoi MySQL ?

MySQL (ou son principal concurrent PostgreSQL) est à ce jour suffisament élaboré pour être utilisé dans de très nombreux cas. Leur fiabilité est généralement excellente, leur disponibilité totale, et en plus ils sont gratuits. MySQL permet de créer des tables contenant plusieurs milliards d'enregistrements.

Création de la base de données

Conception Merise et diagrammes

La méthodologie MERISE fournit un cadre pour la conception efficace de bases de données. Cette méthodologie s'articule autour de trois grandes étapes :

  • établir un modèle conceptuel de données ou MCD
  • établir un modèle logique de données ou MLD
  • établir un modèle physique ou MP

Le MCD est un formalisme permettant de décrire les données intervenant dans le problème et les liens existant entre ces informations de façon claire, simple, complète et non ambiguë. Les formalismes utilisés se situent délibérément en dehors de considérations techniques de stockage informatique des données. Un MCD comprend des entités, des relations, des propriétés, des cardinalités, des identifiants. Une relation peut etre nommée (ex : etre, avoir, represente, etc.). Certaines clés sont plus faciles a manipuler (numéros, codes, etc.). De même, pour une seule entité, plusieurs attributs peuvent avoir le statut de clé.

Le MCD se représente habituellement à l'aide de diagrammes, qu'il est possible de dessiner grace au programme dia. Par exemple :

Figure 12.2. PROTDB

Le modèle logique des données (MLD) consiste à décrire la structure de données utilisée sans faire référence à un langage de programmation. Il s'agit donc de préciser le type de données utilisées lors des traitements. Ainsi, le modèle logique est dépendant du type de base de données utilisé.

Le MP correspond à la traduction du MLD en langage comprehensible par la machine (ex : SQL). C'est ce que nous ferons dans la prochaine section.

Ressources:
  • Initiation aux bases de données http://www.grappa.univ-lille3.fr/polys/access-1997/access.html Dominique Gonzalez
  • Conception de base de données http://www.commentcamarche.net/merise/concintro.php3

Création de la base de données et des tables

Créons la base de données :

$ mysql 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21 to server version: 3.23.36

Type 'help;' or '\h' for help. Type '\c' to clear the buffer

mysql> CREATE DATABASE protdb

Voici les tables devant être créées : les principaux types de données :

  • INT
  • FLOAT
  • VARCHAR
  • CHAR
  • TEXT
  • ENUM

Remarque : il n'existe pas de type BOOLEAN. Pour cela, on utilise généralement TINYINT ou ENUM('true', 'false')


CREATE TABLE PROTEINES (
PROTEINE_ID            int not null auto_increment,
PROTEINE_NOM           varchar(100),
PROTEINE_DESCRIPTION   varchar(255),
PROTEINE_FONCTION      text,
PROTEINE_AASEQUENCE    text,
PROTEINE_PDBID         varchar(20),
PROTEINE_SPID          varchar(10),
primary key(PROTEINE_ID)
);

CREATE TABLE INTERACTIONS (
INTER_ID		int not null auto_increment primary key,
INTER_PROTEINEID1    int,
INTER_PROTEINEID2    int,
INTER_COMMENTAIRE  text
);

CREATE TABLE PUBLICATIONS (
PUBLI_PROTEINEID    int,
PUBLI_PUBMEDID      varchar(10)
);

Avec votre éditeur de texte favori, créez un fichier nommé protdb.sql (par exemple), puis insérez-y les commandes SQL ci-dessus. La création physique des tables se fait alors au moyen de la commande :

$ mysql protdb < protdb.sql

Remarque : il peut être utile, si le schéma de la base est appelé à être modifié souvent de préceder les instructions CREATE TABLE XXX par la commande DROP TABLE IF EXISTS XXX; permettant de supprimer la table. Par exemple :

DROP TABLE IF EXISTS PUBLICATIONS;
CREATE TABLE PUBLICATIONS (
PUBLI_PROTEINEID    int,
PUBLI_PUBMEDID      varchar(10) not null primary key
);

Entrer des données dans la base

Entrer de nouvelles données via SQL

La commande SQL pour insérer de nouvelles données dans une table est la commande INSERT. Par exemple, pour insérer la protéine GADD45a dans notre base de données :

INSERT INTO PROTEINES (PROTEINE_NOM, 
                       PROTEINE_DESCRIPTION, 
                       PROTEINE_FONCTION, 
		       PROTEINE_AASEQUENCE, 
                       PROTEINE_PDBID, 
                       PROTEINE_SPID) VALUES (
                       'GADD45a',
		       'growth arrest and DNA damage inducible protein GADD45, alpha',
		       'MTLEEFSAGEQKTERMDKVGDALEEVLSKALSQRTITVGVYEAAKLLNVDPDNVVLCLLAADEDDDRDVALQIHFTLIQAFCCENDINILRVSNPGRLAELLLLETDAGPAASEGAEQPPDLHCVLVTNPHSSQWKDPALSQLICFCRESRYMDQWVPVINLPER*',
		       'BINDS TO PROLIFERATING CELL NUCLEAR ANTIGEN. MIGHT AFFECT PCNA INTERACTION WITH SOME CDK (CELL DIVISION PROTEIN KINASE) COMPLEXES; STIMULATES DNA EXCISION REPAIR IN VITRO AND INHIBITS ENTRY OF CELLS INTO S PHASE',
		       '',
		       'P24522');

Maintenant, interrogeons la base de données pour voir l'effet de cette commande :

mysql> select * from PROTEINES\G 
*************************** 1. row ***************************
         PROTEINE_ID: 1
        PROTEINE_NOM: GADD45a
PROTEINE_DESCRIPTION: growth arrest and DNA damage inducible protein GADD45, alpha
   PROTEINE_FONCTION: MTLEEFSAGEQKTERMDKVGDALEEVLSKALSQRTITVGVYEAAKLLNVDPDNVVLCLLAADEDDDRDVALQIHFTLIQAFCCENDINILRVSNPGRLAELLLLETDAGPAASEGAEQPPDLHCVLVTNPHSSQWKDPALSQLICFCRESRYMDQWVPVINLPER*
 PROTEINE_AASEQUENCE: BINDS TO PROLIFERATING CELL NUCLEAR ANTIGEN. MIGHT AFFECT PCNA INTERACTION WITH SOME CDK (CELL DIVISION PROTEIN KINASE) COMPLEXES; STIMULATES DNA EXCISION REPAIR IN VITRO AND INHIBITS ENTRY OF CELLS INTO S PHASE
      PROTEINE_PDBID: 
       PROTEINE_SPID: P24522
1 row in set (0.00 sec)

mysql> 


On notera que la requète INSERT précédente ne portais pas sur le champ PROTEINE_ID, de type INT NOT NULL AUTO_INCREMENT. Or nous voyons bien que celui-ci a automatiquement mis à 1 pour la protéine GADD45a. Insérons maintenant les données suivantes :

INSERT INTO PROTEINES (PROTEINE_NOM, 
                       PROTEINE_DESCRIPTION, 
                       PROTEINE_FONCTION, 
		       PROTEINE_FONCTION, 
                       PROTEINE_AASEQUENCE, 
                       PROTEINE_PDBID, 
                       PROTEINE_SPID) VALUES (
                       'PCNA',
		       'proliferating cell nuclear antigen',
		       'MFEARLVQGSILKKVLEALKDLINEACWDISSSGVNLQSMDSSHVSLVQLTLRSEGFDTYRCDRNLAMGVNLTSMSKILKCAGNEDIITLRAEDNADTLALVFEAPNQEKVSDYEMKLMD LDVEQLGIPEQEYSCVVKMPSGEFARICRDLSHIGDAVVISCAKDGVKFSASGELGNGNI KLSQTSNVDKEEEAVTIEMNEPVQLTFALRYLNFFTKATPLSSTVTLSMSADVPLVVEYKIADMGHLKYYLAPKIEDEEGS*',
		       'THIS PROTEIN IS AN AUXILIARY PROTEIN OF DNA POLYMERASE DELTA AND IS INVOLVED IN THE CONTROL OF EUKARYOTIC DNA REPLICATION BY INCREASING THE POLYMERASE'S PROCESSIBILITY DURING ELONGATION OF THE LEADING STRAND',
		       '1AXC',
		       'P12004');


mysql> select * from PROTEINES\G
*************************** 1. row ***************************                                                          
         PROTEINE_ID: 1
        PROTEINE_NOM: GADD45a
PROTEINE_DESCRIPTION: growth arrest and DNA damage inducible protein GADD45, alpha
   PROTEINE_FONCTION: MTLEEFSAGEQKTERMDKVGDALEEVLSKALSQRTITVGVYEAAKLLNVDPDNVVLCLLAADEDDDRDVALQIHFTLIQAFCCENDINILRVSNPGRLAELLLLETDAGPAASEGAEQPPDLHCVLVTNPHSSQWKDPALSQLICFCRESRYMDQWVPVINLPER*
 PROTEINE_AASEQUENCE: BINDS TO PROLIFERATING CELL NUCLEAR ANTIGEN. MIGHT AFFECT PCNA INTERACTION WITH SOME CDK (CELL DIVISION PROTEIN KINASE) COMPLEXES; STIMULATES DNA EXCISION REPAIR IN VITRO AND INHIBITS ENTRY OF CELLS INTO S PHASE
      PROTEINE_PDBID: 
       PROTEINE_SPID: P24522
*************************** 2. row ***************************
         PROTEINE_ID: 2
        PROTEINE_NOM: PCNA
PROTEINE_DESCRIPTION: proliferating cell nuclear antigen
   PROTEINE_FONCTION: MFEARLVQGSILKKVLEALKDLINEACWDISSSGVNLQSMDSSHVSLVQLTLRSEGFDTYRCDRNLAMGVNLTSMSKILKCAGNEDIITLRAEDNADTLALVFEAPNQEKVSDYEMKLMD LDVEQLGIPEQEYSCVVKMPSGEFARICRDLSHIGDAVVISCAKDGVKFSASGELGNGNI KLSQTSNVDKEEEAVTIEMNEPVQLTFALRYLNFFTKATPLSSTVTLSMSADVPLVVEYKIADMGHLKYYLAPKIEDEEGS*
 PROTEINE_AASEQUENCE: THIS PROTEIN IS AN AUXILIARY PROTEIN OF DNA POLYMERASE DELTA AND IS INVOLVED IN THE CONTROL OF EUKARYOTIC DNA REPLICATION BY INCREASING THE POLYMERASE'S PROCESSIBILITY DURING ELONGATION OF THE LEADING STRAND
      PROTEINE_PDBID: 1AXC
       PROTEINE_SPID: P12004
2 rows in set (0.47 sec)

mysql>

Tout comme pour GADD45a, nous voyons bien que le champ PROTEINE_ID de PCNA a automatiquement mis à 2.

Insérons maintenant une interaction entre ces deux protéines :


INSERT INTO INTERACTIONS (INTER_PROTEINEID1, INTER_PROTEINEID2, INTER_COMMENTAIRE)
                          VALUES ('1', '2', 'Using complementary in vivo and in vitro interaction assays the N-terminal (1-46) and middle (100-127) regions of PCNA were identified as harboring MyD118- and Gadd45 interacting domains, whereas PCNA interacting domains within MyD118 and Gadd45 were localized to the C termini of these proteins (amino acids 114-156 and 137-165, respectively)');




Entrer de nouvelles données via Perl et SQL

Le script suivant permet de rentrer la description d'une protéine (contenue dans le script) dans la BD :
#!/usr/bin/perl

use DBI();

$dbh = DBI->connect(    "DBI:mysql:database=protdb;host=localhost", 
                        "", 
                        "",
                        {'RaiseError' => 1}
                );

my %data = ();

%data = ("PROTEINE_NOM"           => "MTK1",
         "PROTEINE_DESCRIPTION"   => "protein kinase, mitogen-activated, kinase kinase 1",
	 "PROTEINE_FONCTION"      => "ACTIVATES THE CSBP2, P38 AND JNK MAPK PATHWAYS, BUT NOT THE ERK PATHWAY. SPECIFICALLY PHOSPHORYLATES AND ACTIVATES MAP2K4 AND MAP2K6",
	 "PROTEINE_AASEQUENCE"    => "
 MREAAAALVPPPAFAVTPAAAMEEPPPPPPPPPPPPEPETESEPECCLAARQEGTLGDSA
 CKSPESDLEDFSDETNTENLYGTSPPSTPRQMKRMSTKHQRNNVGRPASRSNLKEKMNAP
 NQPPHKDTGKTVENVEEYSYKQEKKIRAALRTTERDHKKNVQCSFMLDSVGGSLPKKSIP
 DVDLNKPYLSLGCSNAKLPVSVPMPIARPARQTSRTDCPADRLKFFETLRLLLKLTSVSK
 KKDREQRGQENTSGFWLNRSNELIWLELQAWHAGRTINDQDFFLYTARQAIPDIINEILT
 FKVDYGSFAFVRDRAGFNGTSVEGQCKATPGTKIVGYSTHHEHLQRQRVSFEQVKRIMEL
 LEYIEALYPSLQALQKDYEKYAAKDFQDRVQALCLWLNITKDLNQKLRIMGTVLGIKNLS
 DIGWPVFEIPSPRPSKGNEPEYEGDDTEGELKELESSTDESEEEQISDPRVPEIRQPIDN
 SFDIQSRDCISKKLERLESEDDSLGWGAPDWSTEAGFSRHCLTSIYRPFVDKALKQMGLR
 KLILRLHKLMDGSLQRARIALVKNDRPVEFSEFPDPMWGSDYVQLSRTPPSSEEKCSAVS
 WEELKAMDLPSFEPAFLVLCRVLLNVIHECLKLRLEQRPAGEPSLLSIKQLVRECKEVLK
 GGLLMKQYYQFMLQEVLEDLEKPDCNIDAFEEDLHKMLMVYFDYMRSWIQMLQQLPQASH
 SLKNLLEEEWNFTKEITHYIRGGEAQAGKLFCDIAGMLLKSTGSFLEFGLQESCAEFWTS
 ADDSSASDEIIRSVIEISRALKELFHEARERASKALGFAKMLRKDLEIAAEFRLSAPVRD
 LLDVLKSKQYVKVQIPGLENLQMFVPDTLAEEKSIILQLLNAAAGKDCSKDSDDVLIDAY
 LLLTKHGDRARDSEDSWGTWEAQPVKVVPQVETVDTLRSMQVDNLLLVVMQSAHLTIQRK
 AFQQSIEGLMTLCQEQTSSQPVIAKALQQLKNDALELCNRISNAIDRVDHMFTSEFDAEV
 DESESVTLQQYYREAMIQGYNFGFEYHKEVVRLMSGEFRQKIGDKYISFARKWMNYVLTK
 CESGRGTRPRWATQGFDFLQAIEPAFISALPEDDFLSLQALMNECIGHVIGKPHSPVTGL
 YLAIHRNSPRPMKVPRCHSDPPNPHLIIPTPEGFSTRSMPSDARSHGSPAAAAAAAAAVA
 ASRPSPSGGDSVLPKSISSAHDTRGSSVPENDRLASIAAELQFRSLSRHSSPTEERDEPA
 YPRGDSSGSTRRSWELRTLISQSKDTASKLGPIEAIQKSVRLFEEKRYREMRRKNIIGQV
 CDTPKSYDNVMHVGLRKVTFKWQRGNKIGEGQYGKVYTCISVDTGELMAMKEIRFQPNDH
 KTIKETADELKIFEGIKHPNLVRYFGVELHREEMYIFMEYCDEGTLEEVSRLGLQEHVIR
 LYSKQITIAINVLHEHGIVHRDIKGANIFLTSSGLIKLGDFGCSVKLKNNAQTMPGEVNS
 TLGTAAYMAPEVITRAKGEGHGRAADIWSLGCVVIEMVTGKRPWHEYEHNFQIMYKVGMG
 HKPPIPERLSPEGKDFLSHCLESDPKMRWTASQLLDHSFVKVCTDEE*",

	 "PROTEINE_PDBID"        => "",
	 "PROTEINE_SPID"         => "Q9Y6R4");

$query = "INSERT INTO PROTEINES (
                       PROTEINE_NOM, 
                       PROTEINE_DESCRIPTION, 
                       PROTEINE_FONCTION, 
		       PROTEINE_AASEQUENCE, 
                       PROTEINE_PDBID, 
                       PROTEINE_SPID) VALUES (
                       '$data{"PROTEINE_NOM"}',
		       '$data{"PROTEINE_DESCRIPTION"}',
		       '$data{"PROTEINE_FONCTION"}',
		       '$data{"PROTEINE_AASEQUENCE"}',
		       '$data{"PROTEINE_PDBID"}',
		       '$data{"PROTEINE_SPID"}');";

$sth = $dbh->do($query);

# le champ PROTEINE_ID, automatiquement affecté par MySQL est stocké dans $sth->{'mysql_insertid'};

print "Protéine " . $sth->{'mysql_insertid'} . " insérée dans la base!\n";
        
Insérons maintenant une interaction entre GADD45a et MTK1, toujours grace à Perl.

#!/usr/bin/perl

$query = "SELECT PROTEINE_ID FROM PROTEINES WHERE PROTEINE_NOM = 'GADD45a' OR PROTEINE_NOM = 'MTK1'";

$sth = $dbh->prepare($query);
$res = $sth->execute;
        
$row = $sth->fetchrow_hashref;
$protein1 = $row->{"PROTEINE_ID"};

$row = $sth->fetchrow_hashref;
$protein2 = $row->{"PROTEINE_ID"};

$query = "INSERT INTO INTERACTIONS (
                       INTER_PROTEINEID1, INTER_PROTEINEID2, INTER_COMMENTAIRE)
          VALUES ('$protein1',
	          '$protein2',
		  'commentaire ...');   

Définir un formulaire HTML d'entrée de donnée

Ce formulaire doit permettre de rentrer une nouvelle protéine, et de lui affecter une interaction avec une ou plusieurs protéines déjà présentes dans la base.

Figure 12.3. PROTDB



#!/usr/bin/perl

#
# Perl (traitement de données)
#

use DBI();
use CGI;

$cgi =new CGI;

$dbh = DBI->connect(    "DBI:mysql:database=protdb;host=localhost", 
                        "", 
                        "",
                        {'RaiseError' => 1}
                );

$query = "SELECT PROTEINE_NOM, PROTEINE_ID FROM PROTEINES";

$sth = $dbh->prepare($query);
$res = $sth->execute;
        
my $select = '<select name="INTERACTIONS" multiple="true">'
;
while ($row = $sth->fetchrow_hashref) {
      $select .= '<option value="' . $row->{PROTEINE_ID} . '">' . $row->{PROTEINE_NOM} . "</option>\n"; 
}

$select .= "</select>";
      


#
# HTTP header
#
print $cgi->header;

#
# HTML (affichage)
# 
print <<STOP;
<html>
<body bgcolor="white">


<form action="/perl/insert.pl">
<table>

<tr>
<td align="right">
Nom
</td>
<td>
<input type="text" name="PROTEINE_NOM" value="">
</td>
</tr>

<tr>
<td align="right">
Description
</td>
<td>
<input type="text" name="PROTEINE_DESCRIPTION" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
Fonction
</td>
<td>
<input type="text" name="PROTEINE_FONCTION" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
Séquence
</td>
<td>
<textarea name="PROTEINE_AASEQUENCE" cols="40" rows="10"></textarea>
</td>
</tr>


<tr>
<td align="right">
code PDB
</td>
<td>
<input type="text" name="PROTEINE_PDBID" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
code SWISSPROT
</td>
<td>
<input type="text" name="PROTEINE_SPID" value="" size="30">
</td>
</tr>


<tr>
<td align="right">
Interagit avec
</td>
<td>
$select
</td>
</tr>



<tr>
<td align="right">
</td>
<td>
<input type="submit" name="" value="Valider">

</td>
</tr>

</table>

</form>

</body>
</html>

STOP




Ce script perl doit être placé dans le répertoire cgi-bin ou celui correspondant à mod_perl, puis rendu éxécutable grâce à la commande :
chmod +x protdb_input.pl

Construire le script Perl correspondant

Cas le plus fréquent et le plus pratique : utiliser le même script pour l'affichage du formulaire et l'insertion des données.

#!/usr/bin/perl

#
# Perl (traitement de données)
#

use DBI();
use CGI;

$cgi =new CGI;

$dbh = DBI->connect(    "DBI:mysql:database=protdb;host=localhost", 
                        "", 
                        "",
                        {'RaiseError' => 1}
                );

my $select = "";

if ($cgi->param) {
    
    # insere la description de la proteine dans la BD
    $query = "INSERT INTO PROTEINES (
                       PROTEINE_NOM, 
                       PROTEINE_DESCRIPTION, 
                       PROTEINE_FONCTION, 
		       PROTEINE_AASEQUENCE, 
                       PROTEINE_PDBID, 
                       PROTEINE_SPID) VALUES (
                       '" . $cgi->param("PROTEINE_NOM") . "',
		       '" . $cgi->param("PROTEINE_DESCRIPTION") . "',
		       '" . $cgi->param("PROTEINE_FONCTION") . "',
		       '" . $cgi->param("PROTEINE_AASEQUENCE") . "',
		       '" . $cgi->param("PROTEINE_PDBID") . "',
		       '" . $cgi->param("PROTEINE_SPID") . "');";

    $sth = $dbh->do($query);

    # insere les interaction

    # redirige le navigateur vers une autre page
    print $cgi->redirect("ok.html");
    
    
} else {
    $query = "SELECT PROTEINE_NOM, PROTEINE_ID FROM PROTEINES";
    
    $sth = $dbh->prepare($query);
    $res = $sth->execute;
    
    $select = '<select name="INTERACTIONS" multiple="true">'
	;
    while ($row = $sth->fetchrow_hashref) {
	$select .= '<option value="' . $row->{PROTEINE_ID} . '">' . $row->{PROTEINE_NOM} . "</option>\n"; 
    }
    
    $select .= "</select>";
}   

    
#
# HTTP header
#
print $cgi->header;

#
# HTML (affichage)
# 

 
print <<STOP;
<html>
<body bgcolor="white">


<form action="/perl/protdb_input.pl">
<table>

<tr>
<td align="right">
Nom
</td>
<td>
<input type="text" name="PROTEINE_NOM" value="">
</td>
</tr>

<tr>
<td align="right">
Description
</td>
<td>
<input type="text" name="PROTEINE_DESCRIPTION" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
Fonction
</td>
<td>
<input type="text" name="PROTEINE_FONCTION" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
Séquence
</td>
<td>
<textarea name="PROTEINE_AASEQUENCE" cols="40" rows="10"></textarea>
</td>
</tr>


<tr>
<td align="right">
code PDB
</td>
<td>
<input type="text" name="PROTEINE_PDBID" value="" size="30">
</td>
</tr>

<tr>
<td align="right">
code SWISSPROT
</td>
<td>
<input type="text" name="PROTEINE_SPID" value="" size="30">
</td>
</tr>


<tr>
<td align="right">
Interagit avec
</td>
<td>
$select
</td>
</tr>



<tr>
<td align="right">
</td>
<td>
<input type="submit" name="" value="Valider">

</td>
</tr>

</table>

</form>

</body>
</html>

STOP


Constrôle des données entrées via le formulaire

Quelques lignes de code Javascript permettent d'être sur que certains champs seront systématiquement remplis, et qu'ils seront remplis de la bonne manière. Par exemple, il est possible de s'assurer que le champ PROTEINE_NOM contient au moins 4 caractères (aucun nom de protéine ne possède moins de 4 caractères).

Interroger la base

Il importe évidemment de bien définir le type de requète pouvant être soumises a la base. Exemple : fiche de protéine avec ses interactions Exemple de lien vers SWISSPROT : http://www.expasy.ch/cgi-bin/sprot-search-ac?P24522

#!/usr/bin/perl

#
# Perl (traitement de données)
#

use DBI();
use CGI;

$cgi =new CGI;

$dbh = DBI->connect(    "DBI:mysql:database=protdb;host=localhost", 
                        "", 
                        "",
                        {'RaiseError' => 1}
                );

my $select = "";

if ($cgi->param) {
    
    # recupere la description de la proteine dans la BD
    $query = "SELECT * FROM PROTEINES WHERE PROTEINE_ID = '" . $cgi->param("PROTEINE_ID") . "'";;
    $sth = $dbh->prepare($query);
    $res = $sth->execute;
    
    $proteine = $sth->fetchrow_hashref;
    
	
    # recupere les protéines qui interagissent avec celle-ci et en fait une liste
    $query = "SELECT t1.* FROM PROTEINES as t1, INTERACTIONS as t2 
              WHERE (t2.INTER_PROTEINEID2 = '". $cgi->param("PROTEINE_ID") . "' AND t1.PROTEINE_ID = t2.INTER_PROTEINEID1)
              OR    (t2.INTER_PROTEINEID1 = '". $cgi->param("PROTEINE_ID") . "' AND t1.PROTEINE_ID = t2.INTER_PROTEINEID2)";
    
    $sth = $dbh->prepare($query);
    $res = $sth->execute;
    
    # batit le tableau
    $select = "<table border=1>";
    $select .= "<tr><td>Nom</td><td>code SWWISPROT</td>\n";
    while ($inter = $sth->fetchrow_hashref) {
	$select .= "<tr><td>" . $inter->{PROTEINE_NOM} . "</td>
        <td><a href=\"http://www.expasy.ch/cgi-bin/sprot-search-ac?" . $inter->{PROTEINE_SPID} . "\">" . $inter->{PROTEINE_SPID} . "</a></td>\n";
    }
    $select .= "</table>";
    

        
    
} else {
    $query = "SELECT PROTEINE_NOM, PROTEINE_ID FROM PROTEINES";
    
    $sth = $dbh->prepare($query);
    $res = $sth->execute;
    
    $select = '<select name="PROTEINE_ID">'
	;
    while ($row = $sth->fetchrow_hashref) {
	$select .= '<option value="' . $row->{PROTEINE_ID} . '">' . $row->{PROTEINE_NOM} . "</option>\n"; 
    }
    
    $select .= "</select>";
}   

    
#
# HTTP header
#
print $cgi->header;

#
# HTML (affichage)
# 

if ($cgi->param) { 


    print <<STOP;

<html>
<body bgcolor="white">



<table border="1">

<tr>
<td align="right">
Nom
</td>
<td>
$proteine->{PROTEINE_NOM}
</td>
</tr>

<tr>
<td align="right">
Description
</td>
<td>
$proteine->{PROTEINE_DESCRIPTION}
</td>
</tr>

<tr>
<td align="right">
Fonction
</td>
<td>
$proteine->{PROTEINE_FONCTION}
</td>
</tr>

<tr>
<td align="right">
Séquence
</td>
<td>
$proteine->{PROTEINE_AASEQUENCE}
</td>
</tr>


<tr>
<td align="right">
code PDB
</td>
<td>
$proteine->{PROTEINE_PDBID}
</td>
</tr>

<tr>
<td align="right">
code SWISSPROT
</td>
<td>
$proteine->{PROTEINE_SPID}
</td>
</tr>


<tr>
<td align="right">
Interagit avec
</td>
<td>
$select
</td>
</tr>



<tr>
<td align="right">
</td>
<td>
<input type="submit" name="" value="Valider">

</td>
</tr>

</table>



</body>
</html>

STOP

} else {

    print <<STOP;
<html>
<body bgcolor="white">


<form action="/perl/protdb_query.pl">
    
$select
<input type="submit" value="GO!">    
</form>
STOP
} 


Figure 12.4. Liste des protéines à consulter

Figure 12.5. résultats : affichage d'une fiche protéine

Bonus : utilisation des logs Apache et Perl

Comment trouver les erreurs dans les scripts Perl ?

Si Perl est utilisé en CGI, les erreurs lancées par vos scripts se trouvent ajoutées au fichier d'erreurs du serveur web. Celui-ci peut se trouver à divers endroits selon les plateformes. Par exemple, pour Apache sous Linux Mandrake, le fichier contenant les erreurs est situé à /var/log/httpd/errors

Qui consulte votre base de données ?

La majorité des serveurs web (dont Apache) sont configurés par défaut de manière à conserver une trace des accès aux pages web et scripts associés. Par exemple, pour Apache sous Linux Mandrake, le fichier contenant les accès est situé à /var/log/httpd/access. Il existe des outils très utiles permettant de générer de véritables rapports à partir de ces logs : en particulier le programme webalizer, disponible à l'adresse suivante qui permet d'obtenir un rapport complet sous la forme de pages web avec divers graphiques et tableaux :

Figure 12.6. webalizer

Pour générer ce rapport à partir du fichier de logs /var/log/httpd/access, il suffit de taper :

webalizer /var/log/httpd/access

Attention : par défaut, webalizer fournit un rapport avec les noms ou adresses IP des machines s'étant connecté à votre site. Pour éviter cela, et présever l'anonymité de vos utilisateurs (par exemple des utilisateurs industriels), il faut introduire les 2 lignes suivantes dans le fichier webalizer.conf (un exemple de fichier est fourni sous le nom de sample.conf) :

  
TopSites        0
TopKSites       0

Il est aussi possible de générer plusieurs rapports différents à partir d'un même fichier de logs. Dans ce cas là, ce fichier de logs, ainsi que le répertoire de sortie, et les options des rapports doivent être spécifiés dans plusieurs fichiers de configuration différents, par exemple webalizer-1.conf et webalizer-2.conf. Pour générer ces rapports, on tapera alors :

webalizer -c webalizer-1.conf
.
.
webalizer -c webalizer-2.conf

Interfacer des outils externes : FASTA

Le but de cette opération est de permettre a l'utilisateur de faire d'aligner via FASTA une séquence inconnue (qu'il précisera) contre toutes les séquences protéiques de la base de données. Bien que non utilisé ici, il existe un outil fort pratique pour l'adapatation en "services web" de programmes Unix : PISE, développé par Catherine Letondal, de l'Insitut Pasteur.

L'opération nécessite bien sur d'installer FASTA sur le serveur, cette étape étant décrite plus haut. Contrairement à BLAST, l'utilisation de FASTA en version "standalone" ne nécessite pas la création de bases de donnnées sous un format particulier, un fichier de séquence au format FASTA suffit. Néanmoins, le contenu de la base évoluant, la base de séquence au format FASTA doit etre mise à jour soit à intervalles régulier (par exemple grace a un cronjob), soit a chaque nouvelle entrée d'une séquence dans la base. Nous opterons ici pour la première possibilité, par souci de simplicité.

1ere étape : récuperation, via un script Perl, d'un fichier FASTA contenant toutes les séquences de la base Il s'agit d'un script très simple, qui charge le contenu de la table PROTEINES dans un fichier.

2eme étape : création d'une base de données utilisable par BLAST

3eme étape : définir un formulaire de saisie de séquence

4eme étape : appel de BLAST et affichage des résultats

Chapter 13. Sites et listes de diffusion

Ressources:

Site de l'IMPG (Informatique Mathématique Physique pour la Génomique)
S'inscrire (ou se désinscrire) à la liste bioinfo@impg.prd.fr

Formations:

DESS Bioinformatique pour la génomique et la post-génomique, Université Blaise PASCAL - Clermont II
DEA Mathématiques et Informatique Appliquées à la Biologie, Evry
DESS de BioInformatique, Toulouse

Cours sur le web :

CPSC 536A - Bioinformatics Course, Spring 2001
Computational Molecular Biology
Bioinformatics