Archive de la catégorie «php»

7 mars 2008 – Interface pour l’ajout des orf dans luce_la_puce

mars 7, 2008

11h52 : l’ajout va donc se faire a partir d’un fichier gff.
l’interface va donc etre très simple. une page web avec un formulaire de base. un controle pour envoyer un fichier et un controle submit. et puis le code php pour traiter tout ca. bref, pas trop compliqué. la table bank_orf va etre a revoir cependant.
je vais créer une table bank_gff qui va contenir les metadonnées du fichier gff et la date de release du fichier.

pour créer la table bank_orf, je m’aide de la table feature de la base sophia

CREATE TABLE features(ft_index serial NOT NULL,ft_chr varchar(10),ft_origin varchar(10),ft_type varchar(50),ft_start int4,ft_end int4,ft_score varchar(5),ft_strand varchar(1),ft_frame char(1),ft_rev varchar,ft_dbxref varchar,ft_id varchar,ft_name varchar,ft_note varchar,ft_orf_classification varchar,ft_ontology_term varchar,ft_parent varchar,ft_alias varchar,ft_gene varchar,CONSTRAINT ft_id_key PRIMARY KEY (ft_index))WITHOUT OIDS;ALTER TABLE features OWNER TO fricard;

en fait je ne vais pas créer toute ces colonnes, certaines seront générées automatiquement a partir du fichier gff. cependant je vais les mettre qd meme dans le schema de la base.


create table bank_orf (orf_index serial not null, orf_chr varchar(10), orf_origin varchar(10), orf_type varchar(50), orf_start int4, orf_end int4, orf_score varchar(5), orf_strand varchar(1), orf_frame varchar(1), gff_id serial not null, primary key (orf_index));
create table bank_gff (gff_id serial not null, gff_release_date date, gff_metadata text, primary key (gff_id));

je vais utiliser le module DBGFF.py que j’ai créé pour genepy. comme ca le parser gff est deja fait.

je le fait grace a la commande sys.path += ['/home/gim/genepy']

j’ai finalement modifié bank_gff et j’utilise la date comme clé, ce qui permet d’avoir une contrainte d’unicité sur cette valeur. ce qui se gère bien en python/sql

try :
con.query(query)
except pg.ProgrammingError, e :
print e

qui renvoie

ERROR: duplicate key violates unique constraint "bank_gff_pkey"

si la date existe deja.

j’ai ajouté dans DBGFF.py une méthode pour la classe Features renvoyant un dictionnaire dont les clés sont les attributs de l’objet et les valeurs sont le contenu des attributs. on peut de plus passer un prefixe pour le nom des clés en argument.

  def get_attrdict(self, prefixe=''):      attr_tupple = [ (prefixe + attr, self.getattribute(attr)) for attr in self.attrList  ]      return dict(attr_tupple)

l’avantage de cette méthode est donc d’avoir un dictionnaire des couple attributs, valeurs, ce qui est assez pratique avec la méthode insert de pg.DB
le script pour introduire des features dans la base est donc le suivant

#! /usr/bin/python2.5

import cgiimport pgimport sys

sys.path += ['/home/gim/genepy']

import DBGFF

def create_postgres_db(base):#===============================================================================#    creation de la base de donnee postgresql#===============================================================================

    db = DBGFF.DB(base)    db_date=db.get_release_date('DATE')    print db_date    a=2    DBNAME = "luce_la_puce"    HOST = 'berthemorisot.gim.pasteur.fr'    USER = 'postgres'       #con = pg.connect(dbname=DBNAME, host=HOST, user=USER)    llp=pg.DB(dbname=DBNAME, host=HOST, user=USER)    try :        llp.insert('bank_gff', {'gff_release_date' : db_date, 'gff_metadata':db.info})

    except pg.ProgrammingError, e :        print e        return    prefixe = "orf_"    i = 0    listfields = llp.get_attnames('bank_orf').keys()    listfields = set(map(lambda x : x[4:], listfields))    date_dict={'gff_release_date' : db_date}    for feature in db :        attr_list = set(feature.get_attrlist().keys())        diff = attr_list.difference(listfields)

        if diff :               for attr in diff :

                attr_col = "%s%s" % (prefixe, attr)

                llp.query("alter table bank_orf add column %s varchar" % attr_col)

                listfields.add(attr)

        values = feature.get_attrdict(prefixe)        values.update(date_dict)        llp.insert('bank_orf', values)

        i+=1        if not i%1000 :            print i

