#! /usr/bin/perl -w use strict; print "Content-type: text/html\n\n"; ######################################################################################## ##########################PROGRAMA D'ALINIAMENT DE SEQUENCIES########################### ######################################################################################## # definim variables my $seq1; my $seq2; my @seq1_v; my @seq2_v; my $i; my $j; my $m; my $n; my %msubs; my $matriu_substitucio; my @amin_v; my $amin; my @punt_parcials; my @alinea; my @ali1; my @ali2; my @ali3; my @ali4; my @rali1; my @rali2; my @rali3; my $x = 0; my $puntuacio = 0; my $penalitzacio_salt; ###################################################################################### #############################TRACTAMENT DE L'INPUT#################################### ###################################################################################### my $query_string = $ENV{'QUERY_STRING'}; my %hash = &entrada($query_string); if ($hash{seq1} eq "") { print "
There is no sequence 1.Please, paste your sequence and try again."; exit(1); } if ($hash{seq2} eq "") { print "
There is no sequence 2.Please, paste your sequence and try again."; exit(1); } if ($hash{penalitzacio} ne "") { $penalitzacio_salt = $hash{penalitzacio}; } else { $penalitzacio_salt = $hash{penalitzacio_salt}; } ######################################################################################### #######################LLEGIM LES SEQUENCIES EN FORMAT FASTA############################# ######################################################################################### #guardem les sequencies en un vector, i emmagatzemem el nom de la sequencia #($a[0] i $b[0]) en una variable ($primeralinia) i la resta de la sequencia en una altra #variable ($seq). my @a = split (/\n/, $hash{seq1}); my @b = split (/\n/, $hash{seq2}); my $primeralinia1 = $a[0]; my $primeralinia2 = $b[0]; $i = 1; $seq1 = ""; while ($i < scalar(@a)) { $seq1 = $seq1 . $a[$i]; $i = $i + 1; } $i = 1; $seq2 = ""; while ($i < scalar(@b)) { $seq2 = $seq2 . $b[$i]; $i = $i + 1; } #cridem la funcio llegir_sequencia. Explicacio al final del programa @seq1_v = &llegir_sequencia ($seq1); @seq2_v = &llegir_sequencia ($seq2); ####################################################################################### ################################HASH DE HASHOS########################################## ######################################################################################## #obrim el fitxer de la matriu depenent de l'opcio que ha triat l'ususari: if ($hash{matriu} eq "PAM30") { open (MATRIU1, "
; #cridem la funcio llegir_matriu_substitucio. Explicacio al final del programa %msubs = llegir_matriu_substitucio($amin); ########################################################################################## ###############################MATRIU D'ALINIAMENT######################################## ########################################################################################## #aquesta matriu consta de dues matrius: una, la @punt_parcials, que emmagatzema els valors #de les puntuacions, i l'altra, la @alinea, on enregistrem la procedencia de l'alineament #parcial `optim amb tres etiquetes:'D' (diagonal), 'U' (dalt) i 'L' (esquerra) $m = scalar(@seq1_v); $n = scalar(@seq2_v); #fem un 'unshift' a les sequencies per desplac,ar una posicio a la dreta tots # els simbols per poder inserir un simbol de gap '-' a la posicio 0 unshift(@seq1_v,"-"); unshift(@seq2_v,"-"); #enregistrem la matriu al fitxer matali.txt open (MATALI, ">matali.txt"); #mostrem els simbols del vector de les columnes (@seq2_v) print MATALI " "; $i = 0; while ($i < $n+1) { print MATALI "$seq2_v[$i]\t"; $i = $i + 1; } print MATALI "\n"; #mostrem el primer simbol del vector de les files (@seq1_v), que #es un gap '-' print MATALI "$seq1_v[0] "; #a la posicio 0,0 la puntuacio sera 0 $punt_parcials[0][0]=0; $alinea[0][0] = "final"; print MATALI "$punt_parcials[0][0]\t"; #per omplir la primera fila hem d'utilitzar obligatoriament el valor de l'esquerra ($alinea[0][$i] = 'L') #i la puntuacio en cada posicio s'obte de la suma de la puntuacio anterior i el valor de la #penalitzacio_salt ($ARGV[3]) $i = 1; while ($i < $n+1) { $punt_parcials[0][$i]=$punt_parcials[0][$i-1] + $penalitzacio_salt; $alinea[0][$i] = 'L'; print MATALI "$punt_parcials[0][$i]$alinea[0][$i]\t"; $i = $i + 1; } print MATALI "\n\n"; #ara, a partir de la segona fila i segona columna, anem construint #totes les puntuacions parcials recorrent totes les files i per #cada fila totes les columnes $i = 1; while ($i < $m+1) { #mostrem el simbol de la fila print MATALI "$seq1_v[$i] "; #per omplir la segona columna hem d'utilitzar obligatoriament el valor de dalt ($alinea[$i][0] = 'U') #i la puntuacio en cada posicio s'obte de la suma de la puntuacio anterior i el valor de la #penalitzacio_salt $punt_parcials[$i][0] = $punt_parcials[$i-1][0] + $penalitzacio_salt; $alinea[$i][0] = 'U'; print MATALI "$punt_parcials[$i][0]$alinea[$i][0]\t"; $j = 1; while ($j < $n+1) { #per omplir la resta de la matriu hi ha 3 opcions de puntuacio possibles: alinear dos simbols #($puntuacio_diagonal), alinear un simbol de les files (@seq1_v) amb un gap ($puntuacio_dalt) #i alinear un simbol de les columnes (@seq2_v) amb un gap ($puntuacio_esquerra). Ens quedarem #amb l'aliniament parcial que tingui la maxima puntuacio my $puntuacio_diagonal = $punt_parcials[$i-1][$j-1] + $msubs{$seq1_v[$i]}{$seq2_v[$j]}; my $puntuacio_dalt = $punt_parcials[$i-1][$j] + $penalitzacio_salt; my $puntuacio_esquerra = $punt_parcials[$i][$j-1] + $penalitzacio_salt; if ($puntuacio_diagonal >= $puntuacio_dalt && $puntuacio_diagonal >= $puntuacio_esquerra) { $punt_parcials[$i][$j] = $puntuacio_diagonal; $alinea[$i][$j] = 'D'; } else { if ($puntuacio_dalt >= $puntuacio_diagonal && $puntuacio_dalt >= $puntuacio_esquerra) { $punt_parcials[$i][$j] = $puntuacio_dalt; $alinea[$i][$j] = 'U'; } else { $punt_parcials[$i][$j] = $puntuacio_esquerra; $alinea[$i][$j] = 'L'; } } #imprimim a cada posicio de la matriu el valor de la puntuacio parcial i d'on prove #aquest valor print MATALI "$punt_parcials[$i][$j]$alinea[$i][$j]\t"; $j = $j + 1; } $i = $i + 1; print MATALI "\n\n"; } #tanquem el fitxer close (MATALI); ############################################################################################ ###################################ALINIAMENT OPTIM######################################### ############################################################################################ #un cop tenim la matriu d'aliniament, obtindrem l'aliniament optim comenc,ant # per l'ultima fila i columna, i seguint les anotacions de 'D' (diagonal) # 'U' (dalt) i 'L' (esquerra) que tenim a la matriu @alinea. #Fem servir 3 vectors (@ali1,@ali2 i @ali3): @ali1 contindra els valors de la seq1, @ali2 #contindra els valors de la seq2 i @ali3 contindra els simbols '*','.' o ' '. Posarem un '*' #si els 2 aa son iguals, un '.' si el valor corresponent de la matriu d'identitats es >= 0, i #' ' si aquest valor es < 0 o aliniem l'aa amb un gap. #Paral.lelament anem calculant la puntuacio de l'aliniament optim pas per pas ($puntuacio) #declarem variables $i = $m; $j = $n; while ($i > 0 || $j > 0) { #si la puntuacio maxima venia de la diagonal alineem el simbol #$i de seq1_v amb el simbol $j de seq2_v i posem '*', '.' o ' ' #segons correspongui if ($alinea[$i][$j] eq 'D') { $ali1[$x] = $seq1_v[$i]; $ali2[$x] = $seq2_v[$j]; if ($seq1_v[$i] eq $seq2_v[$j]) { $ali3[$x] = "*"; } else { if ($seq1_v[$i] ne $seq2_v[$j] && $msubs{$seq1_v[$i]}{$seq2_v[$j]} >= 0) { $ali3[$x] = ":"; } if ($seq1_v[$i] ne $seq2_v[$j] && $msubs{$seq1_v[$i]}{$seq2_v[$j]} < 0 ) { $ali3[$x] = " "; } } #en aquest cas el valor de la puntuacio sera el valor anterior mes el valor corresponent a #la matriu d'identitats $puntuacio = $puntuacio + $msubs{$seq1_v[$i]}{$seq2_v[$j]}; $i = $i - 1; $j = $j - 1; $x = $x + 1; } else { # si la puntuacio maxima venia de dalt, alineem el simbol # $i de seq1_v amb un gap i per tant el valor de $ali3[$i] sera ' ' if ($alinea[$i][$j] eq 'U') { $ali1[$x] = $seq1_v[$i]; $ali2[$x] = "-"; $ali3[$x] = " "; #aqui, el valor de la puntuacio sera la suma del seu valor anterior mes el de la #penalitzacio per gap $puntuacio = $puntuacio + $penalitzacio_salt; $i = $i - 1; $x = $x + 1; } else { # si la puntuacio maxima venia de l'esquerra, alineem un # gap amb el simbol $j de seq2_v. El valor de $ali3[$i] sera tambe ' ' $ali1[$x] = "-"; $ali2[$x] = $seq2_v[$j]; $ali3[$x] = " "; #aqui, el valor de la puntuacio sera la suma del seu valor anterior mes el de la #penalitzacio per gap $puntuacio = $puntuacio + $penalitzacio_salt; $j = $j - 1; $x = $x + 1; } } } #fem un reverse dels 3 vectors per tenir l'aliniament en el mateix ordre que el de les #sequencies inicials @rali1 = reverse(@ali1); @rali3 = reverse(@ali3); @rali2 = reverse(@ali2); #imprimim l'aliniament de 60 en 60 aa com el format fasta. Per fer-ho creem una matriu (@ali4) de #tres files on la primera sera el vector rali1, la segona el vector rali3 i la tercera el vector rali2. #El numero de columnes sera la llargada de l'aliniament. my $volta = 1; $j = 0; $i = 0; $x = 0; my $l = 0; #enviarem l'aliniament al fitxer resultat.txt o a resultat.html print " \n\n"; print "$primeralinia1\n$primeralinia2\n\n"; while ($i < scalar(@rali1)) { $x = $i; $j = 0; $l = $l + 1; #mostrem la posicio del primer aa de la fila print "$l\t\t"; while ($j < 3) { $i = $x; if ($j > 0) { print "\t\t"; } #anem mostrant cada element de la matriu separats en blocs de 60 columnes while ($i < 60*$volta && $i < scalar(@rali1)) { if ($j == 0) { print ""; $ali4[$j][$i] = $rali1[$i]; } if ($j == 1) { if ($rali3[$i] eq "*") { print ""; } if ($rali3[$i] eq ":") { print ""; } $ali4[$j][$i] = $rali3[$i]; } if ($j == 2) { print ""; $ali4[$j][$i] = $rali2[$i]; } print $ali4[$j][$i]; $i = $i + 1; } #imprimim la posicio l'ultim aa del bloc if ($j == 0) { print ""; if ($i < (scalar(@rali1)-1)) { $l = $l + 59; print "\t\t$l"; } else { $l = scalar(@rali1); print "\t\t$l"; } } print "\n"; $j = $j + 1; } print "\n\n"; $volta = $volta + 1; } print "\n"; #mostrem la puntuacio total de l'aliniament print "score: $puntuacio\n\n"; ########################################################################################## ################################FUNCIONS################################################## ########################################################################################## #FUNCIO: entrada #OBJECTIU: decodificar i transformar les dades que arriben al programa des de la pagina #html en un hash per poder-les utilitzar com a variables. #Per aconseguir-ho, fem un split de & de manera que les dades ens queden separades en #quatre blocs (seq1, seq2, matriu i penalitzacio_salt) i a continuacio fem un altre split # de = de forma que queda separat l'identificador del contingut. Decodifiquem el contingut #(@value) transformant el '+' en un espai i els codis dels simbols (per exemple, %0D%0A) #en els corresponents simbols. Fem un hash on les claus son els identificadors (@key) i on #els valors (@value) son els continguts. #PARAMETRE: les dades que arriben de la pagina html, totes seguides i codificades. #RETURN: retornem el hash. sub entrada { my $i = 0; my $entrada = $_[0]; my @key; my @value; my @vector = split (/&/, $entrada); while ($i < scalar(@vector)) { ($key[$i],$value[$i]) = split (/=/, $vector[$i]); $value[$i] =~ tr/+/ /; $value[$i] =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg; $hash{$key[$i]} = $value[$i]; $i=$i+1; } return %hash; } #FUNCIO: llegir_sequencia #OBJECTIU: transformar la sequencia en format fasta en un vector on a cada posicio hi hagi #un aminoacid. #En primer lloc, transferim el contingut de la variable $seq a un vector @v de forma que cada #element del vector sera una fila de la sequencia. En segon lloc, ajuntem tots els elements #del vector @v en una nova variable $seq_v i transferim el contingut de $seq_v al vector #@seq_v, on cada posicio sera un aminoacid de la sequencia #PARAMETRE: la sequencia en format fasta ($seq) #RETURN: retornem el vector on cada posicio es un aa sub llegir_sequencia { my $x=$_[0]; my @v = split(/\n/,$x); my $seq_v = ""; $i = 0; while ($i < scalar(@v)) { $seq_v = $seq_v . $v[$i]; $i = $i + 1; } $seq_v =~ s/\W//g; my @seq_v = split (//, $seq_v); return @seq_v; } #FUNCIO: llegir_matriu_substitucio #OBJECTIU: construim un hash a partir de la matriu de substitucio. #En primer lloc, agafem la primera linia de la matriu i la passem a un vector #(@amin_v) on cada posicio hi haura un aa. #En segon lloc, construim el hash: #anem recorrent totes les columnes per cada fila. #guardem cada fila al vector @v #assignem el valor de la matriu ($v[$i]) a la parella d'aminoacids corresponents ($v[0] i $amin_v[$i-1]) #PARAMETRE: la primera linia de la matriu ($amin) #RETURN: el hash (%msubs) sub llegir_matriu_substitucio { $amin = $_[0]; chomp($amin); @amin_v = split(/ +/,$amin); shift(@amin_v); my $i = 0; while () { chomp; my @v = split(/ +/); my $j = 0; while ($j < scalar(@amin_v)) { $msubs{$amin_v[$i]}{$amin_v[$j]} = $v[$j+1]; $j = $j + 1; } $i = $i + 1; } return %msubs; }