#!/usr/bin/perl -w

use strict;


my $p= 0;
#variable que enregistra les linies del fitxer de matrus seleccionades de factors de transcripció
my $nom1;
#variable que enregistra nom i codi del TF
my $suma;
#variable que enregistra
my %hash= ("A" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
           "C" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
           "G" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
           "T" => [0, 0, 0, 0, 0, 0, 0, 0, 0]);
#hash de vectors on enregistrarem la matriu del motiu de cada factor de transcripció

my $clau;
#variable que enregistra les claus del hashos

my %prop_prom=("A" => 0,
               "C" => 0,
               "G" => 0,
               "T" => 0);
#hash que enregistra les proporcions de nucleòtids a la seqüència promotora


# *****PAS PREVI: omplir el hash amb les proporcions de la seqüència promotora*****

my $es_primera=1;
#variable activa, que s'inactiva quan llegim la primera linia del fitxer FASTA
my $tota_promotora="";
#variable on guardem la seqüencia promotora
my @promotora;
#vector que enregistra la seqüència promotora
my $total_prom=0;
#variable que enregistra la longitud de la seq promotora
my $nucleotid;
#enregistrem nuclèotids que anem llegint

open(FP,"< $ARGV[1]");
#filehandle que obrirà  el fitxer de la promotora

while (<FP>) {
#comencem a llegir linia per linia el fitxer FASTA
        chomp($_);

        if ($es_primera==1) {
                $es_primera=0;
        }
        #un cop es llegeixi la 1a linia es desactiva la variable
        else {
                $tota_promotora = $tota_promotora . uc($_);
                #uc-->passa a majúscules
        }
        #guardem tota la seq en majúscules en una variable singular

}

close (FP);