print "Content-type: text/html"print

print "insertion des donnees"

post_data=cgi.FieldStorage()gff=post_data['gff_file']create_postgres_db(gff.file)

print "script fini"

ce script n’est pas définitif, il faut l’améliorer pour que l’ergonomie soit correcte.

7 mars 2008 – interface pour SganArrayL

mars 7, 2008

11h17 : maintenant que la base de données est construite il faut faire l’interface pour y accéder, et y entrer des données.

Prenons les choses dans l’ordre. Les premières infos a rentrer sont celles des orfs.
reprenons un peu la table bank_orf

Cette table est un peu pauvre, la table des orf peut-etre bcp plus étendue. dans la base sophia, j’ai créé une table d’orf à partir du fichier gff /home/gim2/bank/saccharomyces_cerevisiae.gff
je vais donc faire pareil pour cette table. et cette fois je vais faire un vrai joli code en python pour ca.
de plus je me dit qu’il faut peut-etre aussi stocker les infos sur la date du fichier d’orf.
bon, y’a plus qu’a retravailler sur un parser de gff finalement.

29 février 2008 – Loreleï

février 29, 2008

17h44 :

J’ai finalement décider de monter rapidement une petite base de donnée très simplifiée pour pourvoir acceder aux info sur les enzymes de restriction.
J’ai donc créer la table lorelei (pour Liste Of Restriction Enzyme with Location and Enzyme Information). cette table se trouve dans la base bab_el_oueb que je devrais renommé babel_oueb d’ailleurs, étant une sorte de fourre-tout pour mes tables.
j’y ai mis aussi une autre base, congel_location.

code pour creer ces bases

