#!/usr/bin/env perl
############################################################
#
# $Id: network-interactions ,v 0.1 2020/06/12 mpadilla Exp $
#
############################################################


=pod

=head1 NAME

network-interactions

=head1 VERSION

version 1

=head1 DESCRIPTION

Constructs and compares Gene Networks based on the output of <matrix-scan>
from a list of genes and transcriptional factors of interest.

=head1 AUTHORS

mpadilla@lcgej.unam.mx
amedina@liigh.unam.mx

=head1 CATEGORY

=over

=item network tool

=back

=head1 USAGE

network-interactions -tfs [TFsListFile] -cre [RegulatorySeqsBEDfile] -genome [GenomeAssembly] [...]

=head1 INPUT FORMATS

=head2 TFs list file

A one-column file with all transcriptional factors of interest.
Warning! This names should match the gene names indicated in the BED file.

=head2 Regulatory regions BED file

A BED file referring all regulatory regions of all genes of interest,
including TFs. Gene names must be provided in the fourth column.

=head2 Network file

A two-column file indicating all two-node interactions, one per row.

=head1 OUTPUT FORMATS

=head2 Complete Network. <complete_direct_interactions_date.tsv>

A table indicating all direct putative interactions found for all genes
specified in the BED file of regulatory regions. Format is as follows: A
TF-gene interaction per row, the coordinates in which the interaction was
found (as indicated in the input BED), the one-based position starting from
the first coordinate followed at last by the <matrix-scan>'s related score
to the TF's binding in such position. If the interaction is found more than
once, then details of positions and scores are separated by ";", where the
first score corresponds to the first position and so on. If the interaction
is found in another coordinate, then this will appear on another row.

=head2 Gene Regulatory Network. <GRN_direct_interactions_date.tsv>

A table indicating all direct putative interactions found only for
transcription factors. Format is as follows: A TF-TF interaction per row
(the first one regulates the second one), the coordinates in which the
interaction was found, the one-based position starting from the first
coordinate followed at last by the <matrix-scan>'s related score to the TF's
binding in such position. If the interaction is found more than once, then
details of positions and scores are separated by ";", where the first score
corresponds to the first position and so on. If the interaction is found in
another coordinate, then this will appear on another row.

=head2 Gene Regulatory Network indirect interactions. <GRN_indirect_interactions_date.tsv>

Because the program only finds direct putative interactions, this file
indicates all direct interactions composed by 3 nodes. E.g.:
       TFx ==> TFy ==> TFz
which should be read as: TFx directly regulates TFy and TFy directly
regulates TFz, thus, TFx indirectly regulates TFz.

Special cases:

A TF has no targets.
  If a TF has no direct targets (hence no indirect targets) it is specified
  as: "TFx has no targets". If this given "TFx" is a direct target of
  another TF, then "TFx" will simply be a terminal node.

TF regulating itself.
  Cases of TFs putatively regulating theirselves are only specified once,
  as a two-node interaction. E.g.:    TFy ==> TFy

For each TF-TF interaction, the same details are given as in
<GRN_direct_interactions_date.tsv>, these are: coordinates, positions and
scores.

=head2 Network Comparision (-report_net)

When an input network is given, a comparision is made between the input
network and the one generated by the program (the complete network), notice
that this comparison is made only for the direct interactions found. This
comparision is made only taking into account all genes refered to in the
input BED file and will generate the three following output files:

=head2 network_intersection_date.tsv

A tab-delimited file containing, one per row, all the common interactions
between the input network and the network of all genes generated by the
program. Information about coordinates, positions and scores related to the
output network is also given.

=head2 network_not_found_interactions_date.tsv

A two-column, tab-delimited file containing, one per row, all the
interactions found in the input network but not found again in the output
network (the assymetric difference for input network).

An interaction can be "not_found" for one of several reasons:
 a) One or both of the gene's regulatory sequence was not indicated.
 b) The chosen motif database does not contain a matrix describing the
    motif for the TF in the interaction. Default database is JASPAR's 2020
    nonredundant vertebrate motif collection.
 c) <matrix-scan> did not found an instance of the TF's motif in the genomic
    sequences indicated or it found it but it was not reliable given the
    score and/or p-val thresholds.

Since these interactions are absent in the complete output network,
information about coordinates, positions and scores are also absent.


=head2 network_found_interactions_date.tsv

A tab-delimited file containing, one per row, all the interactions found by
the program but that were not specified in the input network (the assymetric
difference for the complete network). Information about coordinates, positions
and scores related to the output network is also given.


=head1 SEE ALSO

=head1 WISH LIST

=over

=item B<wish 1>

=item B<wish 2>

=back

=cut


BEGIN {
  if ($0 =~ /([^(\/)]+)$/) {
    push (@INC, "$`lib/");
  }
}

require "RSA.lib";
#use strict;
use warnings;
use Cwd;

