#!/usr/bin/env perl

## use strict;

=pod

=head1 NAME

position-scan

=head1 VERSION

1

=head1 DESCRIPTION

This program computes the positional binding profile of a set of PSSMs in a set of sequences of the same length.


=head1 AUTHORS

j.a.c.mondragon@ncmm.uio.no

=head1 CATEGORY

=over

=item util

=back

=head1 USAGE

position-scan [-i inputfile] [-o outputfile] [-v #] [...]

=head1 INPUT FORMAT

=head1 OUTPUT FORMAT

=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";
require "RSA2.cgi.lib";
use RSAT::util;
use RSAT::matrix;
use RSAT::MatrixReader;
use RSAT::SeqUtil;
use List::MoreUtils qw(uniq);
use Data::Dumper;
use File::Basename;
use File::Path;
require "RSA.disco.lib";
require "footprint.lib.pl";


################################################################
## 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 = 0;
  our $in = STDIN;
  our $out = STDOUT;

  ## Default parameters
  local $seq_length = 100;
  local $bin_size = 50;
  local $p_value = 1e-3;
  local $bg_format = "oligos";
  local $seq_format = "fasta";
  local $seq_control_format = "fasta";
  local $matrix_format = "tf";
  local $individual_plots = 1;
  local $legend_pos = "bottom";
  local $heatmap_dendo = "show";
  local $strands = "-2str";

  ## Optional parameters
  ## matrix-scan top/last matrices
  local $top_matrix_flag = 0;
  local $skip_matrix_flag = 0;

  ## convert-seq top/last matrices
  local $top_seq_flag = 0;
  local $skip_seq_flag = 0;

  ## BG model input
  local $bg_file_flag = 0;
  local $bg_input_flag = 0;
  local $markov = 1;

  $SCRIPTS = $ENV{RSAT}."/perl-scripts/";

  ## List of files to delete
  %to_delete = ();
  %to_delete_folder = ();


  ## Input formats: only accept formats supporting multiple matrices
  local @supported_matrix_formats = qw(transfac tf tab cluster-buster cb infogibbs meme stamp uniprobe);
  local %supported_matrix_format = ();
  foreach my $format (@supported_matrix_formats) {
    $supported_matrix_format{$format} = 1;
  }
  local $supported_matrix_formats = join ",", @supported_matrix_formats;

  ## Profile plot legend position option
  local @supported_legend_pos = qw(side bottom);
  local %supported_legend_pos = ();
  foreach my $pos (@supported_legend_pos) {
    $supported_legend_pos{$pos} = 1;
  }
  local $supported_legend_pos = join ",", @supported_legend_pos;

  ## Profile heatmap deondrogram position option
  local @supported_heatmap_dendo_pos = qw(hide show);
  local %supported_heatmap_dendo_pos = ();
  foreach my $ps (@supported_heatmap_dendo_pos) {
    $supported_heatmap_dendo_pos{$ps} = 1;
  }
  local $supported_heatmap_dendo_pos = join ",", @supported_heatmap_dendo_pos;

  ## Negative controls
  local $random_seq_flag = 0;
  local $random_motifs_flag = 0;

  ## Differential mode
  local $diff_flag = 0;

  ## Heatmap color palette and classes
  local $heatmap_color_palette = "RdBu";
  local $heatmap_color_classes = 11;

  ## Supported taks
  local @supported_tasks = qw(
			all
                        scan
                        plots
                     );
  local @task = qw (all);
  local $supported_tasks = join ",", @supported_tasks;
  local %supported_tasks = ();
  foreach my $task (@supported_tasks) {
    $supported_tasks{$task} = 1;
  }
  %selected_tasks = ();
  $selected_tasks{"all"} = 1;

  ## Supported heatmap colors (taken from http://colorbrewer2.org/)
  local %supported_heatmap_color_palette = ();
  local @supported_heatmap_color_palette = qw (Spectral RdYlGn RdYlBu RdGy RdBu PuOr PRGn PiYG BrBG);
  local %supported_heatmap_color_palette = ();
  foreach my $palette (@supported_heatmap_color_palette) {
    $supported_heatmap_color_palette{$palette} = 1;
  }
  local $supported_heatmap_color_palette = join ",", @supported_heatmap_color_palette;

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

  ################################################################
  ## Check argument values

  &RSAT::message::TimeWarn("Checking parameter values") if ($main::verbose >= 2);

  ################################################################
  ## Input motif file is mandatory
  unless ($main::infile{motifs}) {
      &RSAT::error::FatalError("The input motif file is mandatory. (-matrix)");
  }

  ################################################################
  ## Input sequences file is mandatory
  unless ($main::infile{sequences}) {
      &RSAT::error::FatalError("The input sequences file is mandatory. (-seq)");
  }

  ################################################################
  ## Input control sequences file is mandatory
  ## If the differential mode is activated
  if($diff_flag){
      &RSAT::message::Info("Differential mode") if ($main::verbose >= 2);
      unless ($main::infile{sequences_control}) {
	  &RSAT::error::FatalError("The control sequences file is mandatory when the differential mode (-diff) is activated. See option -seq_control");
      }
  }

  ################################################################
  ## Input BG file is mandatory
  unless ($main::infile{bg_file} || $bg_input_flag) {
      &RSAT::error::FatalError("The input Background Model file is mandatory. (-bgfile | -bginput)");
  }

  ################################################################
  ## Check that the output prefix has been specified
  unless ($main::outfile{prefix}) {
    &RSAT::error::FatalError("You must define the output prefix (option -o).");
  }

  ################################################################
  ## Non-recognized parameters are ignored
  if (scalar(@args_to_pass)) {
    $args_to_pass = join (" ", @args_to_pass);
    &RSAT::message::Warning("Unrecognized arguments are ignored", $args_to_pass) if ($main::verbose >= 2);
  }

  local $basename;
  ($dir{output}, $basename) = &RSAT::util::SplitFileName($main::outfile{prefix});
  $dir{output} = "." if ($dir{output} eq "");
  &RSAT::util::CheckOutDir($dir{output});
  local $title = $basename;

  ## Create a BG model folder and assign a file name
  ## when the '-bginput' option is specified
  if($bg_input_flag == 1){
    local $bg_dir = $main::outfile{prefix}."_bg_model";
    &RSAT::util::CheckOutDir($bg_dir);

    $main::infile{bg_file} = $bg_dir."/mkv_" . $markov . "_2str.oligos";
    $main::outfile{bg_file_inclusive} = $bg_dir."/mkv_" . $markov . "_2str.inclusive";
    if($diff_flag){
	$main::infile{bg_file_control} = $bg_dir."/mkv_" . $markov . "_2str_control.oligos";
	$main::outfile{bg_file_inclusive_ctrl} = $bg_dir."/mkv_" . $markov . "_2str_control.inclusive";
    }

  } elsif($main::infile{bg_file}){
      local $bg_dir = $main::outfile{prefix}."_bg_model";
      &RSAT::util::CheckOutDir($bg_dir);
      
      $main::outfile{bg_file_inclusive} = $bg_dir."/converted_innput.inclusive";
  }
  

  ## Output file names
  $main::outfile{filtered_sequences} = $main::outfile{prefix}."_filtered_sequences.fasta";
  $main::outfile{random_sequences} = $main::outfile{prefix}."_randomized_sequences.fasta";
  $main::outfile{filtered_sequences_control} = $main::outfile{prefix}."_filtered_control_sequences.fasta";
  $main::outfile{random_sequences_control} = $main::outfile{prefix}."_randomized_control_sequences.fasta";
  $main::outfile{motifs_transfac} = $main::outfile{prefix}."_input_matrix_transfac.tf";
  $main::outfile{motifs_transfac_parsed} = $main::outfile{prefix}."_input_matrix_transfac_parsed.tf";
  $main::outfile{random_motifs_transfac} = $main::outfile{prefix}."_input_matrix_transfac_permuted.tf";
  $main::outfile{matches_tab} = $main::outfile{prefix}."_matrix_scan_results.tab";
  $main::outfile{matches_tab_PARSED} = $main::outfile{prefix}."_matrix_scan_results_PARSED.tab";
  $main::outfile{matches_tab_control} = $main::outfile{prefix}."_matrix_scan_results_control.tab";
  $main::outfile{matches_tab_PARSED_control} = $main::outfile{prefix}."_matrix_scan_results_PARSED_control.tab";
  $main::outfile{sequence_names} = $main::outfile{prefix}."_matrix_scan_sequence_names.tab";
  $main::outfile{sequence_names_control} = $main::outfile{prefix}."_matrix_scan_sequence_names_control.tab";
  $main::outfile{motif_ID_to_name} = $main::outfile{prefix}."_TF_ID_name_correspondence.tab";

  $main::outfile{all_profiles} = $main::outfile{prefix}."_positional_profiles.pdf";
  $main::outfile{profiles_tab} = $main::outfile{prefix}."_profiles.tab";
  $main::outfile{profiles_counts} = $main::outfile{prefix}."_counts_per_bin_profiles.tab";
  $main::outfile{profiles_heatmap} = $main::outfile{prefix}."_profiles_heatmap.pdf";
  $main::outfile{report} = $main::outfile{prefix}."_scan_profile_report.html";
  $main::outfile{report_temp} = $main::outfile{prefix}."_scan_profile_report_temp.html";
  $main::outfile{report_template} = $ENV{RSAT}."/public_html/templates_html/dynamic_positional_profiles.html";
  $main::outfile{report_temp_diff} = $main::outfile{prefix}."_diff_scan_profile_report_temp.html";
  $main::outfile{report_template_diff} = $ENV{RSAT}."/public_html/templates_html/dynamic_positional_profiles_differential_mode.html";
 

  ## Archive to facilitate transfer of all the results in a zip file
  $main::outfile{archive} = $main::outfile{prefix}."_archive.zip";
  $param{archive_format} = "zip";
  &RSAT::message::Info("Archive", $main::outfile{archive}) if ($main::verbose >= 3);

  $main::outfile{log} = $main::outfile{prefix}."_log.txt"; push @outfiles, "log";
  $main::out = &OpenOutputFile($main::outfile{log});

  ## Error file should contain only errors
  $main::outfile{err_log} = $main::outfile{prefix}."_errors.txt"; push @outfiles, "err_log";
  $main::err = &OpenOutputFile($main::outfile{err_log});

  ## Specific log file for R commands
  $main::outfile{Rlog} = $main::outfile{prefix}."_Rlog.txt"; push @outfiles, "Rlog";

  ################################################################
  ## Ensure the access to the java libraries, which are required to
  ## display the results (logo trees, dynamic tables).
  ##
  ## If $include_js_lib is set to 1, the javascript libraries are
  ## included in the output directory, in order to avoid problems with
  ## the links. This solution enables to move the result
  ## (e.g. download a self-contained archive), but costs 500kb of disk
  ## space for each result, we should evaluate alternative solutions.
  ## 
  ## the alternative is to point to the libraries on the RSAT server,
  ## but we faced problems on some servers, due to the the path
  ## public_html/lib, which inludes a soft link (lib ->
  ## ../perl-scripts/lib).
  local $include_js_lib = 1; 

  ## Define the base directories for the javascripts, which are
  ## required to display logo trees, animations and dynamic tables
  if ($include_js_lib) {

      &RSAT::message::Debug("Copying javascript libraries to output directory") if ($main::verbose >= 5);
      my $js_sync_cmd = "rsync -ruptl";
      $js_sync_cmd .= " ".$ENV{RSAT}."/perl-scripts/lib/js";
      $js_sync_cmd .= " ".$dir{output};
      &doit($js_sync_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
      $js_base = $dir{output}."/js";
      &RSAT::message::Info("Javascript libraries copied to output directory", $js_base) if ($main::verbose >= 5);

  }  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";
  }
  $c3_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/c3-0.4.10/c3.js");
  $c3_css_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/c3-0.4.10/c3.css");
  $d3_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/d3.v3.min.js");
  $jquery_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/DataTables-1.10.4/media/js/jquery.js");
  $datatable_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/DataTables-1.10.4/media/js/jquery.dataTables.min.js");
  $datatable_css_base = &RSAT::util::RelativePath($main::outfile{report}, $js_base."/DataTables-1.10.4/media/css/jquery.dataTables.min.css");

  ################################################################
  ## Calculate background of the input sequences
  #if ($bg_input_flag == 1) {
      &CalculateBGModel();
  #}

  ################################################################
  ## Calculate the sequence length
  ## For the moment the input are sequences of same length
  &ProcessSeq();      

  ################################################################
  ## Convert the input motif file to transfac
  ## If required, select the X top or tail matrices
  ## If required, permute the matrices
  &ProcessMatrices();

  ################################################################
  ## Initialize HTML report, 
  &OpenSynthesis() if ($main::param{progressive_synthesis});
  
  ################################################################
  ## Scan step: scan + parsing results + generate logos
  if( defined($selected_tasks{"scan"}) || defined($selected_tasks{"all"}) ){

      ################################################################
      ## Run matrix-scan quick
      &ScanSequences();
      
      ################################################################
      ## Produce the ID to Motif name reference table
      &ID_NameRefTable();
  }

  ################################################################
  ## Plots step: chi-squared calculation + draw profiles
  if( defined($selected_tasks{"plots"}) || defined($selected_tasks{"all"}) ){

      ################################################################
      ## Produce the logos
      &GenerateLogos();

      ## Parse the matrix-scan results table
      &ParseScanResults();

      ################################################################
      ## Compute statistics (X2 pval, eval, qval) 
      ## Draw the dynamic profiles
      ## These steps are executed in R
      if($diff_flag){
	  ## For differential mode
	  &DynamicProfilesDiffR();
      } else {
	  ## For non-differential mode
	  &DynamicProfilesR();
      }
  }

  ################################################################
  ## Initialize HTML report, 
  &ReOpenSynthesis();

  ################################################################
  ## Create an archive with all result files
  # if (-e $main::outfile{report}) {
      &Archive(1);
  # } else {
  #     &RSAT::error::FatalError($main::outfile{report}, "was not generated.");
  # }
 
  #######################################
  ## Delete temporal files and folders
  #&Delete_temporal_files();

  ################################################################
  ## Print verbose
  &Verbose() if ($main::verbose >= 1);

  ################################################################
  ## Report execution time and close output stream
  &close_and_quit();
}

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