DROP TABLE lorelei;
DROP TABLE congel_location;
CREATE TABLE congel_location
(
cl_id serial NOT NULL,
cl_loc varchar(255),
CONSTRAINT congel_location_pkey PRIMARY KEY (cl_id)
)
WITHOUT OIDS;
ALTER TABLE congel_location OWNER TO fricard;
CREATE TABLE lorelei
(
lor_id serial NOT NULL,
lor_name varchar(20),
lor_link varchar(255),
lor__site varchar(50),
cl_id int4,
CONSTRAINT lorelei_pkey PRIMARY KEY (lor_id),
CONSTRAINT lorelei_cl_id_fkey FOREIGN KEY (cl_id)
REFERENCES congel_location (cl_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITHOUT OIDS;
ALTER TABLE lorelei OWNER TO fricard;

lorelei fait référence a congel_location

on stocke dans la base le nom de l’enzyme et le lieu ou est est stockée ainsi qu’un lien vers une base de données donnant les infos sur cette enzyme.

J’ai ensuite créé une interface en php très simplfiée pour voir les donnée, en ajouter et les effacer.
http://berthemorisot.gim.pasteur.fr/lorelei.php

code php

<?php

function add_enz($vals, $db){
$query = "select cl_id from congel_location where cl_loc='".$vals[1]."'";
$res = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
if (pg_numrows($res)==0){
$query="insert into congel_location (cl_loc) values ('".$vals[1]."')";
echo $query;
$res = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
}
$query = "select cl_id from congel_location where cl_loc='".$vals[1]."'";

$res = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
$cl= pg_fetch_row($res, 0);

$cl_id=$cl[0];

$query="insert into lorelei (lor_name, lor_link, cl_id) values ('".$vals[0]."','".$vals[2]."',".$cl_id.")";
$res = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
echo $vals[0]." added<br/>";
}

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>Lorelei</title>
<style type="text/css">
body {
font-family: Arial,Helvetica,sans-serif;
font-size: 12px;
}
h1 {
font-size: 18px;
color: LightSeaGreen;
}
h2 {
font-size: 14px;
}
.initiale{
font-size: 16px;

color: LightSeaGreen;
}
a {
color:steelblue;
text-decoration:none;
}
a:hover{
color:white;
background-color:steelblue;

}
table {
font-size: 13px;
vertical-align:top;
}
td{
vertical-align:top;
}

td.head {
color:white;
background-color:steelblue;

}
td.add{
background-color:YellowGreen;

}
td.del{
background-color:IndianRed;
}
td.add_light{
background-color:#ccff99;
}
td.del_light{
background-color:#ff9999;
}
td.add_dark{
background-color:#003300;
color:white;
}
td.del_dark{
background-color:#330000;
color:white;
}
a.ancre{
color:DarkSlateBlue;
}
a.ancre:hover{
background-color:DarkSlateBlue;
color:white;
}
</style>
</head>
<body>
<table><tr><td rowspan=2>
<img src="lorelei_01.jpg" width=50 height=50 />
</td><td><h1>LORELEÏ</h1></td></tr>
<tr><td>
<h2><span class="initiale">L</span>iste <span class="initiale">O</span>f <span class="initiale">R</span>estriction <span class="initiale">E</span>nzyme with <span class="initiale">L</span>ocation and <span class="initiale">E</span>nzyme <span class="initiale">I</span>nformation</h2>
</td></tr>
</table>
<br/>
<a class="ancre" href="#update">Ajouter ou retirer des enzymes</a>

<balise id="top"></balise>
<br/>
<br/>
<?php
$HOST="berthemorisot.gim.pasteur.fr";
$PORT=5432;
$BASE="bab_el_oueb";
$USER="fricard";
$db = pg_connect("host=$HOST port=$PORT dbname=$BASE user=$USER") or die("impossible de se connecter à la base de données");
if (isset($_POST["add_data"])){
if ($_FILES["file_data"]['name']){
$fichier=$_FILES['file_data']['tmp_name'];
if (file_exists($fichier)) {
$fp2=fopen($fichier, "r");
while(!feof($fp2)){
$line[]=fgets($fp2, 4096);
}
fclose($fp2);
}
}
elseif($_POST["text_data"]){
$line=explode("\n",$_POST["text_data"]);
}
if (count($line)>0){
$sep_list=array("\t",",");
foreach($sep_list as $sep){
if (strpos($line[0],$sep)){
break;
}
}
foreach ($line as $items){
$vals=explode($sep, $items);
add_enz($vals, $db);
}
}
}
if (isset($_POST["del_data"])){
$data_array = $_POST['item_list'];
$in = implode( $data_array, ',');
$query="select lor_name from lorelei where lor_id in ($in)";
$res = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
$query="delete from lorelei where lor_id in ($in)";
$res2 = pg_query($db, $query) or die("La requète $query n'a pas pu aboutir");
for ($i=0;$i<pg_numrows($res);$i++){
$ligne= pg_fetch_row($res, $i);
$enz[]=$ligne[0];
}
if ($i>1){
echo implode( $enz, ', ')." ont été effacées";
}else{
echo implode( $enz, ', ')." a été effacée";
}

}

$query_all = "select lor_id, lor_name, cl_loc, lor_link from lorelei, congel_location where lorelei.cl_id = congel_location.cl_id order by lor_name";
?>
<table>
<tr>
<td> </td><td class="head">Enzyme </td><td class="head">Localisation </td><td class="head">Lien </td></tr>
<?php
$res = pg_query($db, $query_all) or die("La requète n'a pas pu aboutir");
for ($i=0;$i<pg_numrows($res);$i++){
$ligne= pg_fetch_row($res, $i);
echo "<tr>";
foreach($ligne as $val){
if ((strpos($val,"html")) || (strpos($val,"http")) || (strpos($val,"www")) || (strpos($val,"php"))){
echo '<td><a href="'.$val.'">'.$val.'</a></td>';
}
else{
echo "<td>$val</td>";
}
}
echo "</tr>\n";

}
echo "</table>";

?>
<br/>
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<br/>
<a class="ancre" href="#top">Retourner au début de la page</a>
<balise id="update"> </balise>
<br/>
<table>
<tr>
<td class="add_dark">
Pour ajouter des enzymes à la liste
</td>
<td class="del_dark">
Pour effacer des enzymes de la liste
</td>
</tr>
<tr>
<td class="add">
<form name="add_item" method="POST" action="lorelei.php" ENCTYPE="multipart/form-data">
Copier-coller la liste des enzymes ci-dessous selon le format suivant :<br/>
nom localisation lien</br>
en séparant les colonnes par des tabulations ou des virgules<br/> (un copier-coller depuis excel par exemple)
</td>
<td class="del">
sélectionnez la ou les enzymes a effacer<br/>
</td>
</tr>
<tr>
<td class="add_light">
<form name="add_item" method="POST" action="lorelei.php" ENCTYPE="multipart/form-data">

<textarea name="text_data" cols="70" rows="10" wrap="physical" ></textarea>
<br/>
ou uploader un fichier au format décrit ci-dessus<br/>
<input type="file" name="file_data" />
<br/>
<input type="submit" name="add_data" value="Ajouter" />
</form>
</td>
<td class="del_light">
<form name="del_item" method="POST" action="lorelei.php" ENCTYPE="multipart/form-data">
<select name="item_list[]" multiple size=5>
<?php
for ($i=0;$i<pg_numrows($res);$i++){
$ligne= pg_fetch_row($res, $i);
$id=$ligne[0];
$nom=$ligne[1];
echo '<option value="'.$id.'">'.$nom.'</option>';
}
?>
</select>
<br/>
<input type="submit" name="del_data" value="Retirer" />
</form>
</td>
</tr>
</table>
</body>
</head>

20 février 2008 – script pour introduire des données dans la base (suite)

février 20, 2008

9h57 : suite du test sur l’utilisation du module cgi de python
je rajoute
print dir(form)

je récupère
['FieldStorageClass', '_FieldStorage__write', '__contains__', '__doc__', '__getattr__', '__getitem__', '__init__', '__iter__', '__len__', '__module__', '__repr__', 'bufsize', 'disposition', 'disposition_options', 'done', 'file', 'filename', 'fp', 'getfirst', 'getlist', 'getvalue', 'has_key', 'headers', 'innerboundary', 'keep_blank_values', 'keys', 'length', 'list', 'make_file', 'name', 'outerboundary', 'read_binary', 'read_lines', 'read_lines_to_eof', 'read_lines_to_outerboundary', 'read_multi', 'read_single', 'read_urlencoded', 'skip_lines', 'strict_parsing', 'type', 'type_options']

les methodes sont

__contains__
__getattr__
__getitem__
__init__
__iter__
__len__
__repr__
getfirst
getlist
getvalue
has_key
keys
make_file
read_binary
read_lines
read_lines_to_eof
read_lines_to_outerboundary
read_multi
read_single
read_urlencoded
skip_lines

l’objet se comporte un peu comme un dictionnaire, les méthodes has_key et keys permettent d’accéder aux noms des variables passées dans l’adresse
f.keys() renvoie la liste ['toto','tati']

maintenant il faut voir si ca marche avec une requete ajax
mon fichier avec la requete ajax
http://berthemorisot.gim.pasteur.fr/test_ajax.php
et son contenu
la partie javascript

function req_object(method,query, sync){
//fonction renvoyant un objet
XMLHttpRequest qui effectue la requete. l'objet est renvoyé juste après avoir effectuer la requete
var xhr_object = null;

if(window.XMLHttpRequest)//Firefox

xhr_object = new XMLHttpRequest();
else if(window.ActiveXObject) // Internet Explorer
xhr_object = new ActiveXObject("Microsoft.XMLHTTP");
else { // XMLHttpRequest non supporté par le navigateur
alert("Your web browser does not support XMLHTTPRequest objects...");
return;
}
xhr_object.open(method,query, sync);
xhr_object.send(null);
return xhr_object;
}
function request(){
//fonction requete qui envoie des données à test_get.py en utilisant la methode get et
//de façon synchrone (sync=false)
query="cgi-bin/sganarrayl/test_get.py?toto=tata&tati=tonton";
method="get";
sync=false;
var xhr_object=req_object(method,query, sync);
if(xhr_object.readyState == 4) {
//quand la requete est effectuée, affiche le résultat renvoyé par test_get.py dans
//une boite de dialogue
var reponseXML =xhr_object.responseText;
alert(reponseXML);
}
}

et la partie html



1
2

ca marche bien et je reçois correctement la réponse du script python.

12h35 : je vais tester la rapidité de python par rapport au php pour l’accès aux bases de données
j’ai écrit 2 script effectuant les meme actions
le premier en python

#! /usr/bin/python

import cgi
import pg
print "Content-type: text/html"
print

DBNAME = 'sophia'
HOST = 'berthemorisot.gim.pasteur.fr'
USER = 'fricard'
con = pg.connect(dbname=DBNAME, host=HOST, user=USER)
query_all = "select * from features"
all = con.query(query_all)
res=all.getresult()
for val in res[0]:
print val

et le second en php

header("Content-type: text/html");

$HOST="berthemorisot.gim.pasteur.fr";
$PORT=5432;
$BASE="sophia";
$USER="fricard";
$db = pg_connect("host=$HOST port=$PORT dbname=$BASE user=$USER") or die("impossible de se connecter à la base de données");
$query_all = "select * from features";

$res = pg_query($db, $query_all) or die("La requète n'a pas pu aboutir");
$ligne= pg_fetch_row($res, 0);
foreach($ligne as $val){
echo $val.'\n';
}

le code python met en moyenne 222 ms pour faire la requete (sur 11 essais) et le code php met 120 ms en moyenne (sur 11 essais). la requete part du meme script ajax, donc tout est bien equivalent. le code python est presque 2 fois plus lent.
je vais le tenter sur une requete plus longue, car il peut s’agir juste d’un problème d’initialisation.
en modifiant le script pour renvoyer l’ensemble des résultats de la table feature (13316 lignes), le temps d’execution du script python passe a 1518 ms en moyenne (sur 10 essais) et le script php 1481 ms en moyenne(12 essais).
la différence venait donc de l’initialisation de python je pense ou quelque chose comme ca. et encore, je suis obligé d’utiliser python2.3 car le module pg n’est pas installé sur python2.5. je vais essayer de l’installer sur python2.5 pour etre plus tranquille. installation ici
15:25 : je test le meme script avec python2.5 et je n’ai aucune différence, c le meme temps d’execution. mais bon, je préfère quand meme pouvoir me servir de python2.5

Au final je vais donc me servir de python puisque c’est a peine plus lent sur les grosse requetes. il serait qd meme interressant de voir s’il est possible de parser le fichier gpr en php de façon assez simple. cela dit le python est plus simple d’utilisation. a voir donc. dans un premier temps python et puis ensuite peut-etre php.

18h38 : la partie essentielle de sganarrayl est de traiter le fichier envoyé par l’utilisateur. il faut donc etre capable d’envoyer et de recevoir un fichier.
pour l’envoie, les formulaires font ca très bien en utilisant cette ligne de commande
form id="ajax_form" name="ajax_form" action="cgi-bin/sganarrayl/test_get.py" method="post" ENCTYPE="multipart/form-data"

il faut donc utiliser la méthode post, j’ai essayé avec get et ca ne marche pas, ce qui finalement est assez normal car le fichier ne peut pas passer dans l’adresse. ne pas oublier non plus l’encodage avec multipart/form-data
il faut aussi ajouter une balise input de type file mais ca c trivial
input type="file" id="fichier" name="fichier"

du coté du cgi, pour traiter ca c assez simple
on créé une première instance de FieldStorage et on récupère ainsi toutes les variable post. quand un fichier est envoyé, il est stocké sous la forme d’un objet FieldStorage (a nouveau) accessible par la clé qui est le nom de la balise input du formulaire. ok c pas clair mais par contre c tres simple a écrire

import cgi #on importe la classe cgi bien sur
post_data=cgi.FieldStorage() #on récupère les données passée en post
f=post_data['fichier'] #on récupère la variable associée a la clé "fichier"
#comme c un fichier l'objet récupéré est un FieldStorage, avec un attribut file qui est un filehandle
for line in f.file: #on parcours alors ce filehandle
print "%s" % line #et on inprime chaque ligne

facile, non ?
ca marche bien, meme avec un gros fichier du type gpr (fichier de resultat de microarray) et c rapide.
par contre, il n’y a pas le choix, il faut pour envoyer le fichier, passer par le formulaire et un bouton submit. c pas possible de traiter ca juste avec AJAX.
c’est très bien expliqué ici