################################################################
## Main package
package main;
{

  ################################################################
  ## Initialise parameters
  our $start_time = &RSAT::util::StartScript();
  our $program_version = do { my @r = (q$Revision: 1.48 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
  #    $program_version = "0.00";

  #our %infile = ();
  #our %outfile = ();

  our $verbose = 1;
  our $in = \*STDIN;
  my $out = \*STDOUT;

  # command-line arguments
  %main::infile = ();
  %main::outfile = (); # hash of main output files
  %main::used_outfile = (); # hash of intermediate files used by the program
  our $databases = ""; # matrixes dbs
  our $genome = ""; # working genome version
  our $orgdb = ""; # alternative to databases
  our $report_net = 0; # boolean, 1 if network is provided
  #our $net_type = "not_grn"; # default for network type
  our $title = "network interactions results"; # tilte for summary html page
  our $html = 0; # flag variable to output html or not
  our $date = ""; # date for output files
  our $output_prefix = "";
  our $output_dir = "";
  our $seq = 0; # flag variable for input sequences
  our $matrices = 0; # flag variable for input matrices
  our $scan = 0; # flag variable for input scan
  our $score = 5; # score lth to run matrix-scan
  our $pval = "NA"; # pval lth to run matrix-scan
  our $archive_format = "zip"; # default
  our $onlymats = 0; # flag variable, return only TFs matrixes

  # tables strings for html page
  my $tables_str = ();

  my $basename = "";
  local $log; # filehandle for log file

  # other variables
  my $new_enhancer; # filehandle of filtered bed file
  my @genes_reg = (); # genes regulated
  my %nonRep_genes_reg; # hash of non-repetitive genes regulated
  my $val = 0; # values of has %nonRep_genes_reg
  my $i; # general counter variable

  my %nonRepTFs; # hash of non repetitive TFs
  my $report_tfs_noRegSeq = ""; # string with TFs not found on bed file
  my $report_tfs_RegSeq = ""; # string with TFs found on bed file

  my (@net_old_allgenes, @net_old_onlyTFs); # networks from input
  my %noRegSeq = (); # genes lacking regulatory sequence
  my $noRegSeq_reporting = ""; # string of genes lacking reg seq
  my %RegSeq = (); # genes with regulatory sequence on input
  my $RegSeq_reporting = ""; # string of genes with reg seq
  my $z = 1; # values of a hash, actual value is unimportant but it must start at 1
  my $flag = 0;
  my $ngenes = 0; # number of genes regulated
  my $ntfs = 0; # number of genes regulated
  my $interaction_completenet = 0; # flag var to check that matrix-scan gave results

  my @matfiles_path = (); # rsat path to matrixes in use
  my @dbs = ();  # list of databases
  my @fields = (); # general var, list of fields from rows in a file
  my @nonRepTFs_k; # TFs list
  my $fasta; # filehandle of sequences
  my $new_fasta; # filehandle of sequences with headers
  my $cmd = ""; # general variable for &doit
  my $ACs = ""; # list of ACs from matrixes to use

  my (@net_new_allgenes, @net_new_onlyTFs); # networks
  my @seq_id; # seq_id splitted from matrix-scan results
  my %interaction_details; # hash of interaction_details: coordinates, positions and scores
  my @gene_name = ();
  my @deadend = (); # binary list with length of total TFs, 1 if the TF has no direct interactions
  my $matrixscan_re; # filehandle of matrix-scan results

  my $interaction_gene_row; # complete network filehandle
  my ($intersection, $found, $not_found); # filehandles for networks' intersection and complements

  my $count = 0;
  my %nonRepTFs_inv; # inverse hash of nonRepTFs

  my $direct; # filehandle of file with GRN direct interactions (main output)
  my $path = ""; # construction of paths in node

  ## Parameters for the &doit() command
  $dry = 0;
  $die_on_error = 1;
  $job_prefix = "network-interactions";
  $batch = 0;
  #$main::archive=0; # used only once

  $main::out = STDOUT; # one_command() relies on this variable

  ##################################################################
  ### Variables for summary html

  our %status= ();

  #local @tab_to_convert = (); ## Tables to convert to html

  ## A hash to save the name of the clusters and their corresponding
  ## hexa code
  #local %hexa_code = (); # used only once
  local $blue_color = '#D6EEFA';
  local $orange_color = '#F6E6CA';
  local $font_color = '#CC6600';
  local $blue_font_color = '#0D73A7';

  ## Hash containing the icon paths
  local %icons = ();

  local $include_js_lib = 1;

  ## Base on which we will buld the the URLs to the javascripts (D3 +
  ## JQuery libraries, required to display logo trees and tables).
  local $js_base;
  local $d3_base;
  local $d3_venn_base;
  local $jquery_base;
  local $datatable_base;
  local $datatable_css_base;


  ################################################################
  ## Read argument values
  &ReadArguments();

  ## set date for output and report
  $date = &AlphaDate() if ( $date eq "");

 ################################################################
  ## Check argument values
  unless ($main::infile{TFs}) {
    &RSAT::error::FatalError("File with the network's transcription factors must be provided\n It must be a one-column file with list of TFs");
  }
  unless ($main::onlymats){
    unless ($main::infile{cres}) {
      &RSAT::error::FatalError("Bed file of enhancer sequences must be provided\n On the 4th column the gene it is referring to must be specified");
    }
    unless ($main::genome) {
      &RSAT::error::FatalError("Genome version must be specified with option -genome (e.g. mm9, hg19)");
    }
    if($report_net){
      unless ($main::infile{network}) {
        &RSAT::error::FatalError("Turned on network reporting (-rep_net) but no network (-net) provided");
      }
    }
  }

  if ($main::output_dir eq "") {
    $main::output_dir = "network-interactions_".$date;
  }
  &RSAT::util::CheckOutDir($main::output_dir);

  #################################################################
  ## Test for CGI
  if ((defined($ENV{RSA_OUTPUT_CONTEXT})) &&
      (($ENV{RSA_OUTPUT_CONTEXT}eq "cgi") || ($ENV{RSA_OUTPUT_CONTEXT} eq "RSATWS"))) {
      $_ =~ s|$ENV{RSAT}/public_html/|$ENV{rsat_www}|g;
  }

  ################################################################
  ## Create sub directories
  my $out_path = $main::output_dir."/".$main::output_prefix;
  &RSAT::util::CheckOutDir($out_path."IntermediateFiles");
  &RSAT::util::CheckOutDir($out_path."ResultsFiles");

  ## Set output files names
  #my $tmp_dir = &RSAT::util::get_pub_temp();

  $basename = $out_path."IntermediateFiles/".$main::output_prefix;
  $main::used_outfile{used_regulatory_regions} = $basename."network-interactions_used_regulatory_regions_".$date.".bed";
  $main::used_outfile{used_matrixes} = $basename."network-interactions_used_matrixes_".$date.".tf" unless ( $main::matrices );
  unless ( $main::seq ){
    $main::used_outfile{used_cre_seqs} = $basename."network-interactions_used_cre_seqs_".$date.".fa";
    $main::used_outfile{used_cre_seqs_geneheader} = $basename."network-interactions_used_cre_seqs_geneheader_".$date.".fa";
  }
  $main::used_outfile{used_matrix_scan_results} = $basename."network-interactions_used_matrix-scan_results_".$date.".tsv"  unless( $main::scan );

  $basename = $out_path."ResultsFiles/".$main::output_prefix;
  $main::outfile{log} = $basename."network-interactions_log_".$date.".txt";
  $main::outfile{complete_direct_interactions} = $basename."complete_direct_interactions_".$date.".tsv";
  if($report_net){
    $main::outfile{network_intersection} = $basename."network_intersection_".$date.".tsv";
    $main::outfile{network_not_found_interactions} = $basename."network_not_found_interactions_".$date.".tsv";
    $main::outfile{network_found_interactions} = $basename."network_found_interactions_".$date.".tsv";
    $main::outfile{network_intersection_onlyTFs} = $basename."network_intersection_onlyTFs_".$date.".tsv";
  }
  $main::outfile{GRN_direct_interactions} = $basename."GRN_direct_interactions_".$date.".tsv";
  $main::outfile{GRN_indirect_interactions} = $basename."GRN_indirect_interactions_".$date.".tsv";

  #if ( $main::html == 1 );
  # html summary file
  $main::outfile{summary} = $basename."SUMMARY_".$date.".html";
  ## Archive to facilitate transfer of all the results in a zip file
  $main::outfile{archive} = $out_path."network-interactions_archive_".$date.".zip";

  &RSAT::message::Debug("Archive", $main::outfile{archive}) if ($main::verbose >= 3);

  # main error file
  $main::outfile{err_log} = $basename."_errors.txt";
  $main::err = &OpenOutputFile($main::outfile{err_log});
  &Verbose($main::err) if ($main::verbose >= 1);

  ################################################################
  if ( $html == 1 ){
    ## Taken from matrix-clustering
    ## Define the base directories for the javascripts, which are
    ## required to display logo trees, animations and dynamic tables

    if ($include_js_lib) {
  ## Note: we will need to redefine it after having parsed the
  ## arguments, since it will be relative to output directory.
  &RSAT::message::Debug("Copying javascript libraries to output directory") if ($main::verbose >= 3);
  my $js_sync_cmd = "rsync -ruptl";
  $js_sync_cmd .= " ".$ENV{RSAT}."/perl-scripts/lib/js";
  $js_sync_cmd .= " ".$output_dir;
  #&doit($js_sync_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
  &doit($js_sync_cmd, $dry, $die_on_error, $verbose, $batch, $job_prefix);
  $js_base = $output_dir."/js";
  &RSAT::message::Info("Javascript libraries copied to output directory", $js_base) if ($main::verbose >= 3);
    }  elsif (defined($ENV{RSA_OUTPUT_CONTEXT}) && ($ENV{RSA_OUTPUT_CONTEXT} eq "cgi")) {
  $js_base = $ENV{rsat_www}."/lib/js";
    } else {
  ## NOTE from JvH to Jaime: This solution does not allow to see the
  ## result on another computer than the RSAT server on which
  ## matrix-clustering ran.
  $js_base = $ENV{RSAT}."/perl-scripts/lib/js";
    }
    $d3_base= &RSAT::util::RelativePath($main::outfile{summary}, $js_base."/d3.v3.min.js");
    $d3_venn_base= &RSAT::util::RelativePath($main::outfile{summary}, $js_base."/venn.js-master/venn.js");
    $jquery_base = &RSAT::util::RelativePath($main::outfile{summary}, $js_base."/DataTables-1.10.4/media/js/jquery.js");
    $datatable_base = &RSAT::util::RelativePath($main::outfile{summary}, $js_base."/DataTables-1.10.4/media/js/jquery.dataTables.min.js");
    $datatable_css_base = &RSAT::util::RelativePath($main::outfile{summary}, $js_base."/DataTables-1.10.4/media/css/jquery.dataTables.min.css");

    ################################################################
    ## Copy the section icons in the results folder
    ################################################################
    &RSAT::message::Debug("Copying result sections icons to output directory") if ($main::verbose >= 3);
    my $icons_path = $ENV{RSAT}."/public_html/images/program_icons/network-interactions_icons";
    my $icon_sync_cmd = "rsync -ruptl";
    $icon_sync_cmd .= " ".$icons_path;
    $icon_sync_cmd .= " ".$main::output_dir;
    &doit($icon_sync_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);

    $icons{comparison} = &RSAT::util::RelativePath($main::outfile{summary}, $main::output_dir."/network-interactions_icons/comparison.png");
    $icons{indirect} = &RSAT::util::RelativePath($main::outfile{summary}, $main::output_dir."/network-interactions_icons/indirect.png");
    $icons{network} = &RSAT::util::RelativePath($main::outfile{summary}, $main::output_dir."/network-interactions_icons/network.png");

  } # if html

  ################################################################
  ## Open logfile

  $log = &OpenOutputFile($main::outfile{log});
  &Verbose($log) if ($main::verbose >= 1);

  ################################################################

  # Decide which transfac files to use
  # CODE: add all from organism option

  if($main::databases eq ""){ # default option
    #print("Entered default option of dbs\n");
    $matfiles_path[0] = $ENV{RSAT}."/public_html/motif_databases/JASPAR/Jaspar_2020/nonredundant/JASPAR2020_CORE_vertebrates_non-redundant_pfms.tf";
    #$matfiles_path[0] = $ENV{RSAT}."/public_html/motif_databases/JASPAR/Jaspar_2018/nonredundant/JASPAR2018_CORE_vertebrates_non-redundant_pfms_transfac.tf";
    #print($matfiles_path[0]."\n");
  } else {
    if($main::databases eq "all"){ # CODE: falta anadir algo que soporte que meta los nombres de dbs como sea
      @dbs = qw(ENCODE epigram Hocomoco_human Hocomoco_mouse Homer hPDI HT_Selex Jolma_2013 Jolma_2015 NCAP-SELEX CAP-SELEX RSAT jaspar_core_redundant_all cisBP Yeastract DrosophilaTFs);
    } else { @dbs = split(/,|;/, $main::databases) }

    # retrieve paths to databases from db_matrix_files.tab
    open(my $dbs_file, "<", $ENV{RSAT}."/public_html/motif_databases/db_matrix_files.tab") or die "Cannot open file $!";
    $i = 0;
    while(my $row = <$dbs_file>){
      chomp($row);
      next if( $row =~ /^;/);
      next if( $row =~ /^#/);

      foreach my $db (@dbs){
        if( $row =~ /^$db/){
          @fields = split(/\t/,$row);
          $matfiles_path[$i++] = $ENV{RSAT}."/public_html/motif_databases/".$fields[2];
          #print(" matrix file path number ".$c." : ".$matfiles_path[$c]."\n");
          #$c++;
        }
      }
    }
    close $dbs_file;
  }
  &messageInfoAndLog("Number of motif databases = ".scalar(@matfiles_path)."\n");


  ################################################################
  ####################################### Save Input Data

  unless ($main::onlymats){
    # Rewrite to bedfile without NAs or if no gene is refered to
    # Also, save the genes refered to in bed file of enhancers
    #        I want to preserve the order
    $val = 0; # this value is extremely important, since a value corresponds to only one gene and it most be ordered to for search
    $i = 1;

    my ($enhancer, $enh_dir) = &OpenInputFile($main::infile{cres});
    &messageInfoAndLog("# Reading BED file: ".$main::infile{cres}."\n");

    $new_enhancer = &OpenOutputFile($main::used_outfile{used_regulatory_regions});
    print $new_enhancer "# Bed file used for cis-regulatory regions\n";

    while(my $enh_row = <$enhancer>){
      chomp($enh_row);
      next unless ($enh_row =~ /\S/); ## Skip empty rows
      next if ($enh_row =~ /^;/); ## Skip comment rows
      next if ($enh_row =~ /^#/); ## Skip header rows

      if($enh_row =~ /^chr\w{1,2}\t\d+\t\d+\t(\w+).*/){
        if($1 ne "NA"){

            # write to new bed file and save order of genes
            print $new_enhancer $enh_row."\n";
            push(@genes_reg,$1);

            # add values in sequential order
            # gene is key, value is a number
            if( !$val ){
              $val++; # gene counts start at one
              $nonRep_genes_reg{$1} = $val++;
            } elsif(!$nonRep_genes_reg{$1}) {
              $nonRep_genes_reg{$1} = $val++;
            }

        }
      } else {
        print $log "\tGene name on fourth column missing at line: ".$i."\n"
        #&RSAT::error::FatalError("Error: not a fourth column of genes in file ".$main::cres."\n");
        #exit(1);
      }
      $i++;
    }

    close $enhancer;
    close $new_enhancer;

    &RSAT::error::FatalError("Error: not a single gene name was specified on bed file: ".$main::infile{cres}."\n") unless (scalar(@genes_reg) > 0);
    #print ("# of genes regulated = ".scalar(@genes_reg)."\n");
    #print ("# of nonRep genes regulated = ".scalar(keys %nonRep_genes_reg)."\n");
  }

  #############################################################
  # Save non-repited TFs
  $i = 0;
  my $a = 0, $b = 0;

  my ($TF, $TF_dir) = &OpenInputFile($main::infile{TFs});
  &messageInfoAndLog("# Reading TFs list file: ".$main::infile{TFs}."\n");

  while( my $row = <$TF> ){
    next unless ($row =~ /\S/); ## Skip empty rows
    next if ($row =~ /^;/); ## Skip comment rows
    next if ($row =~ /^#/); ## Skip header rows
    chomp($row);

    if (!$main::onlymats){
      # distinguish if their sequences were reported
      if ( $nonRep_genes_reg{$row} ){
        #print("Tf in nonRep_genes_reg\n");
        # add values in sequential order, beginning in 1
        if( !$i ){
          $i++; # start at 1
          $nonRepTFs{$row} = $i++;
        } elsif(!$nonRepTFs{$row}) {
          $nonRepTFs{$row} = $i++;
        }

        # list of TFs with no coordinates
        if(!$b){
          $report_tfs_RegSeq = $row;
          $b++;
        } else {
          $report_tfs_RegSeq .= ",".$row;
        }

      } else {
        # list of TFs with no coordinates
        if(!$a){
          $report_tfs_noRegSeq = $row;
          $a++;
        } else {
          $report_tfs_noRegSeq .= ",".$row;
        }
      }
    } else {
      # save all TFs
      $nonRepTFs{$row} = ++$i;
    }

  }
  #print("# of nonRepTFs = ".%nonRepTFs."\n");
  close $TF;

  ## Check input TFs
  @nonRepTFs_k = keys %nonRepTFs;
  &RSAT::error::FatalError("Error: not a single TF was specified on: ".$main::infile{TFs}."\n") unless (scalar(@nonRepTFs_k) > 0);

  if ($main::onlymats){

    # get requested matrixes
    &runRetrieveMatrix((\@matfiles_path, \@nonRepTFs_k, $dry, $die_on_error, $verbose, $batch, $job_prefix));
    # tell which file has the matrixes
    &RSAT::message::Info("File with matrixes from found TFs ready at :".$main::used_outfile{used_matrixes}."\n");

    # exit program
    &messageInfoAndLog("End of program.\n");

    my $exec_time = &RSAT::util::ReportExecutionTime($start_time); ## This has to be exectuted by all scripts

    print $log $exec_time;
    close $log;

    exit(0);
  }

  # notice user about the lack of regulatory seqences
  &messageInfoAndLog("Seems like you didn't reported the regulatory sequences for the following TFs : ".$report_tfs_noRegSeq."\n") unless ($report_tfs_noRegSeq eq "");
  if( $report_net){
      &messageInfoAndLog("The program will take into account the following TFs for further network comparision : ".$report_tfs_RegSeq."\n");
  }

  #############################################################
  # Save input network and create input GRN
  $flag = 0;
  $ngenes = scalar(keys %nonRep_genes_reg)-1;
  $ntfs = scalar(@nonRepTFs_k) -1;

  if($report_net){

    #initialize matrixes to zeros
    # input all-genes net
    #print($val."\n");
    for $i (0..$ngenes){
        for my $j (0..$ngenes){
  	  $net_old_allgenes[$i][$j] = 0;
        }
    }
    # input only-TFs net
    for $i (0..$ntfs){
        for my $j (0..$ntfs){
  	  $net_old_onlyTFs[$i][$j] = 0;
        }
    }

    $i = 0;
    # Save input network interactions
    my ($net, $net_dir) = &OpenInputFile($main::infile{network});
    &messageInfoAndLog("Reading input network file: ".$main::infile{network}."\n");
    my $input_net_nrows = 0;
    my $input_int_count = 0;

    while (my $net_row = <$net>){
        chomp($net_row);
        next unless ($net_row =~ /\S/); ## Skip empty rows
        next if ($net_row =~ /^;/); ## Skip comment rows
        next if ($net_row =~ /^#/); ## Skip header rows
        $input_net_nrows++;

        @fields = split(/\t|,/, $net_row);

        # make list of genes in network with regulatory sequences reported and not reported
        if($nonRep_genes_reg{$fields[0]}){
          $RegSeq{$fields[0]} = $z++;
      	  $flag++;
        } else {
      	  $noRegSeq{$fields[0]} = $z++;
        }
        if($nonRep_genes_reg{$fields[1]}){
      	  $RegSeq{$fields[1]} = $z++;
      	  $flag++;
        } else {
      	  $noRegSeq{$fields[1]} = $z++;
        }

        # Note: In the network comparison report, only interactions in which both genes had their seq reported will be taken into account

        # if both genes have a reported regulatory sequence
        if( $flag == 2 ){
          # construct network of all genes
          $net_old_allgenes[ $nonRep_genes_reg{$fields[0]}-1 ][ $nonRep_genes_reg{$fields[1]}-1 ] = 1;
          # if the interaction is between TFs, add this one to the input's only-TFs network
          if( $nonRepTFs{$fields[0]} && $nonRepTFs{$fields[1]} ){
            $net_old_onlyTFs[ $nonRepTFs{$fields[0]}-1 ][ $nonRepTFs{$fields[1]}-1 ] = 1;
          }
          # count interactions
          $input_int_count++;
        }
        # reinitialize value
        $flag =0;

      } # while
      close $net;

      # message if sequences of any genes in network were not reported
      if(%noRegSeq){
        $a = 0;
        foreach my $gene (sort keys %noRegSeq){
          if(!$a){
            $noRegSeq_reporting = $gene;
            $a++;
          } else {
            $noRegSeq_reporting .= ",".$gene;
          }
        }
        $a = 0;
        foreach my $gene (sort keys %RegSeq){
          if(!$a){
            $RegSeq_reporting = $gene;
            $a++;
          } else {
            $RegSeq_reporting .= ",".$gene;
          }
        }

        # Tell user which regulatory sequences are lacking and which genes are used in the program
        &messageInfoAndLog("Seems like you didn't reported the regulatory sequences for the following genes in your input network: ".$noRegSeq_reporting."\n");
        &messageInfoAndLog("The program will use the rest of the genes for further network comparison: ".$RegSeq_reporting."\n");
        # Tell user in the html summary
        $status{genes_no_reg_seq} = $noRegSeq_reporting;

      } # Info

      ## Update run status
      if ($input_int_count == 0){
        $status{empty_input_net} = 1;
      } elsif ($input_int_count < $input_net_nrows){
        $status{reduced_input_net} = 1;
      }

  } # report_net

  ################################################################
  ####################################### RSAT processing
  &messageInfoAndLog("Initiating RSAT tools processing ...\n");

  unless( $main::scan ){ ## unless scan results are provided

    # Create the file with all the matrixes to use
    #   retrieve-matrix foreach database foreach TF
    unless ( $main::matrices ){
      # get requested matrixes
      &runRetrieveMatrix(\@matfiles_path, \@nonRepTFs_k, $dry, $die_on_error, $verbose, $batch, $job_prefix);
    }

    # Retrieve sequences of regulatory elements
    unless( $main::seq ){
      &messageInfoAndLog("Retrieving regulatory sequences ...\n");
      $cmd = &RSAT::server::GetProgramPath("fetch-sequences") . " -i ".$main::used_outfile{used_regulatory_regions}." -genome ".$main::genome." -v 1 -header_format galaxy -o ".$main::used_outfile{used_cre_seqs}."";
      &doit($cmd, $dry, $die_on_error, $verbose, $batch, $job_prefix);
      &messageInfoAndLog("\tDone!\n");

      # Add regulated genes names to fasta of regulatory sequences
      #     Im using 'external_id' not ensembl_id
      open( $fasta, "<", $main::used_outfile{used_cre_seqs} ) or die "Cannot open file $!";
      open( $new_fasta, ">", $main::used_outfile{used_cre_seqs_geneheader} ) or die "Cannot open file $!";

      $i = 0;
      while(my $fa_row = <$fasta> ){
        chomp($fa_row);
        if($fa_row =~ /^>/){
          print $new_fasta $fa_row."_*_".$genes_reg[$i++]."\n";# this must be at the identifier line e.g.: >seq1_*_$genes_reg[$i++]
                                                               #  only so that matrix-scan takes this whole name as seq_id
        } else {
          print $new_fasta $fa_row."\n";
        }
      }
      close $fasta;
      close $new_fasta;
    }

    # Search motifs in all regulatory sequences
    &messageInfoAndLog("matrix-scan running ...\n");
    $cmd = &RSAT::server::GetProgramPath( "matrix-scan")." -quick -v 1 -matrix_format transfac -m ".$main::used_outfile{used_matrixes}." -bginput -markov 1";
    $cmd.= " -i ".$main::used_outfile{used_cre_seqs_geneheader}." -o ".$main::used_outfile{used_matrix_scan_results}."";
    $cmd.= " -id_as_name -lth score ".$main::score;
    $cmd.= " -uth pval ".$main::pval if ( $main::pval ne 'NA' );
    &doit($cmd, $dry, $die_on_error, $verbose, $batch, $job_prefix);
    &messageInfoAndLog("\tDone!\n");

  } # unless scan

  &messageInfoAndLog("RSAT tools processing ready.\n");

  ################################################################
  ## Constuct networks and save matrix-scan details of interactions

  for $i (0..$ngenes){
    for my $j (0..$ngenes){
      $net_new_allgenes[$i][$j] = 0;
    }
  }
  # input only-TFs net
  for $i (0..$ntfs){
    for my $j (0..$ntfs){
      $net_new_onlyTFs[$i][$j] = 0;
    }
    # initialize to zeros
    $deadend[$i] = 0;
  }

  &messageInfoAndLog("Network computation running ...\n");
  # Create matrixes of networks:
  open($matrixscan_re, "<", $main::used_outfile{used_matrix_scan_results} ) or die "Cannot open file $!";

  $a = 1; # this value is unimportant, however it must start a 1 since it is a hash
  while(my $results_row = <$matrixscan_re>){
    chomp($results_row);
    next unless ($results_row =~ /\S/); ## Skip empty rows
    next if ($results_row =~ /^;/); ## Skip comment rows
    next if ($results_row =~ /^#/); ## Skip header rows

    @fields = split(/\t/,$results_row); # $fields[2] is the TF
    @seq_id = split(/_/,$fields[0]); # >genome_chr_start_end_+_genename
    @gene_name = split(/_\*_/,$fields[0]);

    $interaction_completenet = 1; # matrix-scan found interactions

    if($nonRep_genes_reg{$gene_name[1]} && $nonRep_genes_reg{$fields[2]}){ # no error
      if( !$net_new_allgenes[ $nonRep_genes_reg{$fields[2]}-1 ][ $nonRep_genes_reg{$gene_name[1]}-1 ] ){

          # set interaction in directed-network
          $net_new_allgenes[ $nonRep_genes_reg{$fields[2]}-1 ][ $nonRep_genes_reg{$gene_name[1]}-1] = 1;

          # if it is a TF-TF interaction, save it on the GRN
          if ($nonRepTFs{$fields[2]} && $nonRepTFs{$gene_name[1]}){
            $net_new_onlyTFs[ $nonRepTFs{$fields[2]}-1 ][ $nonRepTFs{$gene_name[1]}-1 ] = 1;
          }
      }
      $interaction_details{$fields[2]}{$gene_name[1]}{$seq_id[1].":".$seq_id[2]."-".$seq_id[3]}{$fields[3]."_".$fields[4]."_".$fields[5]}{$fields[7]} = $a++;

    }

  } #  while
  close $matrixscan_re;

  #&RSAT::error::FatalError("Error: No interactions found \n") unless ($interaction_completenet);

  ########################################################################
  ################### Comparisons and write-to-file reporting
  my %nonRep_genes_reg_inv;
  my $rowtofile;
  my %interaction_count = ();
  $interaction_count{complete} = 0;

  &messageInfoAndLog("Also creating output files ...\n");
  ## Comparison of complete gene network
  $interaction_gene_row = &OpenOutputFile($main::outfile{complete_direct_interactions});
  &Verbose($interaction_gene_row) if ($main::verbose >= 1);
  print $interaction_gene_row "# Complete Network\n#TF\tGene\tCoordinates\tPositions\tScores\n"; # header
  $tables_str{complete_direct_interactions} = "TF\tGene\tCoordinates\tPositions\tScores\n";

  if( $report_net ){
    $intersection = &OpenOutputFile($main::outfile{network_intersection});
    &Verbose($intersection) if ($main::verbose >= 1);
    print $intersection "# Interactions in common from:\n#\t".$main::infile{network}." and ".$main::outfile{complete_direct_interactions}."\n#TFx\tGeney\tCoordinates\tPositions\tScores\n"; # header
    $tables_str{intersection} = "TFx\tGeney\tCoordinates\tPositions\tScores\n";

    $not_found = &OpenOutputFile($main::outfile{network_not_found_interactions});
    &Verbose($not_found) if ($main::verbose >= 1);
    print $not_found "# Interactions in:\t".$main::infile{network}." not found in ".$main::outfile{complete_direct_interactions}."\n#Genex\tGeney\n"; # header
    $tables_str{not_found} = "Genex\tGeney\n";

    $found = &OpenOutputFile($main::outfile{network_found_interactions});
    &Verbose($found) if ($main::verbose >= 1);
    print $found "# Newly found interactions in:\t".$main::outfile{complete_direct_interactions}." not found in ".$main::infile{network}."\n#TFx\tGeney\tCoordinates\tPositions\tScores\n"; # header
    $tables_str{found} = "TFx\tGeney\tCoordinates\tPositions\tScores\n";

    #$intersectionTFs = &OpenOutputFile($main::outfile{network_intersection_only_TFs});
    #&Verbose($intersectionTFs) if ($main::verbose >= 1);
    #print $intersectionTFs "# Interactions in common from:\n#\t".$main::infile{network}." and ".$main::outfile{GRN_direct_interactions}."\n#TFx\tTFy\tCoordinates\tPositions\tScores\n"; # header
    #$tables_str{intersection_onlyTFs} = "TFx\tTFy\tCoordinates\tPositions\tScores\n";

    $interaction_count{intersection} = 0;
    $interaction_count{not_found} = 0;
    $interaction_count{found} = 0;
  }

  %nonRep_genes_reg_inv = reverse %nonRep_genes_reg;

  for $i (0..$ngenes){
    for my $j (0..$ngenes){

        # write interaction to file according to the case: intersection, not_found or newly found
        if( $net_new_allgenes[$i][$j] ){

          $rowtofile = &writeRow( $nonRep_genes_reg_inv{ $i+1 }, $nonRep_genes_reg_inv{ $j+1 }, \%{ $interaction_details{$nonRep_genes_reg_inv{ $i+1 }}{$nonRep_genes_reg_inv{ $j+1 }} } );
          $tables_str{complete_direct_interactions} .= $rowtofile; # row to table string
          print $interaction_gene_row $rowtofile; # row to output tsv file
          $interaction_count{complete}++;

          if( $report_net ){
            if( $net_old_allgenes[$i][$j] ){
              # overlap (only interactions, not lack of them)
              print $intersection $rowtofile;
              $tables_str{intersection} .= $rowtofile;
              $interaction_count{intersection}++;

              #onlyTFs overlap
            } else {
              # newly found
              print $found $rowtofile;
              $tables_str{found} .= $rowtofile;
              $interaction_count{found}++;
            }
          } # report_net

        } elsif( $report_net && $net_old_allgenes[$i][$j] ){
            # not_found (no details)
            print $not_found $nonRep_genes_reg_inv{ $i+1 }."\t".$nonRep_genes_reg_inv{ $j+1 }."\n";
            $tables_str{not_found} .= $nonRep_genes_reg_inv{ $i+1 }."\t".$nonRep_genes_reg_inv{ $j+1 }."\n";
            $interaction_count{not_found}++;
        }


    } # for
  } # for

  ## Run status
  if ($report_net){
    $status{empty_intersection} = 1 if ($interaction_count{intersection} == 0);
  }

  ## Comparison of GRNs ?


  ################################################################
  ## Report all direct interactions within TFs

  open( $direct, ">", $main::outfile{GRN_direct_interactions} ) or die "Cannot open file $!";
  &Verbose($direct) if ($main::verbose >= 1);
  print $direct "#TFx(Regulator)\tTFy(Regulated)\tCoordinates\tPositions\tScore\n"; # header
  $tables_str{only_TFs} = "TFx\tTFy\tCoordinates\tPositions\tScore\n";
  $interaction_count{only_TFs} = 0;

  %nonRepTFs_inv = reverse %nonRepTFs;
  $count = 0;

  for my $i (0..$ntfs){
    for my $j (0..$ntfs){

      # write to file direct interactions
      if( $net_new_onlyTFs[$i][$j] ){

        $rowtofile = &writeRow( $nonRepTFs_inv{ $i+1 }, $nonRepTFs_inv{ $j+1 }, \%{ $interaction_details{$nonRepTFs_inv{ $i+1 }}{$nonRepTFs_inv{ $j+1 }} } );
        print $direct $rowtofile;
        $tables_str{only_TFs} .= $rowtofile;
        $interaction_count{only_TFs}++;

      } else {
        # add node to list of deadend nodes
        if($count == $ntfs){
          $deadend[$i] = 1;
        }
        $count++;
      }

    } # for
  } # for

  ################################################################
  ### Report interactions counts

  my $interation_count_table = "";
  $interation_count_table .= "Network\tInteractions-count\n";
  while (my ($key,$value) = each %interaction_count) {
      $interation_count_table .= $key."\t".$value."\n";
  }
  &messageInfoAndLog($interation_count_table);

  ################################################################
  ##  Report all indirect interactions, i.e., direct interactions
  ##    composed of three nodes
  # E.g.:
  #   IN GRN_direct_interactions.tsv:
  # TF1 TF2
  # TF2 TF3
  # TF1 TF3
  #   IN GRN_indirect_interactions.tsv_:
  # TF1 ==> TF2 ==> TF3
  # TF2 ==> TF3
  # TF1 ==> TF3
  # Interpretation: TF1 regulates directly and indirectly TF3.

  $path = "\n"; # string to concat paths of 3 nodes
  my $details1 = "";
  my $details2 = "";
  my $coo = "";

  ## Report all paths of three (instead of cases of direct and indirect interactions simoultaneously)
  open( my $indirect, ">", $main::outfile{GRN_indirect_interactions}) or die "Cannot open file $!";
  &Verbose($indirect) if ($main::verbose >= 1);
  print $indirect "# Report of 3-nodes direct interactions\n# cases of no direct interactions are specified.\n#node1 ==> node2 ==> node3\n\n"; #header
  $tables_str{indirect} = "TFx\tTFy\tCoordinates\tPositions\tScore\n";

  for my $row (0..$ntfs){
    #$path = "";
    # check if the node is a deadend
    if ( !$deadend[$row] ){
      for my $con1 (0..$ntfs){
        # find direct connections
        if( $net_new_onlyTFs[$row][$con1] ){

          $details1 = &writeRow( $nonRepTFs_inv{ $row+1 }, $nonRepTFs_inv{ $con1+1 }, \%{ $interaction_details{$nonRepTFs_inv{ $row+1 }}{$nonRepTFs_inv{ $con1+1 }} } );

          # construct path
          $path .= $nonRepTFs_inv{ $row+1 }."\t==>\t".$nonRepTFs_inv{ $con1+1 };
          # report if its a connection to itself
          if ($row == $con1){
            print $indirect $path."\n";
            print $indirect $details1."\n";
          } elsif ( !$deadend[$con1] ){

            for my $con2 (0..$ntfs){
              # skip it its a connection to itself
              if( $con1 == $con2){ next; }
              if( $net_new_onlyTFs[$con1][$con2] ){

                $details2 = &writeRow( $nonRepTFs_inv{ $con1+1 }, $nonRepTFs_inv{ $con2+1 }, \%{ $interaction_details{$nonRepTFs_inv{ $con1+1 }}{$nonRepTFs_inv{ $con2+1 }} } );

                # report 3-node connection to file
                $path .= "\t==>\t".$nonRepTFs_inv{ $con2+1 };
                print $indirect $path."\n";
                print $indirect $details1."==>\n".$details2."\n";
                $tables_str{indirect} .= $path."\n".$details1."".$details2;
                # set the 2-node connection for more 3-node connections
                $path = "\n".$nonRepTFs_inv{ $row+1 }."\t==>\t".$nonRepTFs_inv{ $con1+1 };
              } # direct connection 2 found
            }

          } else {
            # if it was a dead end report 2-node connection
            print $indirect "".$path."\n";
            print $indirect $details1."\n";
          }
          $path = "\n";

        } # direct connection 1 found
      } # for connection 1
    } else {
      print $indirect "".$nonRepTFs_inv{ $row+1 }." has no targets.\n";
      $path = "\n";
    }

  } # for row
  &messageInfoAndLog("\tDone.\n");

  ################################################################
  ## here is what was in sub &close_and_quit()
  ## Close output file and quit

  &messageInfoAndLog("Closing output files ... \n");


  ## Report execution time
  my $exec_time = &RSAT::util::ReportExecutionTime($start_time); ## This has to be exectuted by all scripts

  if ($main::verbose >= 1) { ## only report exec time if verbosity is specified
      while (my ($key,$value) = each %main::outfile) {
          print $interaction_gene_row $exec_time;
          if( $report_net ){
            print $intersection $exec_time;
            print $found $exec_time;
            print $not_found $exec_time;
          }
          print $direct $exec_time;
          print $indirect $exec_time;
      }

      if ($main::verbose > 1){
        foreach my $key ( sort keys %main::outfile) {
          &RSAT::message::TimeWarn("Results files", $main::outfile{$key});
        }
      }
  }

  close $interaction_gene_row;
  if( $report_net ){
    close $intersection;
    close $found;
    close $not_found;
  }
  close $direct;
  close $indirect;
  &messageInfoAndLog("\tDone. \n");

  if ($main::html == 1) {
    &messageInfoAndLog("Creating HTML summary ... \n");

    &messageInfoAndLog("Converting tab-delimited tables to HTML") if ($main::verbose >= 2);
    #&ConvertTabToHTML(@tab_to_convert);
    # Convert tsv tables to html
    our %tables_html = ();
    foreach my $tsv_table ( keys %tables_str ) {
      if($tsv_table eq "not_found"){
        $tables_html{$tsv_table} = &tableToHTML( $tables_str{$tsv_table}, "", 1, "", 1 );
      } elsif($tsv_table eq "indirect") {
        $tables_html{$tsv_table} = &indirectTableToHTML($tables_str{$tsv_table});
      } else {
        $tables_html{$tsv_table} = &tableToHTML( $tables_str{$tsv_table}, "", 1 );
      }
    }

    #&makeZip();
    ################################################################
    ## Check output directories and define file names
    #&set_output_file_names();

    ## Initialize HTML summary
    &OpenSynthesis(); #if ($main::param{progressive_synthesis}); ## Already open the HTML report summary, for the Web site
    #if ($root_matrices_flag == 1) {
    #    $to_delete{'summary'} = $main::outfile{summary};
    #}

    ################################################################
    ## Make output summary html file

    ################################################################
    ## Creates the website
    &Synthesis();

    ################################################################
    ## Create an archive with all result files
    &Archive(1);
  }
  #print $tables_str{indirect}."\n";


  &messageInfoAndLog("End of program.\n");

  print $log $exec_time;
  close $log;

  exit(0);

} # main




################################################################
################### SUBROUTINE DEFINITION ######################
################################################################

################################################################
## Display full help message
sub PrintHelp {
  system "pod2text -c $0";
  exit()
}

## Display short help message
sub PrintOptions {
  &PrintHelp();
}

################################################################
## Read arguments
sub ReadArguments {

    my $arg;

    my @arguments = @ARGV; ## create a copy to shift, because we need ARGV to report command line in &Verbose()

    while (scalar(@arguments) ) {
	$arg = shift (@arguments);

=pod

=head1 OPTIONS

=over 4

=item B<-v #>

Level of verbosity.

=cut

	if ($arg eq "-v") {
	    if (&IsNatural($arguments[0])) {
		$main::verbose = shift(@arguments);
	    } else {
		$main::verbose = 1;
	    }

	    ## Help message
=pod

=item B<-h>

Display full help message.

=cut

	} elsif ($arg eq "-h") {
	    &PrintHelp();
	    ## Dry run

=pod

=item B<-help>

Same as -h.

=cut

	} elsif ($arg eq "-help") {
	    &PrintOptions();

	    ## TFs input file

=pod

=item B<-tfs TFs_infile>

Mandaroty.
File containing a list of TFs to be analysed
One-column input file with list of TFs in network.

=cut

	}elsif ($arg eq "-tfs") {
	    $main::infile{TFs} = shift(@arguments);

	    ## Regulatory sequences file

=pod

=item B<-cre cre_infile>

Mandaroty.
Bed file with of regulatory sequences per gene in network.
Each sequence must refer to its regulated-gene on the 4th column.

=cut

	} elsif ($arg eq "-cre") {
	    $main::infile{cres} = shift(@arguments);

	    ## Genome version

=pod

=item B<-genome genome_version>

Mandaroty.
Working genome version.

=cut

	} elsif ($arg eq "-genome") {
	    $main::genome = shift(@arguments);

=pod

=item B<-db databases>

Database(s) to use separated by commas.

=cut
	} elsif ($arg eq "-db") {
	    $main::databases = shift(@arguments);

	    ## Network file

=pod


=item B<-net network_infile>

Mandaroty if -report_net is specified.
The network must be a two-column file with each row containing a single interaction.

=cut
	} elsif ($arg eq "-net") {
	    $main::infile{network} = shift(@arguments);
	    $main::report_net = 1;

	    ## Report Network
=pod

=item B<-report_net>

Report network,
i.e., differences and overlap between the input network and the new network are outputted

=cut

	} elsif ($arg eq "-report_net") {
	    $main::report_net = 1;

	    ## Title

=pod

=item B<-title title>

Title displayed on top of the report page.

=cut
	} elsif ($arg eq "-title") {
	    $main::title = shift(@arguments);

      ## HTML summary page

=pod

=item B<-html>

Output html SUMMARY file

=cut
      } elsif ($arg eq "-html") {
      $main::html = 1;

      ## Date

=pod

=item B<-date date>

Date used as suffix for output files.

=cut
     } elsif ($arg eq "-date") {
      $main::date = shift(@arguments);

      ## Input sequences
=pod

=item B<-seq input_sequences>

Fasta file with of regulatory sequences per gene in network.
Each sequence must refer to its regulated-gene on its header by tag.
Regulatory sequences of TFs in the network should be incorporated.

=cut
	} elsif ($arg eq "-seq") {
	    $main::used_outfile{used_cre_seqs_geneheader} = shift(@arguments);
      $main::seq = 1;

	    ## Input matrices
=pod

=item B<-m matrices-file>

File of matrices in transfac fomat including the TF name on the
ID field.

=cut
	} elsif ($arg eq "-m") {
	    $main::used_outfile{used_matrixes} = shift(@arguments);
      $main::matrices = 1;

	    ## matrix-scan result
=pod

=item B<-scan matrix-scan-results-file>

File resulting from matrix-scan on regulatory sequences
for the TFs' matrices of interest.

=cut
	} elsif ($arg eq "-scan") {
	    $main::used_outfile{used_matrix_scan_results} = shift(@arguments);
      $main::scan = 1;

      ## Score
=pod

=item B<-score #>

Score lower threshold to run matrix-scan with, default is 5.

=cut
	} elsif ($arg eq "-score") {
	    $main::score = shift(@arguments);
      unless ( &IsNatural($main::score) ){
        &RSAT::error::FatalError("Score should be a natural number or 0.");
      }

      ## Pval
=pod

=item B<-pval #>

P-value upper threshold to run matrix-scan with.

=cut
	} elsif ($arg eq "-pval") {
	    $main::pval = shift(@arguments);

	    ## only retrieve matrixes
=pod

=item B<-onlymatrixes>

Ignore code and only retrieve matrixes from a list of TFs.
This only works if the given name for a TF is reported in the selected matrix databases.

=cut
} elsif ($arg eq "-onlymatrixes") {
	    $main::onlymats = 1;

	    ## Archive_format
=pod

=item B<-archive_format [zip|tar|tgz]>

Archive format. Use also -html

=cut
  } elsif ($arg eq "-archive_format") {
      $main::archive_format = shift(@arguments);
      unless($main::archive_format eq "zip" | $main::archive_format eq "tar" | $main::archive_format eq "tgz"){
          &RSAT::error::FatalError("-archive_format not recognized, available options are zip, tar or tgz.")
      }

	    ##Output dir

=pod

=item B<-o output_prefix>

Prefix for the output files.

=cut
  } elsif ($arg eq "-o") {
      $main::output_prefix = &trim(shift(@arguments))."_";
      #$main::outfile{prefix} = shift(@arguments);


	    ##Output dir

=pod

=item B<-outdir output_dir>

Output dir

=cut

	} elsif ($arg eq "-outdir") {
	    $main::output_dir = &trim(shift(@arguments));
	    $main::output_dir =~ s|\s+||g;
	}
	else {
	    &FatalError(join("\t", "Invalid option", $arg));
	}
    } # while

=pod

=back

=cut

} # sub ReadArguments


################################################################
## Verbose message
sub Verbose {
    my($out) = @_;

    print $out "; network-interactions ";
    &PrintArguments($out);
    #printf $out "; %-22s\t%s\n", "Program version", $program_version;
    if (%main::infile) {
        print $out "; Input files\n";
        while (my ($key,$value) = each %main::infile) {
            printf $out ";\t%-13s\t%s\n", $key, $value;
        }
    }
    if (%main::outfile) {
        print $out "; Results files\n";
        while (my ($key,$value) = each %main::outfile) {
            printf $out ";\t%-13s\t%s\n", $key, $value;
        }
    }
    if (%main::used_outfile) {
        print $out "; Intermediate files\n";
        while (my ($key,$value) = each %main::used_outfile) {
            printf $out ";\t%-13s\t%s\n", $key, $value;
        }
    }
}


################################################################
## Obtain list of the accesions from specified TFs to call retrieve-matrix on
sub retrieveACsfromTFs {
    my ($database, @TFnames) = @_;

    # Check in which field the TF name appears
    my $nameinAC = 0; # boolean to check if TFname is in AC field or ID
    my @cols; # list of elementes in field AC
    my $retrievingACs = ""; # final "list" with all AC's from the TFnames required

    open( my $db, "<", $database) or die "Cannot open file $!";
    while(my $db_row = <$db>){
        chomp($db_row);

        next unless($db_row =~ /^AC/ || $db_row =~ /^ID/);
        if( $db_row =~ /^AC\s+[^MA{0,1}\d{4,5}(_\d){0,1}(\.\d+){0,1}]/){ # si encuentra algo distinto de MA..
            $nameinAC = 1;
            last;
        } elsif( $db_row =~ /^ID\s+[^MA{0,1}\d{4,5}(_\d){0,1}(\.\d+){0,1}]/){
            $nameinAC = 0;
            last;
        } # else, no TFname provided
    } #while
    close $db;

    # Generate array of ACs
    open( $db, "<", $database) or die "Cannot open file $!";

    while(my $db_row = <$db>){ # does this continues from the line before or does it starts over again
        chomp($db_row);
        next unless($db_row =~ /^AC/ || $db_row =~ /^ID/);

        if( $db_row =~ /^AC/){
            @cols = split(/\s+/,$db_row); # save AC for each TF
        }
    #    if( $nameinAC ){
    #      next unless($db_row =~ /^AC/);
    #    } else {
    #      next unless($db_row =~ /^ID/);
    #    }
#
#        foreach my $name (@TFnames){
#          if( $db_row =~ /.*$name.*/){
#            $retrievingACs .= $cols[1].",";
#          }
#        }
        foreach my $name (@TFnames){
            if( $db_row =~ /.*$name.*/){
              if( !$nameinAC && $db_row =~ /^ID/){ # if TF name is found in ID field
                $retrievingACs .= $cols[1].",";
              } elsif( $nameinAC && $db_row =~ /^AC/){ # if TF name is found in AC field
                $retrievingACs .= $cols[1].",";
              }
            } # if
        } # foreach
    } # while
    close $db;

    return $retrievingACs;
} # sub

## Compose row of interaction with details to write to files
sub writeRow {
  my ( $TF, $target, $interaction_details ) = @_;
  my ($rowtofile, $pos, $scores, $i);
  $rowtofile = "";

  foreach my $coordinates ( keys %{ $interaction_details }){
    # report direct interaction TFx Geney
    $rowtofile .= $TF."\t".$target."\t".$coordinates;  #    TFx (regulates) Genex (in) Coordinates

    $pos = "";
    $scores = "";
    foreach my $positions ( keys %{ $interaction_details->{$coordinates} } ){
      if ($pos eq ""){
        $pos = $positions."";
        $i=0;
        # annotate each score assignated to the same positions
        foreach my $s ( keys %{ $interaction_details->{$coordinates}->{$positions} } ) {
          if(!$i){
            $scores = $s."";
            $i++;
          } else {
            $scores .= "_".$s;
          }
        } # foreach score
      } else {
        $pos .= ";".$positions;
        $i=0;
        # annotate each score assignated to the same positions
        foreach my $s ( keys %{ $interaction_details->{$coordinates}->{$positions} } ) {
          if(!$i){
            $scores .= ";".$s;
            $i++;
          } else {
            $scores .= "_".$s;
          }
        } # foreach score
      }
    } # foreach position
    $rowtofile .= "\t".$pos."\t".$scores."\n"; # (in) Positions (with) Scores
  }

  return $rowtofile;
}

## Output INFO message to STDOUT and to log file
sub messageInfoAndLog {
  my ($message) = @_;

  print $log "\n".$message;
  &RSAT::message::Info($message) if ($main::verbose >= 0 );

}


# Convert tsv table to a table in html
sub tableToHTML {
  my ($table_str, $table_id, $header_in_table_str, $header_class, $twocols) = @_;

  my @rows = split(/\n/, $table_str);
  $table_html = '
  <table id="'.$table_id.'" class="icon_section_main_table';
  $table_html .= '_twocol' if ($twocols);
  $table_html .= '" style="width:auto;">

  ';

  ## table header
  if ($header_in_table_str){
    my $header = shift(@rows);
    $header_class = 'class="tab_col"' unless ($header_class);

    # add header row tags
    $header =~ s/^/<th $header_class>/;
    $header =~ s/\t/<\/th><th $header_class>/g;
    $header =~ s/$/<\/th>/;
    # add column tags
    $table_html .= "
      <thead>
        <tr>
          ".$header."
        </tr>
      </thead>
    "
  }

  ## table body
  $table_html .= "
      <tbody>
  ";
  while(my $row = shift(@rows) ){
    # add row tags
    $row =~ s/^/<td>/;
    $row =~ s/\t/<\/td><td>/g;
    $row =~ s/$/<\/td>/;
    # add column tags
    $table_html .= "
        <tr>
          ".$row."
        </tr>
    "
  }
  $table_html .= '
      </tbody>

    </table>
  ';

  return $table_html;
}

sub indirectTableToHTML {
  my ($table_str, $table_id, $header_in_table_str, $header_class) = @_;
  my @indirect_int_unit = split(/\n\n/, $table_str);

  $table_html = '<table';
  $table_html .= ' id="'.$table_id.'"' if ($table_id);
  $table_html .= ' class="icon_section_main_table_indirect';
  $table_html .= '" style="width:auto;">
  ';

  # header of table
  my $header = shift(@indirect_int_unit);
  $table_html .= '
  <thead>
    <tr>
      <th>TF1</th>
      <th>TF2</th>
      <th>TF3</th>
      <th>
        <table>
          <thead>
            <tr><th>Interaction Details</th></tr>';

  # add header row tags
  $header =~ s/^/<th>/;
  $header =~ s/\t/<\/th><th>/g;
  $header =~ s/$/<\/th>/;
  # add column tags
  $table_html .= "
          <tr>
            ".$header."
          </tr>
        </thead>
      </table>
     </th>
    </tr>
  </thead>
  ";

  # body of table
  $table_html .= "
  <tbody>
  ";
  my $indirect_int_unit_html = "";
  my $interaction_details = "";
  while(my $unit = shift(@indirect_int_unit) ){

    my @rows = split(/\n/,$unit);
    $indirect_int_unit_html = "";
    $interaction_details = "";

    while(my $row = shift(@rows)){
      if ($row =~ /^(\w+)\t==>\t(\w+)\t==>\t(\w+)/){
        # add row tags
        $row =~ s/^/<td>/;
        $row =~ s/\t==>\t/<\/td><td>/g;
        $row =~ s/$/<\/td>/;
        $indirect_int_unit_html .= '
      <tr>
          '.$row;
      } else {
        # interaction details
        if ($interaction_details eq ""){
          $interaction_details .= '
          <td><table>'
        }
        # add row tags
        $row =~ s/^/<td>/;
        $row =~ s/\t/<\/td><td>/g;
        $row =~ s/$/<\/td>/;
        # add column tags
        $interaction_details .= "
            <tr>
              ".$row."
            </tr>"
      }
    } # while row
    $interaction_details .= '
         </table></td>';

    $indirect_int_unit_html .= $interaction_details.'
      </tr>';

    $table_html .= $indirect_int_unit_html;
  } # while unit

  $table_html .= '

  </tbody>

</table>
  ';

  return $table_html;
}

sub makeZip {
  my $cmd = "";
  # get dir
  my ($results_dir) = &RSAT::util::SplitFileName($main::outfile{summary});
  my ($complete_results_dir)  = &RSAT::util::SplitFileName($results_dir);

  print("results_dir = ".$results_dir."\n");
  print("complete_results_dir = ".$complete_results_dir."\n");

  $cmd = "zip -rq ".$complete_results_dir." ".$complete_results_dir;
  #$cmd = "tar cf ".$complete_results_dir.".tar ".$complete_results_dir;

  &doit($cmd, $dry, $die_on_error, $verbose, $batch, $job_prefix);
}

# Create the file with all the matrixes to use retrieve-matrix foreach database foreach TF
sub runRetrieveMatrix {

    my ($matfiles_path_ref, $nonRepTFs_k_ref, $dry, $die_on_error, $verbose, $batch, $job_prefix) = @_;

    my @matfiles_path = @{ $matfiles_path_ref };
    my @nonRepTFs_k = @{ $nonRepTFs_k_ref };


  &messageInfoAndLog("Retrieving matrixes ...\n");
  foreach my $db (@matfiles_path){
    $ACs = &retrieveACsfromTFs($db, @nonRepTFs_k);
    #print ("ACs = ".$ACs."\n");
    my $retrieve_matrix_cmd = &RSAT::server::GetProgramPath("retrieve-matrix");

    $cmd = "$retrieve_matrix_cmd -i ".$db." -id ".$ACs." >> ".$main::used_outfile{used_matrixes};
    &doit($cmd, $dry, $die_on_error, $verbose, $batch, $job_prefix);
    #system ($cmd);
    #die "BOOM";
  }
  &messageInfoAndLog("\tGot matrixes!\n");
}


################################################################################
####                                                                        ####
####           Functions to make html SUMMARY output file                   ####
####                        adapted from matrix-clustering                  ####
####                                                                        ####
################################################################################

###############################
## Export the cluster header
sub Text_end_report {
  my ($info_hashref) = @_;
  my %info = %{$info_hashref}; # dereference hash
  # $info{References}[0] = ['Name','link', 'ref citation']
  # $info{AddInfo}[0] = ['link', 'material name']
  # $info(Contacts)[0] = ['web page link', 'Name', 'mail']

    my $end_report = '
 <!--       <div id="References_Button" class="button_click Section_button selected_header_section" style="margin-top:2px;"><strong>References</strong></div> -->
	<div id="end_report" style="margin-bottom:20px;">
	  <ul style="list-style: none;">
	    <li>
	      <strong>References</strong>
              <ol>
--references_html--
              </ol>
	    </li>';

      if ($info{AddInfo}) {
        $end_report .= '
        <li>
          <strong>Additional Information</strong>
                <ul>
--addInfo_html--
                </ul>
        </li>
        ';
      }

      $end_report .= '
	    <li>
	      <strong>Contact</strong>
              <ul>
--contacts_html--
              </ul>
            </li>
          </ul>
	</div>';

  # References
  if ($info{References}){
    # concatenate References
    my $refs_html = "";
    for (my $ref = 0; $ref <= (scalar( @{ $info{References} } ) - 1); $ref++){
      $refs_html .= '
                  <li><strong>'.$info{References}[$ref][0].'</strong><a href="'.$info{References}[$ref][1].'" target=\'_blank\'>'.$info{References}[$ref][2].'</a></li>';
    }
    ## add to html
    $end_report =~ s/--references_html--/$refs_html/;
  } else {
    $end_report =~ s/--references_html--//;
  }

  # Additional info
  if ($info{AddInfo}){
    my $addinfo_html = "";
    for (my $i = 0; $i <= (scalar( @{ $info{AddInfo} } ) - 1); $i++){
      $addinfo_html .= '
                  <li type="square"><a href="'.$info{AddInfo}[$i][0].'" target=\'_blank\'>'.$info{AddInfo}[$i][1].'</a></li>';
    }
    # add to html
    $end_report =~ s/--addInfo_html--/$addinfo_html/;
  }

  # list contacts
  if ($info{Contacts}){
    # concatente contacts
    my $contacts_html = "";
    for (my $person = 0; $person <= (scalar( @{ $info{Contacts} } ) - 1); $person++) {
      $contacts_html .= '
                   <li type="square"><a target=\'_top\' href="'.$info{Contacts}[$person][0].'">'.$info{Contacts}[$person][1].'</a> - <strong>'.$info{Contacts}[$person][2].'</strong></li>';
    }
    # add contacts
    $end_report =~ s/--contacts_html--/$contacts_html/;
  } else {
    $end_report =~ s/--contacts_html--//;
  }

    print $syn $end_report."\n";
}


################################################################
## Generate a compressed archive with all the results
sub Archive {

  my ($remove_first, $to_archive) = @_;
  &RSAT::message::TimeWarn("\n; Archiving data and results") if ($main::verbose >= 2);

  ## Delete previous version of the archive to avoid including the old archive in the new one
  $cmd .= "rm -f ".$main::outfile{archive}."; " if ($remove_first); # used only once

  ################################################################
  ## Define archiving parameters

  ## By default, archive the whole output directory
  $to_archive = $main::output_dir unless $to_archive;

  ## Archive all data and results
  my ($archive_dir, $archive) = &SplitFileName($main::outfile{archive}); # $main::output_dir."/".$main::output_prefix."archive.zip"
  my ($archive_dir_dir, $archive_dir_base) = &SplitFileName($archive_dir);
#  $to_archive_rel_path = &RSAT::util::RelativePath($main::outfile{archive}, $to_archive);
  my $to_archive_rel_path = &RSAT::util::RelativePath($archive_dir_dir, $to_archive);
  my $archive_rel_path = &RSAT::util::RelativePath($archive_dir_dir, $main::outfile{archive});

  ## TO CHECK (Jacques)
  if ($main::verbose >= 3) {
    &RSAT::message::Debug("folder to archive", $to_archive);
  }

  ## Avoid crash of the program when run from the "$archive_dir_dir"
  if ($archive_dir_dir eq "") {
    $archive_dir_dir = ".";
    $to_archive_rel_path = $to_archive;
    $archive_rel_path = $main::outfile{archive};
  }

  my $cmd = "";
  if ($main::archive_format eq "zip") {
    $cmd .= "(cd ".$archive_dir_dir." ; ";
    $cmd .= " zip -ry ".$archive_rel_path." ".$to_archive_rel_path;
    $cmd .= " -x ".$archive;
    $cmd .= ")";
  } elsif (($main::archive_format eq "tar") ||
	   ($main::archive_format eq "tgz")) {
    $cmd .= "tar -cpf ".$main::outfile{archive};
    $cmd .= " -z" if ($main::archive_format eq "tgz");
    $cmd .= " -C ".$archive_dir_dir; ## Avoid including the whole path in the archive paths
    $cmd .= " --exclude ".$archive;
    $cmd .= " ".$to_archive_rel_path;
  } else {
    &RSAT::error::FatalError($main::archive_format, "Invalid archive format. Supported: zip, tar, tgz.");
  }

  &one_command($cmd, 1);

  &RSAT::message::TimeWarn("Archive", $main::outfile{archive}) if ($main::verbose >= 2);
}

##########################################
## Open the HTML page for the synthesis
sub OpenSynthesis {

  my $refresh_time;
  #if ($main::param{progressive_synthesis}) {
    $refresh_time = 90;
  #} else {
  #   $refresh_time = 0;
  #}

  ## Open the summary HTML file
  $syn = &OpenOutputFile($main::outfile{summary});
  #$synthesis_path = `dirname $main::outfile{summary}`; # doesnt work
  my ($synthesis_path, $syn_name) = &RSAT::util::SplitFileName($main::outfile{summary});
  chomp($synthesis_path);

  my $html_lib = ""; # code library for style
  # /* to delete? */
  #if ($root_matrices_flag == 0) {
      ## Add the JS libraries paths
      $html_lib .= '
   <script type="text/javascript" src="'.$d3_base.'"></script>
   <script type="text/javascript" src="'.$jquery_base.'"></script>
   <script type="text/javascript" src="'.$datatable_base.'"></script>
   <link rel="stylesheet" type="text/css" href="'.$datatable_css_base.'">
</head>
     ';
  #}
  # /* ? */

  ## Add the CSS style for matrix-clustering summary and
  ## concatenate it to header the CSS sytles
  my $css_matrix_clustering = &ReportStyleCSS();
  $html_lib .= $css_matrix_clustering."\n";

  my $head = &PrintHtmlResultHeader(program=>"network-interactions", "title"=>$main::param{title}, "result_toc"=>1, refresh_time=>$refresh_time);
  $head =~ s|</head>|$html_lib|;

  print $syn $head;

  &ReportCommand();
}


sub ReOpenSynthesis {

  unlink($main::outfile{summary});
  close($syn);

  ## Open the summary HTML file
  $syn = &OpenOutputFile($main::outfile{summary});
  $synthesis_path = `dirname $main::outfile{summary}`;
  chomp($synthesis_path);

  my $html_lib = ""; # code library for style
  # /* to delete? */
  #if ($root_matrices_flag == 0) {
      ## Add the JS libraries paths
      $html_lib .= '
   <script type="text/javascript" src="'.$d3_base.'"></script>
   <script type="text/javascript" src="'.$jquery_base.'"></script>
   <script type="text/javascript" src="'.$datatable_base.'"></script>
   <link rel="stylesheet" type="text/css" href="'.$datatable_css_base.'">
</head>
     ';
  #}
  # /* ? */

  ## Add the CSS style for matrix-clustering summary and
  ## concatenate it to header the CSS sytles
  my $css_matrix_clustering = &ReportStyleCSS();
  $html_lib .= $css_matrix_clustering."\n";

  my $head = &PrintHtmlResultHeader(program=>"network-interactions", "title"=>$main::param{title});
  $head =~ s|</head>|$html_lib|;

  print $syn $head;

  &ReportCommand();
}


##########################################
sub CloseSynthesis {
    print $syn "</body>\n";
    print $syn "</html>\n";
    close $syn;
}

################################################################
sub ReportCommand {

  print $syn &open_menu_heading($menu_nb++, "<a name='logs'></a><h3>Command</h3>", 1);
  print $syn "<pre>";
  print $syn "network-interactions ";
  &PrintArguments($syn);
  print $syn "</pre>";
  print $syn &close_menu_heading();
}


#################################################
## CSS style for the matrix-clustering summary
## (dynamic tables + D3 trees)
sub ReportStyleCSS{
    my $CSS_mat_clus = '
<style>

  h3 a:hover {
	font-weight: bold;
	text-decoration: none;
  }


  .cluster_division {
	background-color: '.$blue_color.';
	float: left;
	margin: 5px 3px 3px 3px;
	width: auto;
	height: 15px;
	position: relative;
	display: inline-block;
	text-align: center;
	color: '.$font_color.';
	font-size: 12px;
	padding: 4px;
	cursor: pointer;
	border-radius:5px;
	border: 1px solid #819FF7;
  }


  .button_click:active {
  position:relative;
  top:1px;
  }

  .tab{
    font-size: 10px;
    margin-top: 3px;
    text-align: center;
    text-decoration: none;
    display: block;
    background-color: #E6E6E6;
    clear: both;
    float: left;
    position: relative;
    border-radius:5px;
    padding: 0px 10px 10px 10px;
  }

  .sep {
  background-color: #B1D4F9;
  height: 17px;
  }


  .tab_list{
  width: 937px;
  text-align: left;
  color: #000000;
  font-family: Arial;
  text-decoration: none;
  display: none;
  float: left;
  background-color: #E6E6E6;
  font-size: 15px;
  clear: both;
  position: relative;
  border-radius:5px;
  padding: 0px 0px 0px 5px;
  }


  .tab_header {
  border-bottom: 1px solid black;
  width: 175px;
  padding: 7px;
  }

  .tab_col {
    padding: 7px 30px 7px 30px;
    background-color: #B1D4F9 !important;
  }

  .seq {
  font-family: Monospace;
  font-size: 15px;
  }

  .Cluster_results {
  margin-top: 3px;
  width: auto;
  heigth: 80px;
  border: 1px;
  position: relative;
  padding: 1px;
  font-size: 13px;
  margin-top: 20px;
  text-align: center;
  color: #ffffff;
  background:#cc0000;
  border-radius:5px;
  cursor: pointer;
  float: left;
  clear: both;
  display: none;
  }

  .Cluster_results:active {
  position:relative;
  top:1px;
  }

  .icon {
    margin: 17px;
  }

  .Section_button {
  background-color: '.$blue_color.';
  float: left;
  margin-top: 0px;
  margin-bottom: 0px;
  width: 450px;
  height: 20px;
  position: relative;
  display: block;
  text-align: center;
  color: '.$blue_font_color.';
  font-size: 15px;
  padding: 1px;
  clear: both;
  border-radius:5px;
  cursor: pointer;
  }

  .file_link {
  cursor: pointer;
  text-decoration: none;
  }

  .file_link:hover {
  text-decoration: underline;
  }

  #hclust_tree_head {
  width: 900px;
  heigth: 400px;
  margin-top: 15px;
  margin-bottom: 5px;
  display: inline-block;
  position: relative;
  padding: 3px;
  background-color: #B1D4F9;
  float: left;
  border-radius:5px;
  font-size: 12px;
  clear: both;
  }

  .logo {
	position: relative;
	max-width: 100%;
	max-height: 13%;
	width: 120px;
	height: 65px;
	float: left;
	clear: both;
  }

  .logo_tab {
	position: relative;
	max-height: 20%;
	height: 45px;
	width: 75px
	float: left;
	clear: both;
  }

  .logo_tree {
  position: relative;
  float: left;
  display: none;
  clear: both;
  padding: 0px;
  }

  .branch_motifs_head {
  width: 950px;
  heigth: 500px;
  margin-top: 15px;
  margin-bottom: 5px;
  display: none;
  position: relative;
  padding: 3px;
  background-color: #B1D4F9;
  float: left;
  border-radius:5px;
  font-size: 12px;
  clear: both;
  }

  .spacer {
  heigth: 200px;
  display: block;
  position: relative;
  clear: both;
  float: left;
  background-color: #B1D4F9;
  }


  .tab_spacer_1 {
  padding: 2px 12px 2px 12px;
  font-size: 12px;
  }


  .tab_spacer_2 {
    padding: 3px;
    font-size: 12px;
  }

  #heatmap {
	heigth: 400px;
	width: 450px;
  }

  #show_forest {
	heigth: auto;
	width: 97%;
	position: relative;
	float: left;
	clear: both;
	border-radius:5px;
  }

  .display_clusters{
    width: 1100px;
    background-color: #E6E6E6;
    text-align: center;
    padding: 0px 10px 10px 10px;
  }

  .par_text {
    font-size: 12px;
    text-align: center;
  }

  .sep_clusters_div {
    clear: both;
    float: left;
    display: block;
  }

  .display{
	height: auto;
	width: 1000;
	border-radius: 5px;
	background-color: #FFFFFF;
	margin: 10px;
        padding: 7px;
	text-align: left;
	border: solid 3px #004F72;
	clear: both;
	position: relative;
	float: left;
	display: block;
  }

  .individual_results{
	text-align:center;
	padding: 0px 10px 0px 20px;
	width: auto;
	height: auto;
	border-radius: 10px;
	background-color: #E6E6E6;
        position: relative;
        clear: both;
        margin: 0px 7px 7px 0px;
        display: block;
        float: left;
  }

  .cluster_info_head {
	background-color: #DCE4EC;
	float: left;
	height: 45px;
	width: 630px;
	position: relative;
	display: block;
	text-align: left;
	color: #34373B;
	font-size: 15px;
	padding: 0px;
	border-radius:5px;
	clear: both;
        margin-top: 5px;
  }

  .hide_show_button{
	float: left;
	margin: 5px 3px 3px 3px;
	width: 75px;
	height: 15px;
	position: relative;
	display: inline-block;
	text-align: center;
	color: #34373B;
	font-size: 12px;
	padding: 4px;
	cursor: pointer;
	border-radius:5px;
  }

  #show_all_button{
     background-color: '.$orange_color.';
     border: 1px solid orange;
     color: '.$font_color.';
  }

  #hide_all_button{
    background-color: '.$blue_color.';
    border: 1px solid #819FF7;
     color: '.$font_color.';
  }

  .selected_cluster {
    background-color: '.$orange_color.';
    border: 1px solid orange;
  }

  .selected_header_section {
    color : '.$font_color.';
    background-color: '.$orange_color.' !important;
    border: 1px solid '.$orange_color.';
  }

  #end_report {
  width: 977px;
  heigth: 400px;
  margin-top: 15px;
  margin-bottom: 5px;
  display: inline-block;
  position: relative;
  padding: 3px;
  background-color: #E6E6E6;
  float: left;
  border-radius:5px;
  font-size: 12px;
  clear: both;
  }

  /****************/
  /* D3 CSS sytle */
  /****************/

  div {
  border-radius: 0.5px;
  }


  table {
  border: #2377D2;
  }


  .node circle {
  stroke-width: 0.5px;
  }


  .node {
  font: 10px sans-serif;
  }


  .link {
  fill: none;
  stroke-width: 1px;
  }

  svg {
  pointer-events: all;
  background-color: white;
  overflow: scroll;
  }

  .param {
  font: 11px sans-serif;
  }

</style>
';

    return($CSS_mat_clus);
}

###########################################
## PArameters table of matrix-clustering.
## The values are filled with variables
## taken from other parts of the code
sub ParametersTable{
  my ( $parameters, $main_title ) = @_;
  my %hash_params = %{ $parameters }; # dereference hash
  # hash should have paired all parameters or section paired with their values
  # subparameters or subsections can be specified using a multidimensional hash
  # an example is provided in network-interactions subroutin Synthesis

  $main_title = 'Parameters' if ( $main_title eq '' );

  my $par_table = '
  <!-- Div with the table of selected parameters -->
  <div id="Par_tab" class="tab" style="margin-bottom:15px;">
    <h2 style="margin-top: 0px;margin-bottom: 5px;">'. $main_title .'</h2>

    <table id="parameters_table" style="width:700px;">

      <thead>
        	<tr>
--parameters_titles_html--
        	</tr>
      </thead>

      <tbody>
      	<tr>
--parameters_values_html--
      	</tr>
      </tbody>

    </table>

  </div>
'."\n\n";

 # construct sections with input hash
 my $param_titles_html = "";
 my $param_values_html = "";
 foreach my $param_title (sort keys %hash_params){

   $param_titles_html .=  '<th class="tab_col">'.$param_title;

   # In case of subparameters or subsections
   if ( ref($hash_params{$param_title}) eq 'HASH' ) {

     # subtitle html
     $param_titles_html .=  '
       <table><tbody>
         <tr>
     ';

     # subvalue html
     $param_values_html .=  '
      <td>
       <table span="3"><tbody>
         <tr>
     ';

     #foreach my $subparam_title (sort keys %{ $hash_params{$param_title} } ){
      #  $param_titles_html .=  '<td class="tab_col param">'. $subparam_title .'</td>';
      #  $param_values_html .=  '<td class="par_text" style="width:150px;">'. %{ $hash_params{$param_title} }{$subparam_title} .'</td>';
      #  print($subparam_title."\t => ".%{ $hash_params{$param_title} }{$subparam_title}."\n");
     #}

     my ($subparam_title, $value);
     while ( ($subparam_title, $value) = each %{ $hash_params{$param_title} }) {
       #print($subparam_title."\t => ".$value."\n");
       $param_titles_html .=  '<td class="tab_col param">'. $subparam_title .'</td>';
       $param_values_html .=  '<td class="par_text" style="width:150px;">'. $value .'</td>';
     }

     $param_titles_html .= '
         </tr>
      </tbody></table>
     ';

     $param_values_html .= '
         </tr>
      </tbody></table>
     </td>
     ';
   } else {
     $param_values_html .=  '<td class="par_text">'. $hash_params{$param_title} .'</td>';
   }

   $param_titles_html .= '</th>';
 }

 # add sections to html
 $par_table =~ s/--parameters_titles_html--/$param_titles_html/;
 $par_table =~ s/--parameters_values_html--/$param_values_html/;

  print $syn $par_table;
}

###########################################
## Table in div with button

sub ButtonNTable {
  my ($button_div_id, $table_div_id, $title_in_button, $title_in_table_div, $table_html, $button_div_class, $table_div_class, @add_notes) = @_;

  ## check input
  #unless ($table_html ne ""){
  #  print "No input html table when calling ButtonNTable\n";
  #  exit;
  #}

  # div class defaults
  $button_div_class = "button_click Section_button" unless ($button_div_class);
  $table_div_class = "tab" unless ($table_div_class);

  # button and table section skeleton
  my $div_button_table = '
  <div id="'.$button_div_id.'" class="'.$button_div_class.'"><strong>'.$title_in_button.'</strong></div>
  <div id="'.$table_div_id.'" class="'.$table_div_class.'" style="margin-bottom:15px;display:none;width:auto;">
    <h2 style="margin-top: 0px;margin-bottom: 5px;">'.$title_in_table_div.'</h2> '."\n";

$div_button_table .= "\n".'

--main_table_html--

    <ul style="text-align:left;margin:0px 0px 5px 0px;">
--additional_notes_html--
       <li type="square" style="color:red">Note: by default the table displays the first 50 entries. Click on the <i>Show X entries</i> button to display more (or less).</li>
       <li type="square">Click on the column names to change the order of the data.</li>
       <li type="square">Use the <i>Search</i> window to find your entries of interest.</li>
    </ul>

  </div>
'."\n\n";

  ## Additional notes
  if (scalar(@add_notes) > 0 ){
    my $add_notes_html = "";

    foreach my $note (@add_notes) {
      $add_notes_html .= '       <li type="square">'.$note.'</li>
      ';
    }

    ## add additional notes
    $div_button_table =~ s/--additional_notes_html--/$add_notes_html/g;
  } else {
    $div_button_table =~ s/--additional_notes_html--//g;
  }

  # add actual table
  $div_button_table =~ s/--main_table_html--/$table_html/g;

  # add script to summary html
  print $syn $div_button_table;
}

#########################################
## Open the <scrip> tag for JQuery code
sub OpenScriptJQuery {
  $script_jquery = '<script>

// Dynamic Icons section tables
$(document).ready( function () {
    $(\'.icon_section_main_table\').DataTable({
        "info":     true,
        "iDisplayLength": 50,
        "order": [[ 1, "asc" ]],
	"search": {
	    "regex": true,
	    "smart": true
	},
	"aoColumnDefs": [
            { "bSortable": true, "aTargets": [ 0,1,2,3,4 ] }
	]
    });
});

// Dynamic Icons section tables Not Found two cols
$(document).ready( function () {
    $(\'.icon_section_main_table_twocols\').DataTable({
        "info":     true,
        "iDisplayLength": 50,
        "order": [[ 1, "asc" ]],
	"search": {
	    "regex": true,
	    "smart": true
	},
	"aoColumnDefs": [
            { "bSortable": true, "aTargets": [ 0,1 ] }
	]
    });
});