################################################################
## Close output file and quit
sub close_and_quit {

  ## Report execution time
  my $exec_time = &RSAT::util::ReportExecutionTime($start_time); ## This has to be exectuted by all scripts
  print $main::out $exec_time if ($main::verbose >= 1); ## only report exec time if verbosity is specified

  ## Close output file
  if ($outfile{output}) {
    close $main::out;
    &RSAT::message::TimeWarn("Output file", $outfile{output}) if ($main::verbose >= 2);
  }

  ## CLOSE OTHER FILES HERE IF REQUIRED

  exit(0);
}


################################################################
## 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) >= 1) {
    $arg = shift (@arguments);


=pod

=head1 OPTIONS

=over 4

=item B<-v #>

Level of verbosity (detail in the warning messages during execution)

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


=pod

=item B<-h>

Display full help message

=cut
    } elsif ($arg eq "-h") {
      &PrintHelp();


=pod

=item B<-help>

Same as -h

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

=pod

=item B<-seq input_sequences_file>

A file containing the sequences in fasta format.

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


=pod

=item B<-seq_format sequence_format>

Sequence format.

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

=pod

=item B<-seq_control control_sequences_file>

A file containing the control sequences in fasta format.

=cut

    } elsif ($arg eq "-seq_control") {
	$main::infile{sequences_control} = shift(@arguments);
	$diff_flag = 1;

=pod

=item B<-seq_control_format sequence_format>

Control sequences format.

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

=pod

=item B<-matrix input_motif_file>

The input file contains a set of position-specific scoring
matrices.

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


=pod

=item B<-matrix_format matrix_format>

Specify the input matrix format.


B<Supported matrix formats>

Since the program takes several matrices as input, it only accepts
matrices in formats supporting several matrices per file (transfac,
tf, tab, cluster-buster, cb, infogibbs, meme, stamp, uniprobe).

For a description of these formats, see the help of I<convert-matrix>.

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

      unless ($supported_matrix_format{$matrix_format}) {
	&RSAT::error::FatalError($matrix_format, "Invalid format for input matrices\tSupported: ".$main::supported_matrix_formats);
      }


=pod

=item	B<-title title>

Title displayed on top of the report page.

=cut
     } elsif ($arg eq "-title") {
      $main::title = shift(@arguments);
      $main::title =~ s/\s+/_/g;

=pod

=item B<-top_matrices X>

Only analyze the first X motifs of the input file. This options is
convenient for quick testing before starting the full analysis.

=cut
    } elsif ($arg eq "-top_matrices") {
      $top_matrices = shift(@arguments);
      $top_matrix_flag = 1;

      &RSAT::error::FatalError($top_matrices, "Invalid value for option -top_matrices: must be a natural number") 
         unless (&IsNatural($top_matrices));

=pod

=item B<-skip_matrices X>

Skip the first X motifs of the input file. This options is convenient
for testing the program on a subset of the motifs before starting the
full analysis.

=cut
    } elsif ($arg eq "-skip_matrices") {
      $skip_matrices = shift(@arguments);
      $skip_matrix_flag = 1;
      &RSAT::error::FatalError($skip_matrices, "Invalid value for option -skip_matrices: must be a natural number") 
         unless (&IsNatural($skip_matrices));


=pod

=item B<-top_sequences X>

Only analyze the first X sequences of the input sequence file.
=cut
    } elsif ($arg eq "-top_sequences") {
      $top_sequences = shift(@arguments);
      $top_seq_flag = 1;

      &RSAT::error::FatalError($top_sequences, "Invalid value for option -top_sequences: must be a natural number") 
         unless (&IsNatural($top_sequences));

=pod

=item B<-skip_sequences X>

Skip the first X sequences of the input sequence file. 

=cut
    } elsif ($arg eq "-skip_sequences") {
      $skip_sequences = shift(@arguments);
      $skip_seq_flag = 1;
      &RSAT::error::FatalError($skip_sequences, "Invalid value for option -skip_matrices: must be a natural number") 
         unless (&IsNatural($skip_sequences));



=pod

=item B<-bin bin_length>

The length of the bin (in bp).

Default: 50

=cut
    } elsif ($arg eq "-bin") {
      $bin_size = shift(@arguments);
      &RSAT::error::FatalError($bin_size, "Invalid value for option -bin_size: must be a natural number") 
         unless (&IsNatural($bin_size));

=pod

=item B<-pval p_value>

Select only those matches with a p-value equal or lower than the
specified.

Default: 1e-3

=cut

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

=pod

=item B<-legend_pos legend_position>

The place where the legend will be inserted in the profile plot.

Default: bottom

Supported: bottom,side

=cut

    } elsif ($arg eq "-legend_pos") {
      $legend_pos = shift(@arguments);
      unless(exists($supported_legend_pos{$legend_pos})) {
	&RSAT::error::FatalError($legend_pos, "Invalid position. Supported:", $supported_legend_pos);
      }

=pod

=item B<-heatmap_dendogram>

Indicate if the dendogram in the profiles heatmap should be visible or not.

Default: show

Supported: show,hide

=cut

    } elsif ($arg eq "-heatmap_dendogram") {
      $heatmap_dendo = shift(@arguments);

      unless(exists($supported_heatmap_dendo_pos{$heatmap_dendo})) {
	&RSAT::error::FatalError($heatmap_dendo, "Invalid option. Supported:", $supported_heatmap_dendo_pos);
      }

=pod

=item B<-bgfile background_file>

A file containing the background model used to scan the sequences.

=cut
	} elsif ($arg eq "-bgfile") {
	    $bg_file_flag = 1;
	    $main::infile{bg_file} = shift(@arguments);


=pod

=item B<-bg_format background_file>

Format for the background model file.

        Supported formats: all the input formats supported by
        I<convert-background-model>.

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

=pod

=item B<-bginput>

Calculate background model from the input sequence set.

=cut

    } elsif ($arg eq "-bginput") {
	$bg_input_flag = 1;
      &RSAT::error::FatalError("Options -bgfile and -bginput are mutually exclusive") if (($bg_file_flag) && ($bg_input_flag));

=pod

=item B<-markov>

Order of the markov chain for the background model.

This option is incompatible with the option -bgfile.

=cut
    } elsif ($arg eq "-markov") {
      $markov = shift(@arguments);
      &RSAT::error::FatalError("Markov order must be a natural number.")
	unless &RSAT::util::IsNatural($markov);
      &RSAT::error::FatalError("The options -markov and -bgfile are mutually exclusive.")
	if (($bg_file_flag) && ($bg_input_flag));

=pod

=item B<-rand_motifs>

Scan the sequences with the randomly permuted input matrices.

Use this option as negative control.

=cut
    } elsif ($arg eq "-rand_motifs") {
      $random_motifs_flag = 1;

=pod

=item B<-rand_seq>

The input sequences are randomly permuted (thus the interdependence of nucleotides is lost).

If option -bg_file is selected, the Background model is calculated from
these shuffled sequences.

Use this option as negative control.

=cut
    } elsif ($arg eq "-rand_seq") {
      $random_seq_flag = 1;

=pod

=item	B<-heatmap_color_palette Color_Palette>

Select the color palette used in the heatmaps (divergent scales)
The color palettes (and their names) are taken from ColorBrewer2 website (http://colorbrewer2.org/)

Supported: Spectral,RdYlGn,RdYlBu,RdGy,RdBu,PuOr,PRGn,PiYG,BrBG

Default: RdBu
=cut

    } elsif ($arg eq "-heatmap_color_palette") {
         $heatmap_color_palette = shift(@arguments);
         unless(exists($supported_heatmap_color_palette{$heatmap_color_palette})) {
	   &RSAT::error::FatalError($heatmap_color_palette, "Invalid hclust method. Supported:", $supported_heatmap_color_palette);
         }

=pod

=item	B<-heatmap_color_classes X>

This option specifies in how many color classes the color palette will be divided.

For sequential color palettes: max 9
For diverging color palettes: max 11

If the user specified a color greater than the maximum allowed, the program takes this maximum value.

For more information see ColorBrewer2 website (http://colorbrewer2.org/)

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

      &RSAT::error::FatalError($heatmap_color_classes, "Invalid value for option -top_matrices: must be a natural number") 
         unless (&IsNatural($heatmap_color_classes));

=pod

=item B<-task tasks>

Specify one or several tasks to be run. If this option is not
specified, all the tasks are run.

Note that some tasks depend on others. This option should thus be
used with caution, by advanced users only.

Supported tasks: (all, scan, plots)

=over

=item B<all>

Execute all the parts of the program (default)

=item B<scan>

Run the motif scaning step with I<matrix-scan>. Usually this is the slower step.
Generate a table with the putative TFBSs of each PSSMs on the input sequences. 

=item B<plots>

Skip the matrix scan step (if the I<matrix-scan> results already exists) and only executes the step where the 
p-values are calculated and the plots are generated.

This option is ideal to saving time once the scaning has been done. 

=back

=cut

       } elsif ($arg eq "-task") {
	 $arg = shift (@arguments);
	 chomp($arg);
	 my @tasks = split ",", $arg;
         %selected_tasks = ();
	 foreach my $task (@tasks) {
	   $task = lc($task);
	   if ($supported_tasks{$task}) {
	     $selected_tasks{$task} = 1;
	   } else {
	     &RSAT::error::FatalError(join("\t", $task, "Invalid tasks. Supported:", $supported_tasks));
	   }
	 }

=pod

=item B<-diff>

Activate the differential mode where the distribution of TFBSs in the input sequences
are compared relative the control sequences.

=cut
    } elsif ($arg eq "-diff") {
      $diff_flag = 1;

=pod

=item	B<-o output_prefix>

Prefix for the output files and folders.

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

    } else {
      &FatalError(join("\t", "Invalid option", $arg));

    }
 }

=pod

=back

=cut

}

