#! /usr/bin/perl -w
use strict;
use Getopt::Std;
###########################################################################################
###########################################################################################
###########################################################################################
#
# PROMFINDER: PROMOTER MOTIFS FINDER.
#
# CREATION DATE: March 2003
#
# AUTHORS: Alexandra BALLESTER e-mail: alexandra.ballester01@campus.upf.es
# Patricia GORDILLO e-mail: patricia.gordillo01@campus.upf.es
#
# This program is FREE SOFTWARE. You can distribute it and/or modify it.
#
# The program is aimed to be a powerful tool to find promoter regions in DNA sequences (FASTA format)
# using as much Weight Matrixes (TRANSFAC) as desired.
#
#
#
#
#
#
#
############################################################################################
######################### GLOBAL VARIABLES DECLARATION ####################################
############################################################################################
my %secuencias = ();
my %matrices = ();
my $nummat;
my @posicion;
my $seqname;
my @tot_consenso;
my @max; #consenso
my %total;
my %prin_vent;
my %pmax;#cada secuencia
my $thold;
my %opt; #variables para getopts
my $param_one; #variables para getopts
my $param_two; #variables para getopts
my $n_params; #variables para getopts
my @consens; #Es el vector en el cual, en cada posicion, hallaremos el string correspondiente a la secuencia consenso
my $hit; #Esta variable nos servira para imprimir por pantalla que no hemos encontrado ningun hit.
my $hitsequence; #Esta variable sirve para imprimir en el output el hit para cada secuencia/matriz.
my $hitparcial; #Esta variable va resumiendo nucleotido a nucleotido el hit para cada secuencia/matriz.
my $counter_pinta;
############################################################################################
######################## READING PROGRAM PARAMETERS AND OPTIONS ############################
############################################################################################
#######################################################################################
#####################################################
# reading options
#####################################################
(getopts('vmst:',\%opt)) or die("Problems reading options, try again, please\n");
print_mess("Loading options: done! ");
#####################################################
# reading parameters
#####################################################
print_mess("Reading parameters....");
$n_params = scalar(@ARGV);
# if there are more than two files, quit the program
($n_params == 2) or die (print_error("Wrong number of parameters ($n_params)! Want to try again?\n"));
($param_one) = $ARGV[0];
($param_two) = $ARGV[1];
# write on the screen the name of the parameters one and two
print_mess ("First argument is... ",$param_one,"\n");
print_mess ("Second argument is... ",$param_two,"\n");
print_mess("Parameters LOADED! ");
my ($fastafile,$matrixfile) = @ARGV;
unless (-e $fastafile && -r $fastafile) {
print STDERR "## HEY I can't access to or read $fastafile\n"; #Comprobamos que el fichero de secuencias existe y se puede leer
exit(1);
}
unless (-e $matrixfile && -r $matrixfile) {
print STDERR "## HEY I can't access to or read $matrixfile\n"; #Comprobamos que el fichero de matrices existe y se puede leer
exit(1);
}
#######################################################################################
######################## OPENING OF OUTFILES ##########################################
#######################################################################################
# Opening for writing (>).
open (OUTFILE,">outfile.html");
open (OUTGRAF,">graphical.html");
print OUTFILE "
PROMFINDER
PROMFINDER: TRANSCRIPTIONAL FACTORS MOTIFS SCANNING.
RESULTS.
\n";
print OUTGRAF "
PROMFINDER
PROMFINDER: TRANSCRIPTIONAL FACTORS MOTIFS SCANNING.
GRAPHICAL RESULTS.
\n";
############################################################################################
########################### MAIN LOOP ##########################################
############################################################################################
if (exists($opt{t})){
&opt_t()
}
&leer_fichero_fasta($fastafile);
&pasa_seq2vector();
if (exists($opt{s}) && !exists($opt{m})) {
&opt_s() ;
exit ();
}
if (exists($opt{s}) && exists($opt{m})) {
&opt_s()
}
&leer_fichero_matriz($matrixfile);
if (exists($opt{m})){
&opt_m();
}
&printa_results_matriz();
&pasa_fasta_x_matriz();
#####################################################
# Finish successfully the program execution
#####################################################
print_mess("Everything well done. Exit!\n");
exit(0);
####################################################################################################################################################
################################################ SUBROUTINES ##################################################################################
####################################################################################################################################################
######################################################## READING FASTA FILE ########################################################################
sub leer_fichero_fasta() {
my $file = $_[0];
my $seqname;
open(FASTA,"< $file") || die("### No puedo abrir $file...");
print_mess("Reading $file file....");
while () {
next if /^\s*$/o; #Saltamos las lineas vacias
chomp;
if ($_ =~ m/^>([^\s]+).*$/o) { #capturamos el identificador de la secuencia
$seqname = $1;
$secuencias{$seqname} = "";
next;
};
$secuencias{$seqname} = $secuencias{$seqname} . $_ ;
}; # while
close(FASTA);
if (scalar(keys %secuencias) == 0) { #comprobamos que el fichero introducido contiene informacion de secuencia/-s
print STDERR "## HEY $file no te cap secuencia\n";
exit(1);
};
print_mess("Dealing with $file file information....");
} # leer_fichero_fasta
######################################################## GET SEQUENCES INTO ARRAYS #######################################################################
sub pasa_seq2vector() {
my $k;
foreach $k (keys %secuencias) {
$secuencias{$k} = [ split //o, uc($secuencias{$k}) ]; #pasamos la secuencia a un vector que contendra un nucleotido en mayusculas por posicion
}; # foreach
} # pasa_seq2vector
################################## READING MATRIXES FILE & NORMALIZATION #######################################################################
######################## FINDING CONSENSUS SEQUENCE AND ITS VALUE FOR EACH MATRIX ################################################################
sub leer_fichero_matriz() {
my $matriz = $_[0];
open(MATRIZ,"< $matriz") || die("### No puedo abrir $matriz..."); #comprobamos que el fichero introducido contiene informacion de matriz/-ces
print_mess("Reading $matriz file....");
print_mess("Rearrange of $matriz file information....");
print_mess("Finding consensus sequences for each matrix .....");
print_mess("Calculating scores for consensus sequences.....");
my $m= 0;
my @nucleotidos;
my $suma = 0;
my @consenso;
my $comp = " ";
$nummat = 0;
while () {
next if /^\s*$/o; #Saltamos las lineas vacias
if ($_ =~ m/\AP[0O]\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)/) { #identificamos el inicio de la matriz
# restamos una unidad a $posicion[$nummat] porque al final de la iteracion cuando ha
# leido la ultima fila, se suma 1 al valor de la variable; cuando este valor ya era el
# correspondiente al numero de filas de la matriz.
$consens[$nummat]="";
$posicion[$nummat]--;
if ($nummat-1 >= 0) {
$tot_consenso[$nummat-1] = @consenso;
}
$nummat = $nummat +1;
$posicion[$nummat] = 0;
$nucleotidos[0] = $1; #Capturamos los nucleotidos que encabezan la matriz
$nucleotidos[1] = $2;
$nucleotidos[2] = $3;
$nucleotidos[3] = $4;
@consenso= " ";
$max[$nummat-1] = 0;
next
};
if ($_=~ m/\A\d+\s+([\-\d\.]+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+([\-\d\.]+)/) {
$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] = $1;
$matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] = $2; #Capturamos los valores numericos para cada nucleotido/posicion
$matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] = $3;
$matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] = $4;
$suma = $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] + $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] + $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] + $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]];
$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] = $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] / $suma;
$matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] = $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] / $suma; #Normalizamos la matriz
$matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] = $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] / $suma;
$matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] = $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] / $suma;
################ Obtaining Consensus sequence and its value for each matrix #####################################################################################
if ( $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] >$matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]]) {
$consens[$nummat-1] = $consens[$nummat-1]."A";
$consenso[$posicion[$nummat]] = "A";
$max[$nummat-1] = $max[$nummat-1] +$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]];
}
if ( $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] >$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]]) {
$consens[$nummat-1] = $consens[$nummat-1]."C";
$consenso[$posicion[$nummat]] = "C";
$max[$nummat-1] = $max[$nummat-1] + $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]];
}
if ( $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] >$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]]) {
$consens[$nummat-1] = $consens[$nummat-1]."G";
$consenso[$posicion[$nummat]] = "G";
$max[$nummat-1] = $max[$nummat-1] + $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]];
}
if ( $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] >$matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] && $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]] > $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]]) {
$consens[$nummat-1] = $consens[$nummat-1]."T";
$consenso[$posicion[$nummat]] = "T";
$max[$nummat-1] = $max[$nummat-1] + $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]];
}
if (scalar (@consenso) == $posicion[$nummat]) {
$consenso[$posicion[$nummat]] = "X";
$consens[$nummat-1] = $consens[$nummat-1]."X";
if ( $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]] >= $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]]) {
$comp = $matrices{$nummat}{$nucleotidos[0]}[$posicion[$nummat]];
}
else {
$comp = $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]];
}
if ( $matrices{$nummat}{$nucleotidos[1]}[$posicion[$nummat]] < $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]]) {
$comp = $matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]];
}
if ($matrices{$nummat}{$nucleotidos[2]}[$posicion[$nummat]] < $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]]){
$comp = $matrices{$nummat}{$nucleotidos[3]}[$posicion[$nummat]];
}
$max[$nummat-1] = $max[$nummat-1] + $comp;
}
}
$posicion[$nummat] ++;
next;
next if ($_ =~ m/\AXX\s+(\d+)/); #Indicamos al programa que salte la linea si coincide con la expresion regular de fin de matriz
} #while
# restamos una unidad aqui por la misma razon que en el caso anterior pero este solo
# afecta a la ultima de las matrices a la que no se le resta arriba, puesto que tras
# la ultima matriz no vuelve a haber un match para inicio de nueva matriz.
$posicion[$nummat]--;
$tot_consenso[$nummat - 1] = @consenso;
print_mess("$matriz file READ! --> There are $nummat matrix/-es");
print_mess("Information REARRANGED!");
print_mess("Consensus sequences obtained and stored!");
print_mess("Scores STORED!");
}#leer_fichero_matriz
################################## SEQUENCES EVALUATION USING EACH MATRIX ##################################################################
sub pasa_fasta_x_matriz() {
my @bgcolor;
$bgcolor[2] = "FF0000";
$bgcolor[1] = "00FF00";
$bgcolor[0] = "0000FF";
$bgcolor[3] = "FF7F50";
$bgcolor[4] = "808080";
print OUTFILE "
\n";
print OUTFILE "
\n";
print OUTFILE "RESULTS OBTAINED FROM CANDIDATE SEQUENCES\n";
print OUTFILE "
\n";
print OUTFILE "
\n";
print OUTFILE " SEQUENCE | MATRIX | FIRST POSITION | LAST POSITION | SCORE | HITSEQUENCE |
\n";
my $pinta_sec;
my $k;
my $n;
my $p;
my $av_sec;
my $v;
$hit = 0;
print_mess("\n");
print_mess("Processing sequence/-s with matrix/-es......");
foreach $k (keys %secuencias) {
$pinta_sec = 0;
print OUTGRAF "\n";
print OUTGRAF "Sequence $k | \n";
while ($pinta_sec < (scalar (@{$secuencias{$k}}))){
print OUTGRAF "$secuencias{$k}[$pinta_sec] | \n";
$pinta_sec ++;
}#while
print OUTGRAF "
\n";
print OUTGRAF "
\n";
print OUTGRAF "
\n";
foreach $n (keys %matrices){
$pmax{$k}[$n] =0;
$av_sec = 0;
$total{$k}[$n] = 0;
$pinta_sec = 0;
print OUTGRAF "\n";
print OUTGRAF " Matrix $n | \n";
while ($av_sec < (scalar(@{$secuencias{$k}}) - $posicion[$n])) {
$v = 0;
$p = 0;
$hitparcial = " ";
while ($v < $posicion[$n]) {
$p = $p + ($matrices{$n}{$secuencias{$k}[$av_sec+$v]}[$v]/$max[$n-1]);
$hitparcial = $hitparcial.$secuencias{$k}[$av_sec+$v];
$v = $v + 1;
}
$hitsequence = $hitparcial;
$thold = 0.8;
if (exists($opt{t})) {
$thold = $opt{t};
}
if ($p>=$thold){
print "HIT FOUND !!!!!!!!!!!!!!!!!!!!!\n";
print "SEQUENCE ID \t\t HIT \t\t\t SCORE \t\t\t MATRIX\n";
print "-----------------------------------------------------------------------------------\n";
print "$k \t $hitsequence \t $p \t $n\n";
print "\n";
print OUTFILE " $k | $n | $av_sec | ".( $av_sec+$v)." | $p | $hitsequence |
\n";
$hit ++;
}
if ($p >= $thold){
# print OUTGRAF "
\n";
$pinta_sec = 0;
$counter_pinta = 0;
# while ($pinta_sec <= $av_sec+$v){
while ($pinta_sec <= $av_sec+$v){
if ($pinta_sec < $av_sec) {
print OUTGRAF " | \n";
}
if ($pinta_sec == $av_sec){
while ($counter_pinta <= $posicion[$n]){
print OUTGRAF " | \n";
$counter_pinta ++;
}
}
$pinta_sec ++;
}#while
}
$total{$k}[$n] = $total{$k}[$n] + $p;
if ($pmax{$k}[$n] < $p){
$pmax{$k}[$n] = $p;
$prin_vent{$k}[$n] = $av_sec;
}#if del pmax
$av_sec = $av_sec + 1;
}
print OUTGRAF "
\n";
} #foreach $nummat
}#foreach sec
if ($hit == 0){
print "NO HIT FOUND!!!!!\n";
}
print "Used THRESHOLD VALUE = $thold\n";
print "\n";
print "TWO HTML FILES HAVE BEEN GENERATED WITH RESULTS !!!! RESULTS: outfile.html GRAPHICAL VIEW: graphical.html (IN CURRENT DIRECTORY)\n";
print "HOPE THEY'LL WORTH YOU!\n";
} #pasa_fasta_x_matriz
################################## PRINTING RESULTS #######################################################################
sub printa_results_matriz() {
my $k;
my $n;
my $contador = 0;
print OUTFILE "CONSENSUS SEQUENCES OBTAINED FROM EACH MATRIX\n";
print OUTFILE "
\n";
print OUTFILE " MATRIX | CONSENSUS SEQUENCE | CONSENSUS SEQUENCE VALUE | |
\n";
while ($contador < $nummat){
print OUTFILE "".($contador+1)." | ".($consens[$contador])." | $max[$contador] | |
\n"; #print de las secuencias consenso en el fichero html
$contador ++;
}
print OUTFILE "Consensus Sequences table. When appearing symbol X means that two or more nucleotides have equal scores in the same matrix being this score the maximum value for the position.
\n";
print OUTFILE "
\n";
} #printa_results_matriz
#######################################################################################
############################# GETOPTS #############################################
#######################################################################################
#####################################################
# doing things according to the options selected
#####################################################
sub opt_m {
if (exists($opt{m})) {
# doing things for the "m" option
print "OPTION m: selected!\n";
print "\n";
print "_____________INFORMATION ABOUT MATRIXES______________\n";
print "\n";
print "number of matrixes contained in $matrixfile = $nummat\n";
print "\n";
print "\t _____CONSENSUS SEQUENCES_______\n";
my $r=0;
while ($r < $nummat) {
print "matrix ".($r+1)." consensus sequence: ".($consens[$r])." associated value: $max[$r]\n";
$r ++;
}
}
}#opt_m
sub opt_s {
if (exists($opt{s})) {
# doing things for the "s" option
print "OPTION s: selected!\n";
print "\n";
print "\n";
print "_____________INFORMATION ABOUT SEQUENCES______________\n";
my $k;
foreach $k (keys %secuencias){
my $numgc = 0;
my $congc = 0;
while ($congc < (scalar (@{$secuencias{$k}}))){
if ($secuencias{$k}[$congc] eq "G" || $secuencias{$k}[$congc] eq "C") {
$numgc ++;
}
$congc ++;
}
print "For sequence--> $k:\n";
print "The content of G and C nucleotides is $numgc and its lenght is ".(scalar (@{$secuencias{$k}}))."\n";
print "So the percentage of G+C is ".($numgc/scalar (@{$secuencias{$k}}))."\n";
print "\n";
}
print_mess("\n");
}
}#opt_s
sub opt_t{
if (exists($opt{t})) {
# doing things for the "t" option (the associated value is at $opt{c}
$thold = $opt{t};
print_mess("OPTION t: selected and associated value is $opt{t}!");
}
else {
$thold = 0.8;
print_mess("treeshold value is 0.8 if you want to run the program with another treeshold call it: promfinder.pl -c treeshold_value sequences_file matrixes_file")
}
}#opt_t
############ Subroutines to print messages (info) or errors(break the execution)
# INFO: print information about different stages of the processing
# The info is always send to the Standard Error!
# option "v" (verbose) allows to see the messages on the screen
sub print_mess
{
my @mess = @_;
print STDERR ("\t: @mess \n") if (exists($opt{v}));
}
# ERROR: print message and quit the program
sub print_error
{
my @mess = @_;
print STDERR ("\t: @mess \n") and exit();
}
################################################################################################################################################
################################################################################################################################################
###################################################### THE END ##########################################################################
################################################################################################################################################