// Dynamic Icons section tables
$(document).ready( function () {
    $(\'.icon_section_main_table_indirect\').DataTable({
        "info":     true,
        "iDisplayLength": 50,
        "order": [[ 1, "asc" ]],
	"search": {
	    "regex": true,
	    "smart": true
	},
	"aoColumnDefs": [
            { "bSortable": true, "aTargets": [ 0,1,2,3 ] }
	]
    });
});

// Change the color of buttons
$(document).ready(function() {

    /////////////////////////////
    // Individual files button
    $(\'#List_File_Button\').mouseenter(function() {
        $(this).fadeTo(\'fast\', 0.6);
    });

    $(\'#List_File_Button\').mouseleave(function() {
        $(this).fadeTo(\'fast\',1);
    });

});


// Slide the Parameters Table
$(document).ready(function() {
    $(\'#Par_tab_button\').click(function() {
	$(\'#Par_tab\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Complete Net Buttons n Tables
$(document).ready(function() {
    $(\'#complete_net_button\').click(function() {
	$(\'#complete_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Only TFs Net Buttons n Tables
$(document).ready(function() {
    $(\'#onlyTFS_net_button\').click(function() {
	$(\'#onlyTFs_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Intersection Net Buttons n Tables
$(document).ready(function() {
    $(\'#intersection_net_button\').click(function() {
	$(\'#intersection_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Not Found Buttons n Tables
$(document).ready(function() {
    $(\'#not_found_net_button\').click(function() {
	$(\'#not_found_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Found Buttons n Tables
$(document).ready(function() {
    $(\'#found_net_button\').click(function() {
	$(\'#found_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide Indirect Buttons n Tables
$(document).ready(function() {
    $(\'#indirect_net_button\').click(function() {
	$(\'#indirect_net_table_div\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide the File list
$(document).ready(function() {
    $(\'#List_Files_Button\').click(function() {
	$(\'#File_list\').slideToggle(\'fast\');
        $(this).toggleClass(\'selected_header_section\');
    });
});

// Slide the References
$(document).ready(function() {
  $(\'#References_Button\').click(function() {
	   $(\'#end_report\').slideToggle(\'fast\');
     $(this).toggleClass(\'selected_header_section\');
  });
});
';
}


###########################################
## Insert the JQuery script in the report
sub InsertJquery {
    print $syn $script_jquery;
}


#######################################
## Insert the list of files exported
sub InsertListOfFiles {
  my ($list_of_files, $button_title) = @_;
  # $list_of_files{main_outfile_key} = ('File Name','Description')
  my $list_of_files_html = "";
  my %hash_list_of_files = %{$list_of_files}; # dereference hash

  # default title
  $button_title = 'List of Files' if ( $button_title eq '' );

      my $add_files =
	  '

    <div id="List_Files_Button" class="button_click Section_button" style="margin-top:5px;margin-bottom:4px;"><strong>'.$button_title.'</strong></div>
  	<div id="File_list" class="tab_list" style="width:960px">

	  <table>

	    <thead>
	      <tr>
      		<th class="tab_col" style="width:200px">File</th>
      		<th class="tab_col" style="width:700px">Description</th>
	      </tr>
	    </thead>

	    <tbody>
--list_of_files_html--
	    </tbody>

	  </table>

	</div>
';

  my ($dir, $short_file_name) = &RSAT::util::SplitFileName($main::outfile{summary});

  # list files
  foreach my $file (sort keys %hash_list_of_files) {
    $list_of_files_html .= '
      <tr>
        <td class="tab_spacer_2"><a target="_blank" class="file_link" href="'.&RSAT::util::RelativePath($dir, $main::outfile{$file}).'"><strong>'.$hash_list_of_files{$file}[0].'</strong></a></td>
        <td class="tab_spacer_2">'.$hash_list_of_files{$file}[1].'</td>
      </tr>
    ';
  }
  # add list to table
  $add_files =~ s/--list_of_files_html--/$list_of_files_html/;
  # add list table N button to summary html
  print $syn $add_files;
}

################################################################
## Generate a HTML report summarizing the main results with
## links to the original result files.
sub Synthesis {

    &RSAT::message::TimeWarn("\n; Generating HTML Report") if ($main::verbose >= 2);

    &ReOpenSynthesis();

    ## Initialize the variables
    ## /* to delete? */
    #%ids_to_cluster = ();
    #%alignment_table_data = ();
    #%alignment_size = ();
    ## /* ? */
    $script_jquery = "";
    ## /* to delete? */
    #$all_d3_trees = "";
    #$all_consensus_table = "";
    #$number_of_motifs = 0;
    #$nb_char = 0;
    ## /* ? */
    my $section_tab_icon_tail = '</td></tr>';
    my $section_tab_icon_intermediate = '</td></tr><tr><td>';
    my $section_tab_icon_tail_int_table = '</td></tr></table></td></tr>';
    my $icon_height = 60;

    $menu_nb = 200; ## Numbering of the IDs for collapsible elements ## /* to delete? */

    #&ReadAlignmentTable();

    ## /* to delete? */
    #$number_of_clusters = scalar(keys %alignment_table_data);
    #
    #if ($radial_tree_flag == 1){
	  #   &create_html_radial_tree_file();
    #} else {
	  #   &create_html_small_tree_file();
    #}
    ## /* ? */

    &OpenScriptJQuery();

    &ReportStyleCSS();

    my %parameters = (); # sections for Results Summary / Parameters Table
    #$parameters{'Results Files'} = '<a href="'.&RSAT::util::RelativePath($main::outfile{summary}, $main::output_dir).'">Download</a>';
    $parameters{'Complete Output Files [zip]'} = '<a href="'.&RSAT::util::RelativePath($main::outfile{summary}, $main::outfile{archive}).'">Download</a>';
    $parameters{'Genome Assembly'} = $main::genome;
    $parameters{'<i>matrix-scan</i> Parameters'}{'Score lth'} = $main::score;
    $parameters{'<i>matrix-scan</i> Parameters'}{'P-value uth'} = $main::pval if ( $main::pval ne "NA" );

    #my ($k, $v);
    #while ( ($k,$v) = each %parameters ) {
    #  print "$k => $v\n";
    #}

    &ParametersTable( \%parameters, 'Results Summary');
    #&ParametersTable( %parameters );

    #################################
    ##       ICONS SECTION        ##
    #################################
    my @add_notes = ();

    ## Open the icons table
    my $table_icons_head = '<table style="display:block;clear:both;"><tbody>';
    print $syn $table_icons_head;

    #################################
    ##  Main networks

    my $net_icon = '
          <tr>
            <td>
              <img class="icon" src="'.$icons{network}.'" height="'.$icon_height.'", width="auto">
            </td>
            <td>
              <table>
                <tr>
                  <td>';
    print $syn $net_icon;

    # complete network
    #             ($button_div_id,       $table_div_id,            $title_in_button,   $title_in_table_div,            $table_html,             $button_div_class, $table_div_class, @add_notes)
    &ButtonNTable("complete_net_button", "complete_net_table_div", "Complete Network", "Complete Network (all genes)", $tables_html{complete_direct_interactions});
    print $syn $section_tab_icon_intermediate;

    # only-TFs network
    &ButtonNTable("onlyTFS_net_button", "onlyTFs_net_table_div", "Only-TFs Network", "Only-TFs Network", $tables_html{only_TFs});
    print $syn $section_tab_icon_tail_int_table;

    #################################
    ##  Comparison networks

    ## Check run status
    if ($status{empty_input_net}){
      push(@add_notes, "<b>Warning!</b> The input network was not taken into account for comparison because the regulatory sequences of the nodes were not specified. In this case, no interactions will appear in the Overlap and Not found tables. Please specify the regulatory sequences of the genes and TFs in 'Regulatory Sequences BED file'. ");
      push(@add_notes, "The regulatory sequences of the following genes were not specified: ".$status{genes_no_reg_seq});
    } elsif ($status{reduced_input_net}){
      push(@add_notes, "<b>Warning!</b> Some of the interactions specified in the input network were not taken into account for this comparison because their regulatory sequences were not specified. ");
      push(@add_notes, "The regulatory sequences of the following genes were not specified: ".$status{genes_no_reg_seq});
    }
    if ($status{empty_intersection}){
      push(@add_notes, "<b>Warning!</b> No interactions were found in common. This can happen if the input network was emptied.");
    }

    ## Continue constructing summary

    my $comparison_icon = '
          <tr>
            <td>
              <img class="icon" src="'.$icons{comparison}.'" height="'.$icon_height.'", width="auto">
            </td>
            <td>
              <table>
                <tr>
                  <td>';
    print $syn $comparison_icon;

    # intersection
    &ButtonNTable("intersection_net_button", "intersection_net_table_div", "Networks Overlap", "Intersection between Input Network and Complete Network", $tables_html{intersection} , "", "", @add_notes );
    print $syn $section_tab_icon_intermediate;

    # not_found interactions
    &ButtonNTable("not_found_net_button", "not_found_net_table_div", "Not Found Interactions", "Input Network's Interactions Not Found", $tables_html{not_found},"" ,"" , @add_notes  );
    print $syn $section_tab_icon_intermediate;

    # found interactions
    &ButtonNTable("found_net_button", "found_net_table_div", "Newly Found Interactions", "Network's Newly Found Interactions", $tables_html{found} , "", "", @add_notes );
    print $syn $section_tab_icon_tail_int_table;

    # intersection (only-TFs)

    @add_notes = ();
    #################################
    ##  Indirect network

    my $indirect_icon = '
          <tr>
            <td>
              <img class="icon" src="'.  $icons{indirect}.'" height="'.$icon_height.'", width="auto">
            </td>
            <td>
              <table>
                <tr>
                  <td>';
    print $syn $indirect_icon;

    &ButtonNTable("indirect_net_button", "indirect_net_table_div", "Indirect Interactions", "Indirect Interactions", $tables_html{indirect});
    print $syn $section_tab_icon_tail_int_table;

    ## Close the icons table
    my $table_icons_tail = "</tbody></table>";
    print $syn $table_icons_tail;

    #################################
    #################################

    my %list_of_files = (); # hash of list of files, with name and description
    $list_of_files{complete_direct_interactions} = ['Complete Network',"This table shows the network done with all the genes for which its regulatory corrdinates was indicated. Format is as follows: a TF-gene interaction per row, coordinates where the TF moif was found, strand and position starting from first coordinate and <em>matrix-scan</em>'s related score."];
    $list_of_files{GRN_direct_interactions} = ['Only-TFs Network',"This table shows the network done with all TFs for which its regulatory coordinates was indicated. Format is as follows: a TFx-TFy interaction per row (where the first putatively regulates the second one), coordinates where the TFx motif was found, strand and position starting from first coordinate and <em>matrix-scan</em>'s related score"];
    $list_of_files{network_intersection} = ['Networks Overlap',"This table shows the intersection of interactions between the input network and the complete network outputted by the program. Format is as in 'Complete Network'."];
    $list_of_files{network_not_found_interactions} = ['Not Found Interactions',"This table lists interactions indicated in the input network but that were not corroborated by the program. Format is a gene-gene interaction per row."];
    $list_of_files{network_found_interactions} = ['Newly Found Interactions',"This table lists interactions found by the program but that were not indicated in the input network. Format is as in 'Complete Network'."];
    #$list_of_files{network_intersection_onlyTFs} = ['Networks Overlap (Only-TFs)',""];
    $list_of_files{GRN_indirect_interactions} = ['Indirect Interactions',"This file lists indirect interactions (composed by three nodes), as well as direct interactions and no interactions for all TFs. Putative interaction (or binding) information is given as in 'Only-TFs Network'."];
    $list_of_files{log} = ['Log',"This file specifies each step of the program, posible errors, warnings (e.g. which genes were actually taken into account), and execution time."];
    #$list_of_files{archive};
    #$list_of_files{summary} = ['HTML Summary',"The present html document."]; # HTML is not an independent file and can only be completely loaded when the other files are also available
    $list_of_files{used_matrixes} = ['Used PSSMs TRANSFAC',"Here are listed the used Position-Specific Score Matrixes (PSSMs) used to find the indicated TFs' motifs in TRANSFAC format."];
    $list_of_files{used_regulatory_regions} = ['Used Regulatory Regions BED',"Here is the used BED file with the coordinates of the regulatory regions of each gene."];
    #$list_of_files{used_cre_seqs} = ['Used Regulatory Regions FASTA',""];
    $list_of_files{used_cre_seqs_geneheader} = ['Used Regulatory Regions FASTA',"Here are the regulatory sequences in FASTA format for all the genomic coordinates indicated in 'Used Regulatory Regions BED' file."];
    $list_of_files{used_matrix_scan_results} = ['Used matrix-scan Results',"Here are the results outputted by <em>matrix-scan</em> used to build the networks."];
    &InsertListOfFiles(\%list_of_files, 'Individual Files');

    &InsertJquery();

    #if ($radial_tree_flag == 1){
	     print $syn "</script>\n";
    #}

    my %end_report_info = (); # description of hash structure in function
    $end_report_info{References}[0] = ['Last RSAT release: ','https://academic.oup.com/nar/article/46/W1/W209/4990780', 'Nguyen NTT et al. RSAT 2018: regulatory sequence analysis tools 20th anniversary. Nucleic Acids Research (2018).'];
    $end_report_info{Contacts}[0] = ['','Monica Padilla','mpadilla@lcgej.unam.mx'];
    $end_report_info{Contacts}[1] = ['http://liigh.unam.mx/amedina/index.html','Alejandra Medina Rivera','amedina@liigh.unam.mx'];
    &Text_end_report(\%end_report_info);

    ## End of the HTML file
    &CloseSynthesis();

    &RSAT::message::TimeWarn("Report", $main::outfile{summary}) if ($main::verbose >= 2);
}