################################################################
## Verbose message
sub Verbose {
  print $out "; template ";
  &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 "; Output files\n";
    while (my ($key,$value) = each %main::outfile) {
      printf $out ";\t%-13s\t%s\n", $key, $value;
    }
  }
}


################################################################
## Scan the input sequences with the input matrices using
## RSAT matrix-scan
sub ProcessMatrices {

    &RSAT::message::TimeWarn("Processing input matrices") if ($main::verbose >= 2);

    $process_motif_cmd = $SCRIPTS."/convert-matrix";
    $process_motif_cmd .= " -i ".$main::infile{motifs};
    $process_motif_cmd .= " -from ".$matrix_format;
    $process_motif_cmd .= " -to transfac";

    ## If motif permutations are selected
    $process_motif_cmd .= " -perm 1" if $random_motifs_flag;

    ## If top or skip matrices are required
    $process_motif_cmd .= " -top ".$top_matrices if $top_matrix_flag;
    $process_motif_cmd .= " -skip ".$skip_matrices if $skip_matrix_flag;
    $process_motif_cmd .= " -o ".$main::outfile{motifs_transfac};
    
    &doit($process_motif_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);

    ## Given that some characters produce errors in R or CSS, they are substituted by "_"
    my ($parsed_tf_file) = &RSAT::util::OpenOutputFile($main::outfile{motifs_transfac_parsed});
    my ($non_parsed_tf_file) = &RSAT::util::OpenInputFile($main::outfile{motifs_transfac});

    while(<$non_parsed_tf_file>){

	next if (/^#/); ## Skip header line
	next if (/^;/); ## Skip comment lines
	next unless (/\S/); ## Skip empty lines	
	chomp();

	if( (/^\s*AC\s+/) || (/^\s*ID\s+/) ){

	    $_ =~ s/-/_/gi;
	    $_ =~ s/\./_/gi;
	    $_ =~ s/::/_/gi;
	    #$_ =~ s/\s+/_/gi;
	}

	print $parsed_tf_file $_."\n";
    }
    close($non_parsed_tf_file);
    close($parsed_tf_file);

    $main::infile{motifs} = $main::outfile{motifs_transfac_parsed};
}


################################################################
## Scan the input sequences with the input matrices using
## RSAT matrix-scan
sub ScanSequences {

    ## Initialize the sequences array
    my @sequence_sets = ();
    push(@sequence_sets, $main::infile{sequences});

    ## If the diff mode is activated, then add the control sequences
    ## to be processed as the query sequences
    if($diff_flag){
	push(@sequence_sets, $main::infile{sequences_control});
    }

    ## Process each set of sequence
    
    my $seq_counter = 0;
    foreach my $seq (@sequence_sets){

	$seq_counter++;
	&RSAT::message::Info("Matrices loaded from file", $main::infile{motifs}) if ($main::verbose >= 2);
	&RSAT::message::TimeWarn("Scanning sequences") if ($main::verbose >= 2);
	

	
	if($seq_counter == 1){
	    $s = $main::infile{sequences};
	    $so = $main::outfile{matches_tab};
	    $bg = $main::outfile{bg_file_inclusive};


	} elsif($seq_counter == 2){
	    $s = $main::infile{sequences_control};
	    $so = $main::outfile{matches_tab_control};

	    if($bg_input_flag){

		$bg = $main::outfile{bg_file_inclusive_ctrl};
#		$bg = $main::infile{bg_file_inclusive_control};
	    } 
	    
	} 
	
	$matrix_scan_cmd = $SCRIPTS."/matrix-scan -v ".($main::verbose);
	$matrix_scan_cmd .= " -m ".$main::infile{motifs};
	$matrix_scan_cmd .= " -matrix_format ".$matrix_format;
	$matrix_scan_cmd .= " -origin end -n score";
	$matrix_scan_cmd .= " -uth pval ".$p_value;
	$matrix_scan_cmd .= " -i ".$seq." -seq_format fasta";
	$matrix_scan_cmd .= " -pseudo 1 -decimals 1 ".$strands." -bg_pseudo 0.01";
	$matrix_scan_cmd .= " -return limits -return pval -ac_as_name";
	$matrix_scan_cmd .= " -quick -o ".$so;
	$matrix_scan_cmd .= " -bgfile ".$bg." -bg_format inclusive";
	
	&doit($matrix_scan_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);

	if($seq_counter == 1){
	    &RSAT::message::TimeWarn("matrix-scan file results", $main::outfile{matches_tab}) if ($main::verbose >= 2);
	} elsif($seq_counter == 2){
	    &RSAT::message::TimeWarn("matrix-scan file results", $main::outfile{matches_tab_control}) if ($main::verbose >= 2);
	}
    }
}


################################################################
## Parse the matrix-scan result table.
## This is done because as the table is read and loaded by R
## and this requires a lot of memory, the table is cut to only 
## those columns required to draw the profiles.
sub ParseScanResults {

    ## Initialize the sequences array
    my @sequences = ();
    push(@sequences, $main::infile{sequences});

    ## If the diff mode is activated, then add the control sequences
    ## to be processed as the query sequences
    if($diff_flag){
	push(@sequences, $main::infile{sequences_control});
    }

    ## Process each set of sequences
    my $seq_counter = 0;
    foreach my $s (@sequences){
	
	$seq_counter++;
	if($seq_counter == 1){
	    &RSAT::message::TimeWarn("Parsing matrix-scan results - Query", $main::outfile{matches_tab}) if ($main::verbose >= 2);
	    $m = $main::outfile{matches_tab};
	    $sn = $main::outfile{sequence_names};
	    $scanned = $main::outfile{matches_tab_PARSED};

	} elsif ($seq_counter == 2){
	    &RSAT::message::TimeWarn("Parsing matrix-scan results - Control", $main::outfile{matches_tab_control}) if ($main::verbose >= 2);
	    $m = $main::outfile{matches_tab_control};
	    $sn = $main::outfile{sequence_names_control};
	    $scanned = $main::outfile{matches_tab_PARSED_control};
	}

	## Extract the name and counts the input sequences 
	$input_sequences_cmd = "more ".$m;
	$input_sequences_cmd .= " | grep -v ';' | grep limit | cut -f1 | uniq ";
	$input_sequences_cmd .= " > ".$sn;
	&doit($input_sequences_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
	
	&RSAT::message::TimeWarn("Scanned sequence names", $sn) if ($main::verbose >= 2);
	
	## Extract somet fields in the matrix-can table
	$parse_cmd = " grep -v '^;' ".$m;
	$parse_cmd .= " | awk -F '\t'  ' ".'$2!="limit" && ($11 >= 3) {print $1"\t"$3"\t"($6+$5)/2"\t"$9"\t"$8}'." ' ";
	$parse_cmd .= " > ".$scanned;
	&doit($parse_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
   
	&RSAT::message::TimeWarn("PARSED matrix-scan file results", $scanned) if ($main::verbose >= 2);
    }

    if($seq_counter == 1){
	$to_delete{'matched_tab_PARSED'} = $main::outfile{matches_tab_PARSED};
    } elsif ($seq_counter == 2){
	$to_delete{'matched_tab_PARSED_control'} = $main::outfile{matches_tab_PARSED_control};
    }
}

################################################################
## Create an associative list of the motif ID -> name
## This is done because sometimes we have redundancy in the motif set and hence
## their names can be repeated and although the ID is unique, this is not so 
## informative to display it.
sub ID_NameRefTable {

    &RSAT::message::TimeWarn("Generating ID -> Name reference table") if ($main::verbose >= 2);

    ## Open the ID to Motif name reference table
    my ($ID_to_Motif_name_file) = &RSAT::util::OpenOutputFile($main::outfile{motif_ID_to_name});

    ################################################
    ## Save the unique ID in a hash table
    ## Key = ID unique
    ## Value = Motif name
    my ($transfac_matrix_file) = &OpenInputFile($main::infile{motifs});
    my ($AC_flag, $name_flag, $null, $AC_unique, $motif_ID) = 0;
    while(<$transfac_matrix_file>){

	next if (/^#/); ## Skip header line
	next if (/^;/); ## Skip comment lines
	next unless (/\S/); ## Skip empty lines	
	chomp();

	## Get the AC (unique)
	if(/^\s*AC\s+/){
	    ($null, $AC_unique) = split(/\s+/, $_);
	}

	## Get the ID (motif name)
	if(/^\s*ID\s+/){
	    ($null, $motif_ID) = split(/\s+/, $_);

	    ## Print the ID -> Name in the File
	    print $ID_to_Motif_name_file  $AC_unique."\t".$motif_ID."\n";
	    ($AC_flag, $name_flag, $AC_unique, $motif_ID) = 0;
	}
    }
    close($transfac_matrix_file);
    close($ID_to_Motif_name_file);

    &RSAT::message::TimeWarn("ID to Motif name correspondence table", $main::outfile{motif_ID_to_name}) if ($main::verbose >= 2);
}


################################################################
## Generate the Motif Logos
sub GenerateLogos {

    &RSAT::message::TimeWarn("Generating logos from input matrices") if ($main::verbose >= 2);

    $logos_cmd = $SCRIPTS."/convert-matrix";
    $logos_cmd .= " -i ".$main::infile{motifs};
    $logos_cmd .= " -from ".$matrix_format;
    $logos_cmd .= " -to transfac";
    $logos_cmd .= " -return logo -logo_program seqlogo";
    $logos_cmd .= " -logo_format png -logo_dir ".$main::outfile{prefix}."_logos";
    &doit($logos_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
}


################################################################
## Call the Rscript where the statistics are calculated
## (Chi-squared, p-val, q-val, e-val)
##
## Within this script the dynamic profiles are drawn and exported
## in a HTML file.
sub DynamicProfilesR {

    &RSAT::message::TimeWarn("Calculating Chi-squared values for positional profiles of TFBSs") if ($main::verbose >= 2);

    ##################################
    ### Identify the path of the R executable
    my $r_path = &RSAT::server::GetProgramPath("R");

    my $profiles_script  = $ENV{RSAT}."/R-scripts/Scan_profile.R";
    &RSAT::error::FatalError("Cannot read Motif scan profile script", $profiles_script) unless (-r $profiles_script);
    # $r_verbosity = &RSAT::stats::max(($main::verbose-1), 0);

    ## Basic parameters
    my $profile_cmd = "";
    $profile_cmd .= " cat ".$profiles_script;
    $profile_cmd .= " | ".$r_path;
    $profile_cmd .= " --slave --no-save --no-restore --no-environ --vanilla";
    $profile_cmd .= " --args \"";
    $profile_cmd .= " matrix.scan.file = '".$main::outfile{matches_tab_PARSED}."'";
    $profile_cmd .= "; sequence.names.file = '".$main::outfile{sequence_names}."'";
    $profile_cmd .= "; p.val = '".$p_value."'";
    $profile_cmd .= "; bin = '".$bin_size."'";
    $profile_cmd .= "; prefix = '".$main::outfile{prefix}."'";
    $profile_cmd .= "; logo.folder = '".$basename."_logos/'";
    $profile_cmd .= "; results.folder = '".$dir{output}."'";
    $profile_cmd .= "; basename = '".$basename."'";
    $profile_cmd .= "; ID.to.names.correspondence.tab = '".$main::outfile{motif_ID_to_name}."'";
    $profile_cmd .= "; seq.length = '".$seq_length."'";
    $profile_cmd .= "; individual.plots = '".$individual_plots."'";
    $profile_cmd .= "; heatmap.dendo = '".$heatmap_dendo."'";
    $profile_cmd .= "; html.template.file = '".$main::outfile{report_template}."'";
    $profile_cmd .= "; c3.css.base = '".$c3_css_base."'";
    $profile_cmd .= "; c3.base = '".$c3_base."'";
    $profile_cmd .= "; d3.base = '".$d3_base."'";
    $profile_cmd .= "; jquery.base = '".$jquery_base."'";
    $profile_cmd .= "; datatable.base = '".$datatable_base."'";
    $profile_cmd .= "; datatable.css.base = '".$datatable_css_base."'";
    $profile_cmd .= "; heatmap.color.palette = '".$heatmap_color_palette."'";
    $profile_cmd .= "; heatmap.color.classes = '".$heatmap_color_classes."'";
    $profile_cmd .= " \"";
#    $Cluster_motifs_cmd = "(".$cluster_motifs_cmd.")"; # Uncomment this line to check the R output in the terminal
#    $profile_cmd = "(".$profile_cmd.") 2 > ".$main::outfile{Rlog}; 

    if ($r_path) {
        &doit($profile_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
    } else {
        &RSAT::message::Warning("Could not run position scan because the program R is not available") if ($main::verbose >= 1);
    }
    return();
}


################################################################
## Call the Rscript where the statistics are calculated
## (Chi-squared, p-val, q-val, e-val) - Differential mode 
##
## Within this script the dynamic profiles are drawn and exported
## in a HTML file.
sub DynamicProfilesDiffR {

    &RSAT::message::TimeWarn("Calculating differential Chi-squared values for positional profiles of TFBSs in Query and Control sequences") if ($main::verbose >= 2);

    ##################################
    ### Identify the path of the R executable
    my $r_path = &RSAT::server::GetProgramPath("R");

    my $profiles_script  = $ENV{RSAT}."/R-scripts/Scan_profile_diff.R";
    &RSAT::error::FatalError("Cannot read Motif scan profile script", $profiles_script) unless (-r $profiles_script);
    # $r_verbosity = &RSAT::stats::max(($main::verbose-1), 0);

    ## Basic parameters
    my $profile_cmd = "";
    $profile_cmd .= " cat ".$profiles_script;
    $profile_cmd .= " | ".$r_path;
    $profile_cmd .= " --slave --no-save --no-restore --no-environ";
    $profile_cmd .= " --args \"";
    $profile_cmd .= " matrix.scan.file.query = '".$main::outfile{matches_tab_PARSED}."'";
    $profile_cmd .= "; matrix.scan.file.control = '".$main::outfile{matches_tab_PARSED_control}."'";
    $profile_cmd .= "; sequence.names.file.query = '".$main::outfile{sequence_names}."'";
    $profile_cmd .= "; sequence.names.file.control = '".$main::outfile{sequence_names_control}."'";
    $profile_cmd .= "; p.val = '".$p_value."'";
    $profile_cmd .= "; bin = '".$bin_size."'";
    $profile_cmd .= "; prefix = '".$main::outfile{prefix}."'";
    $profile_cmd .= "; logo.folder = '".$basename."_logos/'";
    $profile_cmd .= "; results.folder = '".$dir{output}."'";
    $profile_cmd .= "; basename = '".$basename."'";
    $profile_cmd .= "; ID.to.names.correspondence.tab = '".$main::outfile{motif_ID_to_name}."'";
    $profile_cmd .= "; seq.length = '".$seq_length."'";
    $profile_cmd .= "; individual.plots = '".$individual_plots."'";
    $profile_cmd .= "; heatmap.dendo = '".$heatmap_dendo."'";
    $profile_cmd .= "; html.template.file = '".$main::outfile{report_template_diff}."'";
    $profile_cmd .= "; c3.css.base = '".$c3_css_base."'";
    $profile_cmd .= "; c3.base = '".$c3_base."'";
    $profile_cmd .= "; d3.base = '".$d3_base."'";
    $profile_cmd .= "; jquery.base = '".$jquery_base."'";
    $profile_cmd .= "; datatable.base = '".$datatable_base."'";
    $profile_cmd .= "; datatable.css.base = '".$datatable_css_base."'";
    $profile_cmd .= "; heatmap.color.palette = '".$heatmap_color_palette."'";
    $profile_cmd .= "; heatmap.color.classes = '".$heatmap_color_classes."'";
    $profile_cmd .= " \"";
#    $Cluster_motifs_cmd = "(".$cluster_motifs_cmd.")"; # Uncomment this line to check the R output in the terminal
#    $profile_cmd = "(".$profile_cmd.") 2 > ".$main::outfile{Rlog}; 

    if ($r_path) {
        &doit($profile_cmd, 0, 1, $verbose, 0, "", $main::out, $main::err);
    } else {
        &RSAT::message::Warning("Could not run position scan because the program R is not available") if ($main::verbose >= 1);
    }
    return();
}


################################################################
## Calculate sequence length
sub ProcessSeq {

    ## Initialize the sequences array
    my @sequences = ();
    push(@sequences, $main::infile{sequences});

    ## If the diff mode is activated, then add the control sequences
    ## to be processed as the query sequences
    if($diff_flag){	
	push(@sequences, $main::infile{sequences_control});
    }

    ## Process each set of sequence
    my $seq_counter = 0;
    foreach my $s (@sequences){
	$seq_counter++;
	&RSAT::message::TimeWarn("Calculating Sequence length") if ($main::verbose >= 2);

	$seq_length_cmd = $SCRIPTS."/sequence-lengths";
	$seq_length_cmd .= " -i ".$s;
	$seq_length_cmd .= " -unit bp -in_format ".$main::seq_format;
	$seq_length_cmd .= " | cut -f2 | uniq | head -n 1";
	
	chomp($seq_length = `$seq_length_cmd`);

	## Save the sequence length of the query and input sequences
	## if they are not the same, the program ends
	if($seq_counter == 1){
	    $seq_length_query = $seq_length;
	} elsif ($seq_counter == 2){
	    $seq_length_control = $seq_length;
	}

	&RSAT::error::FatalError($seq_length, "Invalid value for sequence length: must be a natural number") 
	    unless (&IsNatural($seq_length));
	
	my $seq_length_up = $seq_length + 1;
	my $seq_length_dw = $seq_length - 1;
    

	if($seq_counter == 1){
	    &RSAT::message::Info("Query Sequences length: ", $seq_length, "bp") if ($main::verbose >= 2);	
	    &RSAT::message::Info("Filtering sequences shorter or longer than", $seq_length) if ($main::verbose >= 2);
	} elsif($seq_counter == 2){
	    &RSAT::message::Info("Control Sequences length: ", $seq_length, "bp") if ($main::verbose >= 2);	
	    &RSAT::message::Info("Filtering sequences shorter or longer than", $seq_length) if ($main::verbose >= 2);
	}
	
	$convert_seq_cmd = $SCRIPTS."/convert-seq";
	$convert_seq_cmd .= " -i ".$s;
	$convert_seq_cmd .= " -from ".$main::seq_format." -to ".$main::seq_format;
	$convert_seq_cmd .= " -skip_long ".$seq_length_up;
	$convert_seq_cmd .= " -skip_short ".$seq_length_dw;
	$convert_seq_cmd .= " -top ".$top_sequences if($top_seq_flag == 1);
	$convert_seq_cmd .= " -skip ".$skip_sequences if($skip_seq_flag == 1);

	## Indicate the proccessed sequences file name
	if($seq_counter == 1){
	    $convert_seq_cmd .= " -o ".$main::outfile{filtered_sequences};
	} elsif($seq_counter == 2){
	    $convert_seq_cmd .= " -o ".$main::outfile{filtered_sequences_control};
	}
	&doit($convert_seq_cmd, $dry, $die_on_error, $verbose, 0, $job_prefix);
	
	################################################################
	## If it is specified randomize the input sequences
	if($random_seq_flag){
	    
	    &RSAT::message::TimeWarn("Random permutation of the sequences") if ($main::verbose >= 2);
	    
	    $random_seq_cmd = $SCRIPTS."/random-seq";

	## Indicate the proccessed sequences file name
	if($seq_counter == 1){
	    $random_seq_cmd .= " -i ".$main::outfile{filtered_sequences};
	    $random_seq_cmd .= " -o ".$main::outfile{random_sequences};
	} elsif($seq_counter == 2){
	    $random_seq_cmd .= " -i ".$main::outfile{filtered_sequences_control};
	    $random_seq_cmd .= " -o ".$main::outfile{random_sequences_control};
	}


	    &doit($random_seq_cmd, $dry, $die_on_error, $verbose, 0, $job_prefix);
	    
	    $main::infile{sequences} = $main::outfile{random_sequences};
	    $to_delete{'random_sequences'} = $main::outfile{random_sequences};
	    if($diff_flag){
		$main::infile{sequences_control} = $main::outfile{random_sequences_control};
		$to_delete{'random_sequences_control'} = $main::outfile{random_sequences_control};
	    }
	    
	} else { 
	    $main::infile{sequences} = $main::outfile{filtered_sequences};
	    $to_delete{'filtered_sequences'} = $main::outfile{filtered_sequences};

	    if($diff_flag){
		$main::infile{sequences_control} = $main::outfile{filtered_sequences_control};
		$to_delete{'filtered_sequences'} = $main::outfile{filtered_sequences_control};
	    }

	}	
#	return($seq_length);
    }

    if($seq_counter >= 2){
	unless ($seq_length_query == $seq_length_control) {
	&RSAT::error::FatalError("The length of the query and control sequences differs.");
    }
    }

}


##############################################################
## When the option -top is used the analysis is restricted 
## to the first X motifs, however the input motif file is 
## splitted on individual files, although not all of them 
## are not. This functions will delete those files
sub Delete_temporal_files {

  foreach my $f (keys %to_delete) {
    unlink($to_delete{$f});
  }

  foreach my $fd (keys %to_delete_folder) {
    rmtree($to_delete_folder{$fd});
  }

}


##############################################################
## Calculate the BG model from the input seuences
sub CalculateBGModel {

   ## Initialize the sequences array
    my @sequences = ();
    push(@sequences, $main::infile{sequences});

    if($bg_input_flag == 1){
	
	## If the diff mode is activated, then add the control sequences
	## to be processed as the query sequences
	if($diff_flag){
	push(@sequences, $main::infile{sequences_control});
	}
	
	## Process each set of sequence
	my $seq_counter = 0;
	foreach my $s (@sequences){
	    $seq_counter++;
	    
	    if($seq_counter == 1){
		&RSAT::message::TimeWarn("Calculating background model from Query sequences", $bg_dir) if ($main::verbose >= 2);
	    } elsif ($seq_counter == 2){
		&RSAT::message::TimeWarn("Calculating background model from Control sequences", $bg_dir) if ($main::verbose >= 2);
	    }
	    
	    my $bg_comand = $SCRIPTS."/oligo-analysis -v 1 -quick ".$strands;
	    $bg_comand .= " -i ".$s." -l ".$markov." -noov ";
	    
	    if($seq_counter == 1){
		$bg_comand .= " -o ".$main::infile{bg_file};
	    } elsif ($seq_counter == 2){
		$bg_comand .= " -o ".$main::infile{bg_file_control};
		
	    }
	    
	    &doit($bg_comand, $dry, $die_on_error, $verbose, 0, $job_prefix);
	    if($seq_counter == 1){
		&RSAT::message::TimeWarn("Background for sequence set", $s, $main::infile{bg_file}) if ($main::verbose >= 2);
	    } elsif ($seq_counter == 2){
		&RSAT::message::TimeWarn("Background for sequence set", $s, $main::infile{bg_file_control}) if ($main::verbose >= 2);
	    }
	    $bg_format = "oligos";
	    
	    my $convert_bg_cmd = "";
	    ## Convert background model in INCLUSIVE format for matrix-scan-quick
	    $convert_bg_cmd = $SCRIPTS."/convert-background-model -from oligos -to inclusive ";
	    
	    if($seq_counter == 1){
		$convert_bg_cmd .= " -i ".$main::infile{bg_file};
	    } elsif ($seq_counter == 2){
		$convert_bg_cmd .= " -i ".$main::infile{bg_file_control};
	    }
	    
	    if($seq_counter == 1){
		$convert_bg_cmd .= " -o ".$main::outfile{bg_file_inclusive};
	    } elsif ($seq_counter == 2){
		$convert_bg_cmd .= " -o ".$main::outfile{bg_file_inclusive_ctrl};
	    }
	    &doit($convert_bg_cmd, $dry, $die_on_error, $verbose, 0, $job_prefix);
	}
    }  elsif ($main::infile{bg_file}){
##If a bg input file was given convert it to inclusive
    	$convert_bg_cmd = $SCRIPTS."/convert-background-model -from oligos -to inclusive ";
	$convert_bg_cmd .= " -i ". $main::infile{bg_file};
	$convert_bg_cmd .= " -o ".$main::outfile{bg_file_inclusive};
	&doit($convert_bg_cmd, $dry, $die_on_error, $verbose, 0, $job_prefix);
	return;

    }
}

################################################################
## 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);

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

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

  ## Archive all data and results
  my ($archive_dir, $archive) = &SplitFileName($main::outfile{archive});
  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::param{archive_format} eq "zip") {
    $cmd .= "(cd ".$archive_dir_dir." ; ";
    $cmd .= " zip -ryq ".$archive_rel_path." ".$to_archive_rel_path;
    $cmd .= " -x ".$archive;
    $cmd .= ")";
  } elsif (($main::param{archive_format} eq "tar") ||
	   ($main::param{archive_format} eq "tgz")) {
    $cmd .= "tar -cpf ".$main::outfile{archive};
    $cmd .= " -z" if ($main::param{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::param{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 ReOpenSynthesis {

    ## Open the summary HTML file + temporal report 
    if($diff_flag){
	$main::outfile{report_temp} = $main::outfile{report_temp_diff};
    }
    my ($syn) = &OpenInputFile($main::outfile{report});
    my ($syn2) = &OpenOutputFile($main::outfile{report_temp});

  
    my $head = &PrintHtmlResultHeader(program=>"position-scan", "title"=>$main::title);

  ######################################
  ## Read the HTML report
  ## Add the header and command line
  while(<$syn>){
      
      chomp;

      ## Substitute the Header
      if($_ =~ /--he--/){
	  $_ =~ s/--he--/$head/;
      }

      ## Substitute the Command section
      if($_ =~ /--show_command--/){

	  ## Print arguments
	  print $syn2 &open_menu_heading(1, "<a name='logs'></a><h3>Command</h3>", 1);
	  print $syn2 "<pre>";
	  print $syn2 "position-scan ";
	  &PrintArguments($syn2);
	  print $syn2 "</pre>";
	  print $syn2 &close_menu_heading();

	  $_ =~ s/--show_command--//;
      }

      print $syn2 $_."\n";
  }

  close($syn);
  close($syn2);

  ## Rename the files
  system("mv ".$main::outfile{report_temp}." ".$main::outfile{report});
}

__END__