@promotora=split(//, $tota_promotora);
# transfromem la variable singular que contenia la seqüència en una variable plural, un vector

$total_prom = scalar(@promotora);
#mesurem la longitud del vector promotora, és a dir, la longitud de la seqüència

my $posicio=0;
#variable que avança al llarg del vector


#comencem a recorrer la seqüència
while ($posicio<$total_prom) {

        $nucleotid = $promotora[$posicio];
        #guardem els nucleotids que llegim


        $prop_prom{ $nucleotid } = $prop_prom{ $nucleotid }  +  1   ;
        #fem servir els nucleotids que llegim com a clau per hash de proporcions i anem                 enregistrant-los en la seva clau corresponent

        $posicio=$posicio+1;
}

# calcul de les proporcions de cada nuclèotid enregistrant-las al hash
$prop_prom{"A"}= $prop_prom{"A"} / $total_prom;
$prop_prom{"C"}= $prop_prom{"C"} / $total_prom;
$prop_prom{"G"}= $prop_prom{"G"} / $total_prom;
$prop_prom{"T"}= $prop_prom{"T"} / $total_prom;

# Les 4 proporcions sumen aprox. 100% (1.0)


# ************* PUNT 1 *************************
open(FH,"< $ARGV[0]");

#filehandle que obrirà  el fitxer de matrius
while (<FH>) {
#tot el programa es realitzarà a mida que anem llegint linia a linia el fitxer
        chomp ($_);

        if ($_ =~ m/^FA  (.+)$/){
        #expressió regular que reconeix el nom i codi del TF
                $nom1= $1;
                #assignem el nom i el codi de TF, a la variable $nom1
                $p=0;
                #al inici de cada matriu del la variable contador esta a 0
                print "\n";
                print "$nom1\n";
        }
        elsif ($_ =~ m/(\d+)\t(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/){
        #expressió regular que reconeix les linies del fitxer només formades per numeros
                $suma= $2 + $3 + $4 + $5;
                #variable per calcular posteriorment les proporcions, per poder tranfromat la                         matriu d'ocurrències en matriu de pesos al punt 2.
                $hash{"A"}[$p]=$2;
                $hash{"C"}[$p]=$3;
                $hash{"G"}[$p]=$4;
                $hash{"T"}[$p]=$5;
                $p= $p + 1;
                #asignem a les diferents posicions del hash els valors corresponents
        }

        elsif (($_ =~ m/^\/\/$/) && ($p>2)){
        #expressió regular que reconeix el fi del motiu

              #************IMPRESSIÓ******************** (feta per l'apartat 1, al programa final no es farà)

              #my $i = 0;
                #variable que conta files

              #my @k = ("A","C","G","T");
                #vector que conta els diferents nucleòtids


              #while ($i < scalar(@k)) {
                #iniciem el recorregut de la matriu per printar-la

                      #my $j = 0;
                        #variable que conta columnes
                      #print "$k[$i]:";
                        #imprimim el nucleòtid, amb aquesta variable que reconeix les claus
                      #while ($j < $p) {
                        #ens permet recorrer la fila fins que s'acabi
                              #print "\t$hash{$k[$i]}[$j]";
                                #printem els valors que toquen
                              #$j = $j + 1;
                                #avancem a traves de la fila
                                #}
                       #print "\n";
                       #$i= $i + 1;
                        #avancem a la següent fila quan arribem al final de la fila
                       #}


              #************PUNT 2: matriu de pessos********************
              foreach $clau (keys (%hash)){
                #cada clau del hash, l'assignarem a la variable $clau i realitzarem les següents                         accions


                      #2. Calculem el pes
                      my $f = 0;
                       while ($f < $p){        #recorrem la fila fins que s'acaba

                               if (($hash{$clau}[$f]) != 0){
                               #quan el valor del hash és diferent a 0 transformem la matriu                                                                                                                                                            d'ocurrències en matriu de pesos
                                     $hash{$clau}[$f]= log($hash{$clau}[$f] / $suma) - log($prop_prom{$clau});
                                     #apliquem la fórmula
                                     #print "\t$hash{$clau}[$f]";
                               }
                               else {
                               #quan sigui igual a 0, asignem el valor de -999

                                     $hash{$clau}[$f] = -999;
                                     #print "\t$hash{$clau}[$f]";
                               }
                               $f = $f + 1;
                               #avancem per la fila   fins arribar a l'última posició de la matriu
                       }


                        #print "\n";
                        }


                        #************PUNT 3: PuntuaciÃ³ amb matriu de pesos ********************
                        my $tamany_f;
                        #llargada finestra
                        my @score;
                        #vector que enregistra els scores de cada finestra
                        #enregistrant-los al 1r nucleòtid de la seqüència
                        my $pos_finestra;
                        #variable que mira en quina posició de la finestra estem
                        my $s_estrella;
                        #ens dona l'score més alt per a cada motiu
                        my $pos_estrella;
                        #ens dona la posició de l'score més alt de cada motiu

                        $tamany_f=$p;
                        #la llargada de la finestra será igual a la llargada del motiu del TF

                        $posicio=0;
                        # tornem a recorrer la seqüència promotora
                        $s_estrella=-99999;
                        #assignem un valor molt baix ja que tenim valors d'score màxim molt baixos

                        while ($posicio <= ($total_prom - $tamany_f)) {
                        #avancem fins arribar a la última finestra possible on poguem mesurar l'score

                                 # **** Recorrem la finestra *****
                                 $pos_finestra=0;
                                 $score[$posicio]=0;

                                 while ($pos_finestra < $tamany_f) {
                                 #bucle que ens permet avançar per la finestra

                                 $nucleotid = $promotora[$posicio + $pos_finestra];
                                 #enregistrem els nuceòtids de totes les posicions de la finestra


                                 $score[$posicio] = $score[$posicio] + $hash{$nucleotid}[$pos_finestra] ;         #anem sumant a l'score de la finestra el valor de la matriu de pesos
                                 #sumem l'score de cada posició de la finestra i ho sumem

                                 $pos_finestra = $pos_finestra+1;
                                 #continuem avançant per la finestra

                                 }                                                                                       #ens quedem amb el valor més alt de cada TF

                                 if ($s_estrella < $score[$posicio]){

                                      $s_estrella = $score[$posicio];
                                      #print "S ESTRELLA = $s_estrella \n";
                                      $pos_estrella = $posicio;
                                      #ens quedem amb el màxim score de tota la seqüència
                                 }

                                 $posicio=$posicio+1;

                        }
                        #print "S ESTRELLA = $s_estrella \n";
                        #print "posició = $pos_estrella\n";

                        # **************** Punt 4  **********
                        my $num_permutacions=0;
                        #variable que calcula el número de permutacions que anem fent
                        my $c = 0;
                        #variable que conta qauntes vegades trobes un score major al màxim de la nostra
                        #seqüència promotora
                        my $pvalue;
                        #variable que printarem al final del treball
                        my @promotora_permutada;
                        #vector on enregistrem les diferents seqüencies permutades que anem obtenint
                        my $n;

                        @promotora_permutada = @promotora;
                        # asignem la seqüència promotora a un nou vector, per no perdre-la cada vegada que realitzem una permutació

                        while ($num_permutacions<100) {

                        # 4.1 **** Algorisme de la Permutació ***

                                    $n = scalar(@promotora_permutada);
                                    my $ii = $n - 1;

                                    while ($ii >= 0) {
                                            my $jj = int(rand($ii+1));
                                            if ($ii != $jj) {
                                                 my $tmp = $promotora[$ii];
                                                 $promotora_permutada[$ii] = $promotora_permutada[$jj];
                                                 $promotora_permutada[$jj] = $tmp;
                                            }
                                            $ii = $ii - 1;
                                    }

                                    # 4.2 *** Apliquem la matriu de pesos repetint el mateix algorisme ***

                                    $posicio=0;

                                    my $s_estrella_permutacio=-99999;


                                    while ($posicio <= ($total_prom - $tamany_f)) {


                                            # **** Recorrem la finestra *****
                                            $pos_finestra=0;
                                            $score[$posicio]=0;

                                             while ($pos_finestra < $tamany_f) {
                                                     $nucleotid = $promotora_permutada[$posicio + $pos_finestra];

                                                     $score[$posicio] = $score[$posicio] + $hash{$nucleotid}[$pos_finestra] ;

                                                     $pos_finestra = $pos_finestra+1;

                                             }

                                             if ($s_estrella_permutacio < $score[$posicio]){

                                                  $s_estrella_permutacio = $score[$posicio];
                                             }

                                             $posicio=$posicio+1;
                                    }

                                    if ($s_estrella_permutacio >= $s_estrella) {
                                         #si trobem un score més alt que l'obtingut a la matriu, sumem la variable c
                                         $c = $c +1;
                                    }

                                    $num_permutacions = $num_permutacions + 1;

                              }      # <--- While de 100 iteracions

                              $pvalue = $c / 100;
                              #print "Vegades (c) > $c \n";
                              print "p-value = $pvalue \n";

                               #***** Inicialització per tractar un nou MOTIU  *********



                               %hash= ("A" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
                                       "C" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
                                       "G" => [0, 0, 0, 0, 0, 0, 0, 0, 0],
                                       "T" => [0, 0, 0, 0, 0, 0, 0, 0, 0]);
                                #tornem a actualitzar el valor de la matriu




        }


}
close (FH);
