Programa:

#!/usr/bin/perl -w

use strict;

my $entrada;
my $nom;
my $comptar;
my $num;
my $i;
my @claus;
my @factors;
my $factors;
my $f;
my %matriu;
my $p;
my @total;
my $suma;
my $x;
my $s;

$f = 0;
$s = 0;
$suma =0;

my @sequencia;
my @linia;
my $linia;
my $n;
my $A = 0;
my $C = 0;
my $G = 0;
my $T = 0;
my $N;
my $y=0;
my @logs;

my $k;
my $l;
my $m;
my $g;
my $d;
my $z;
my @lloc;
my $max;
my $imax;
my $fmax;


my @v;
my $c;
my $j;
my $b;
my $tmp;
my $maxrandom;
my $w;
my $cops;
my $pvalue;
my $majuscules;

open (FITXER,"< $ARGV[1]"); #obtindrem la seqüència promotora del gen que volem estudiar


while (){

    $linia = $_;
    
    chomp($linia);

    if ($linia =~m/([ACGTacgt]*)/){

	@linia = split(//,$1);

	push(@sequencia,@linia); #@sequencia serà un vector amb tota la seqüència promotora del gen

    }

}

close (FITXER);

$N = scalar(@sequencia);

$majuscules = 0;

while ($majuscules < $N){ #fem això per tal que el programa ens canviï totes les minúscules per majúscules del promotor

    if ($sequencia[$majuscules] eq "a"){

	$sequencia[$majuscules] = "A";

    }

    if ($sequencia[$majuscules] eq "c"){

	$sequencia[$majuscules] = "C";

    }

    if ($sequencia[$majuscules] eq "g"){

	$sequencia[$majuscules] = "G";

    }

    if ($sequencia[$majuscules] eq "t"){

	$sequencia[$majuscules] = "T";

    }

    $majuscules = $majuscules + 1;

}

@v = @sequencia; #el vector @v ens servirà per randomitzar la seqüència promotora, sense perdre aquesta seqüència

foreach $n (@sequencia){ #el que fem amb aquest foreach, és calcular el nombre d'ocurrències de cada nucleòtid

    if ($n eq "A"){
	
	$A = $A + 1;
    }
	
    elsif ($n eq "C"){

	$C = $C + 1;
    }

    elsif ($n eq "G"){

	$G = $G + 1;
    }

    elsif ($n eq "T"){

	$T = $T + 1;
    }

}
   
$A = log($A/$N)/log 10; #per fer el logaritme en base 10 de la freqüència relativa del nucleòtid en la seqüència promotora
$C = log($C/$N)/log 10;
$G = log($G/$N)/log 10;
$T = log($T/$N)/log 10;

@logs=($A,$C,$G,$T);

open (MATRIUS,"< $ARGV[0]");

while (){

    $entrada = $_;
   
    chomp ($entrada);

    if ($entrada =~m/FA\s+(.+)\s+.\w./){ #agafarem tots els noms dels factors de transcripció
	
	$nom=$1;
	    
	print "\nResultats obtinguts pel factor $nom:\n";
	
	$factors[$f] = $nom;

	$f = $f + 1;	
	
	$factors = scalar(@factors);
	
	$comptar = 0;
			
	}
    
    elsif ($entrada =~m/(\/+)/ && $f != 0){ 
	
	if ($entrada =~m/(\/+)\s+\w+/){ #per distingir entre canvis de matriu i el final de l'arxiu
	    
	    print "\n\nFi de l'arxiu\n";

	}

	else {
    	
	    $num = keys(%matriu);

	    @claus = keys(%matriu);

	    $i = 0;

	    while ($i < $num){
			
		#print "\n$claus[$i]\t"; per imprimir les claus de la matriu de pesos
		
		$p = 0;
		
		while ($p < $comptar){

		  # print "$matriu{$claus[$i]}->[$p]\t"; #per imprimir la matriu de pesos
		    
		   $p = $p + 1;

		}
		
		$i = $i + 1;
		
		}

	    print "\n";
	    
	    $k = 0; #inici del vector que conté la possible posició d'unió del FT

	    $max = -99999;

	    $m = 0; #final del vector que conté la possible posició d'unió del FT

	    $g = $N - 1; # últim nucleòtid que formarà part d'un lloc d'unió del FT

	    $l = $comptar; #llargada del FT
	    	  
	    while ($m < $g){ #mentre l'últim nucleòtid no entre al vector del posible lloc d'unió del FT

		$m = $k + $l - 1; #valor de l'última posició del nucleòtid en la seqüència total
		
		@lloc = @sequencia[$k..$m]; #@lloc serà el vector que contindrà la possible posició d'unió del FT

		#print "@lloc\n"; si vols veure tots els possibles llocs on es pot unir

		my $v = 0; #posició de cada nucleòtid dins del possible lloc d'unió del FT

		$d = 0; #ens anirà sumant els valors de la matriu de pesos (ens donarà l'score)
		
		while ($v < $l){ #mentre la posició del nucleòtid del FT no sigue l'última

		    $z = $matriu{$lloc[$v]}->[$v]; #$z agafa el pes del nucleòtid de la posició $v del vector @lloc, 

		    #print "valor $z\n"; només si volem veure els valors de la matriu de pesos

		    $d = $d + $z; #$d va sumant els pesos fins obtenir l'score
	    		    
		    $v = $v + 1; #per avançar un lloc dins el vector @lloc
		    
		}
		
		#print "suma $d \ $max\n"; si vols veure tots els scores
		
		if ($d > $max){

		    $max = $d;

		    $imax = $k;

		    $fmax = $m;
		    
		}
		
		$k = $k + 1;
	
	    }

	    $max = sprintf("%.4f",$max); #sprintf serveix per arrodonir a 4 decimals, el valor de score

	    print "L'score màxim és $max i el dóna la unió del FT  a la seqüència ",@sequencia[$imax..$fmax]," situada entre els nucleòtids ",$imax+1," i ",$fmax+1,"\n";


	    #============================= PUNT 4 =================================================================================

	    $w = 0;
	    
	    $cops = 0;

	    while ($w < 100) {

		$b = $N -1;

		while ($b >= 0){

		    $j = int(rand($b+1));
		
		    if ($i != $j){
		    
			$tmp = $v[$b];

			$v[$b] = $v[$j];
		    
			$v[$j] = $tmp;

		    }

		    $b = $b - 1;
		
		}
	    
		# print "seqüència random @v\n";
	    
		$k = 0; #inici del vector que conté la possible posició d'unió del FT

		$maxrandom = -99999;

		$m = 0; #final del vector que conté la possible posició d'unió del FT

		$g = $N - 1; # últim nucleòtid que formarà part d'un lloc d'unió del FT

		$l = $comptar; #llargada del FT

		while ($m < $g){ #mentre l'últim nucleòtid no entre al vector del posible lloc d'unió del FT

		    $m = $k + $l - 1; #valor de l'última posició del nucleòtid en la seqüència total
		
		    @lloc = @v[$k..$m]; #@lloc serà el vector que contindrà la possible posició d'unió del FT

		    #	print "@lloc\n"; #si vols veure tots els possibles llocs on es pot unir

		    my $v = 0; #posició de cada nucleòtid dins del possible lloc d'unió del FT

		    $d = 0; #ens anirà sumant els valors de la matriu de pesos (ens donarà l'score)
		
		    while ($v < $l){ #mentre la posició del nucleòtid del FT no sigue l'última
			
			$z = $matriu{$lloc[$v]}->[$v]; #$z agafa el pes del nucleòtid de la posició $v del vector @lloc, 

			#print "valor $z\n"; només si volem veure els valors de la matriu de pesos

			$d = $d + $z; #$d va sumant els pesos fins obtenir l'score
	    		    
			$v = $v + 1; #per avançar un lloc dins el vector @lloc

			# print "$d\n";
		    
		    }

		    #print "suma $d \t $maxrandom \t $max\n"; #si vols veure tots els scores
		
		    if ($d > $maxrandom){
		    
			$maxrandom = $d;

		    }
		
		    $k = $k + 1;
	
		}
		
		if ($maxrandom >= $max){

		    $cops = $cops + 1;

		}

		$w = $w +1;
		
	    } #tanca el while de les 100 vegades

	    $pvalue = $cops/100;

	    print "El p-value associat és $pvalue\n";


	    #=====================================================FI PUNT 4 ========================================================

	
	}
    
    }

		        	
	elsif ($entrada =~m/\d+\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/){ #per crear la matriu de freqüències absolutes
		
	    @total = ($1,$2,$3,$4);
	    
	    while ($s < 4){
		
		$suma = $suma + $total[$s];
		
		$s = $s + 1;
	    }
	    
	    $s = 0;

	    while ($y < 4){

		if ($total[$y] == 0){

		    $total[$y] = -999; #per evitar per logaritme d'un número negatiu
		}
		
		else{
		   
		    $total[$y]=((log($total[$y]/$suma))/log 10) - ($logs[$y]); #per fer la matriu de pesos
		    	       
		}
		$y = $y +1;
	    }

	    $y = 0;

	    $matriu{A}->[$comptar]=$total[0]; #anem ficant cada valor absolut al hash de vectors
	    $matriu{C}->[$comptar]=$total[1];
	    $matriu{G}->[$comptar]=$total[2];
	    $matriu{T}->[$comptar]=$total[3];
	
	    $comptar = $comptar + 1;

	    $suma = 0;
	    
	}
    
    
}
		
print "\n";	

close (MATRIUS);