package AnalysisFunctions;
use strict;
=head1 Class:AnalysisFunctions

=head2 Attributes

=over 4

=item 1
$self->{AlignACE} - The command line argument required to call AlignACE

=item 2
$self->{AlignACEBackground} - The background gc content used with AlignACE

=item 3
$self->{BioProspector} - The command line argument required to call BioProspector

=item 4
$self->{MDscan} - The command line argument required to call MDscan

=item 5
$self->{Background} - The background file used with MDscan and BioProspector

=item 6
$self->{MEME} - The command line argument required to call MEME

=item 7
$self->{MEMEBackground} - The background Markov file used with MEME

=item 8
$self->{ScanACE} - The command line argument required to call ScanACE

=item 9
$self->{ScanACEBackground} - The background sequence file used with ScanACE

=item 10
$self->{ScanSites} - Maximum number of ScanACE sites to list

=item 11
$self->{CompareACE} - The command line argument required to call CompareACE

=item 12
$self->{MotifStats} - The command line argument required to call MotifStats

=item 13
$self->{Tree} - The command line argument required to call Tree

=item 14
$self->{ListClusters} - The command line argument required to call ListClusters.pl

=item 15
$self->{TransfacMotifs} - The file containing transfac motifs

=item 16
$self->{SequenceFile} - The test set sequence file used for motif finding

=item 17
$self->{Temp} - This is directory to store temporary information

=back

=head2 Methods


=head3 new


=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
A new uninitialized AnalysisFunctions object

=back

=head4 Description

=over 4

=item 1
Constructor. Returns a new AnalysisFunctions object.  All attributes still need to be set

=back

=cut

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = {};
    $self->{AlignACE} = 'AlignACE';
    $self->{AlignACEBackground} = undef;    
    $self->{BioProspector} = 'BioProspector';
    $self->{MDscan}   = 'MDscan';
    $self->{Background} = undef;
    $self->{MEME} = 'meme';
    $self->{MEMEBackground} = undef;
    $self->{ScanACE} = 'ScanACE';
    $self->{ScanACEBackground} = undef;
    $self->{ScanSites} = undef;
    $self->{CompareACE} = 'CompareACE';
    $self->{MotifStats} = 'MotifStats';
    $self->{Tree} = 'Tree';
    $self->{ListClusters} = 'list_clusters.pl';
    $self->{TransfacMotifs} = undef;
    $self->{SequenceFile} = undef;
    $self->{Temp} = undef;
    bless($self, $class);
    return $self;
};

sub load_config{
    my $self = shift;
    my $file = shift;
    open (FH, "< $file");
    while(<FH>){
        if($_ =~ /AlignACE\:(\S+)/){$self->{AlignACE} = $1};
        if($_ =~ /BioProspector\:(\S+)/){$self->{BioProspector} = $1};
        if($_ =~ /MDscan\:(\S+)/){$self->{MDscan} = $1};
        if($_ =~ /meme\:(\S+)/){$self->{MEME} = $1};
        if($_ =~ /ScanACE\:(\S+)/){$self->{ScanACE} = $1};
        if($_ =~ /CompareACE\:(\S+)/){$self->{CompareACE} = $1};
        if($_ =~ /MotifStats\:(\S+)/){$self->{MotifStats} = $1};
        if($_ =~ /Tree\:(\S+)/){$self->{Tree} = $1};
        if($_ =~ /list_clusters.pl\:(\S+)/){$self->{ListClusters} = $1};
    };
    close FH;
};

=head3 DESTROY

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
Destructor. Destroys the current AnalysisFunctions object

=back

=cut

sub DESTROY {
    my $self = shift;
    return;
};

=head3 set_background_files

=head4 Parameters

=over 4

=item 1
Name of the ScanACE background file

=item 2
Name of the MDscan and BioProspector background file

=item 3
Name of the MEME background file

=item 4
Name of the AlignACE background file

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets the background files that are used for motif finding

=back

=cut

sub set_background_files{
    my $self = shift;
    $self->{ScanACEBackground} = shift;
    $self->{Background} = shift;
    $self->{MEMEBackground} = shift;
    open (FH, "< $self->{MEMEBackground}");
    my $g = undef;
    my $c = undef;
    while(<FH>){
        my $line = $_;
        chomp $line;
        if ($line =~ /G\s+(\S+)/){$g = $1};
        if ($line =~ /C\s+(\S+)/){$c = $1};
        if (defined $g and defined $c){last};
    }
    close FH;
    my $gc = $g + $c;
    $self->{AlignACEBackground} = $gc;
    return;
};

=head3 set_transfac_files

=head4 Parameters

=over 4

=item 1
Name of the file containing transfac motifs in AlignACE format

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets the location of the tranfac motifs that will be used for comparison with motif finding results

=back

=cut

sub set_transfac_files{
    my $self = shift;
    $self->{TransfacMotifs} = shift;
};

sub set_alignace{my $self = shift; $self->{AlignACE} = shift};
sub set_alignace_background{my $self = shift; $self->{AlignACEBackground} = shift};
sub set_bioprospector{my $self = shift; $self->{BioProspector} = shift};
sub set_mdscan{my $self = shift; $self->{MDscan} = shift};
sub set_background{my $self = shift; $self->{Background} = shift};
sub set_meme_background{my $self = shift; $self->{MEMEBackground} = shift};
sub set_meme{my $self = shift; $self->{MEME} = shift};
sub set_scanace_background{my $self = shift; $self->{ScanACEBackground} = shift};
sub set_scanace{my $self = shift; $self->{ScanACE} = shift};
sub set_compareace{my $self = shift; $self->{CompareACE} = shift};
sub set_motifstats{my $self = shift; $self->{MotifStats} = shift};
sub set_tree{my $self = shift; $self->{Tree} = shift};
sub set_list_clusters{my $self = shift; $self->{ListClusters} = shift};
sub set_transfac_motifs{my $self = shift; $self->{TransfacMotifs} = shift};
sub set_sequence{my $self = shift; $self->{SequenceFile} = shift};
sub set_scansites{my $self = shift; $self->{ScanSites} = shift};

=head3 run_alignace

=head4 Parameters

=over 4

=item 1
The name of the output file for motif finding results

=item 2
Number of active columns during motif search

=item 3
Expect value for AlignACE

=item 4
Oversample increases the number of motifs found

=item 5
Minimum number of passes before returning results

=item 6
Seed value that is used for the random number generator

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an AlignACE run and then starts the program

=back

=cut

#align_ace($infile, $outfile, $expect, $oversample, $minpass, $numcols, $seed);
sub run_alignace{
    my $self = shift;
    my $outfile =  shift;
    my $numcol = shift;
    my $expect = shift;
    my $oversample = shift;
    my $minpass = shift;
    my $seed = shift;
    my @align = ($self->{AlignACE},
                 '-i', $self->{SequenceFile},
                 '-gcback', $self->{AlignACEBackground},
                 '-expect', $expect,
                 '-oversample', $oversample,
                 '-minpass', $minpass,
                 '-numcols', $numcol,
                 '-seed', $seed);
    print "Starting AlignACE\:\n";
    for my $i (0 .. $#align){
        print"$align[$i] ";
    };
    my $file = `@align`;
    print "\nAlignACE run finished\n";
    open (FILE, "> $outfile");
    print FILE $file;
    close FILE;
    return;
};

=head3 run_mdscan

=head4 Parameters

=over 4

=item 1
The name of the output file for motif finding results

=item 2
Width of motif to search for during motif search

=item 3
Number of candidate motifs to report

=item 4
Number of motifs to scan

=item 5
Number of refinement iterations

=item 6
Number of top sequences to look for candidate motifs

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an MDscan run and then starts the program

=back

=cut
#$programs->run_mdscan($outfile, $width, $options{m}, '50', '10', '20');
sub run_mdscan{
    my $self = shift;
    my $outfile = shift;
    my $numcol = shift;
    my $numrep = shift;
    my $nummotif = shift;
    my $numref = shift;
    my $topseq = shift;
    my @mdscan = ($self->{MDscan},
                  '-i', $self->{SequenceFile},
                  '-b', $self->{Background},
                  '-o', $outfile,
                  '-w', $numcol,
                  '-s', $nummotif,
                  '-r', $numrep,
                  '-n', $numref,
                  '-t', $topseq,
                  '-g', '1'
    );
    print "Starting MDscan\:\n";
    for my $i (0 .. $#mdscan){
        print"$mdscan[$i] ";
    };
    system @mdscan;
    print "\nMDscan run completed\n";
    return;
};

=head3 run_bioprospector

=head4 Parameters

=over 4

=item 1
The name of the output file for motif finding results

=item 2
Width of motif to search for during motif search

=item 3
Number of candidate motifs to report

=item 4
Number of motifs to scan

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an BioProspector run and then starts the program

=back

=cut

sub run_bioprospector{
    my $self = shift;
    my $outfile = shift;
    my $numcol = shift;
    my $numrep = shift;
    my $topseq = shift;
    my $maxgap = int($numcol/3);
    my $secmot = $maxgap;
    if ($secmot < 4){$secmot = 4};
    my @biopro = ($self->{BioProspector},
                  '-i', $self->{SequenceFile},
                  '-b', $self->{Background},
                  '-o', $outfile,
                  '-W', $numcol,
                  '-n', $numrep,
                  '-T', $topseq,
                  '-w', $secmot,
                  '-G', $maxgap);
    print "Starting BioProspector\:\n";
    for my $i (0 .. $#biopro){
        print"$biopro[$i] ";
    };
    system @biopro;
    print "\nBioProspector run completed\n";
    return;
};

=head3 run_meme

=head4 Parameters

=over 4

=item 1
The name of the output file for motif finding results

=item 2
Minimum motif width to search

=item 3
Maximum motif width to search

=item 4
Number of motifs to find

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an MEME run and then starts the program

=back

=cut

sub run_meme{
    my $self = shift;
    my $outfile = shift;
    my $mincol = shift;
    my $maxcol = shift;
    my $nummotifs = shift;
    my @meme = ($self->{MEME}, $self->{SequenceFile},
                '-dna', '-mod', 'tcm', '-revcomp',
                '-bfile', $self->{MEMEBackground},
                '-maxsize', '2000000',
                '-minw', "$mincol",
                '-maxw', "$maxcol",
                '-text',
                '-nostatus',
                '-nmotifs', $nummotifs,
                '-minsites', '10');
    print "Starting MEME\:\n";
    for my $i (0 .. $#meme){
        print"$meme[$i] ";
    };
    my $file = `@meme`;
    print "\nMEME run completed\n";
    open (FILE, "> $outfile");
    print FILE $file;
    close FILE;
    return;
};

=head3 run_meme_fixed

=head4 Parameters

=over 4

=item 1
The name of the output file for motif finding results

=item 2
Minimum motif width to search

=item 3
Maximum motif width to search

=item 4
Number of motifs to find

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an MEME run and then starts the program

=back

=cut

sub run_meme_fixed{
    my $self = shift;
    my $outfile = shift;
    my $width = shift;
    my $nummotifs = shift;
    my @meme = ($self->{MEME}, $self->{SequenceFile},
                '-dna', '-mod', 'tcm', '-revcomp',
                '-bfile', $self->{MEMEBackground},
                '-maxsize', '2000000',
                '-w', $width,
                '-text',
                '-nostatus',
                '-nmotifs', $nummotifs,
                '-minsites', '10');
    print "Starting MEME\:\n";
    for my $i (0 .. $#meme){
        print"$meme[$i] ";
    };
    my $file = `@meme`;
    print "\nMEME run completed\n";
    open (FILE, "> $outfile");
    print FILE $file;
    close FILE;
    return;
};

=head3 run_compareace

=head4 Parameters

=over 4

=item 1
First input file name 

=item 2
Second input file name

=item 3
Output file name

=item 4
Pearson correlation coefficent cutoff

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an CompareACE run and then starts the program

=back

=cut

#This function uses CompareACE to 
#determine the similarity between two
#AlignACE files using a specified
#cutoff score
sub run_compareace{
    my $self = shift;
    my $file1 = shift;
    my $file2 = shift;
    my $outfile =  shift;
    my $cutoff = shift;
    my @comp = ($self->{CompareACE},
                 $file1,
                 $file2,
                 '-c', $cutoff);
    print "Starting CompareACE\:\n";
    for my $i (0 .. $#comp){
        print"$comp[$i] ";
    };
    my $filehold = `@comp`;
    print "\nCompareACE run finished\n";
    open (FILE, "> $outfile");
    print FILE $filehold;
    close FILE;
    return;
};

=head3 run_compare_transfac

=head4 Parameters

=over 4

=item 1
First input file name 

=item 2
Output file name

=item 3
Pearson correlation coefficent cutoff

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up an CompareACE run with a set of transfac motifs

=back

=cut

sub run_compare_transfac{
    my $self = shift;
    my $file1 = shift;
    my $outfile =  shift;
    my $cutoff = shift;
    my @comp = ($self->{CompareACE},
                 $file1,
                 $self->{TransfacMotifs},
                 '-c', $cutoff);
    print "Starting CompareACE\:\n";
    for my $i (0 .. $#comp){
        print"$comp[$i] ";
    };
    my $filehold = `@comp`;
    print "\nCompareACE run finished\n";
    open (FILE, "> $outfile");
    print FILE $filehold;
    close FILE;
    return;
};

=head3 run_compareace_self

=head4 Parameters

=over 4

=item 1
First input file name 

=item 2
Output file name

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function sets up a CompareACE run that checks the correlation between all the motifs in an single alignace file

=back

=cut


#This function does a CompareACE run
#that compares all motifs in a file
#against itself with no score cutoff.
sub run_compareace_self{
    my $self = shift;
    my $file = shift;
    my $outfile =  shift;
    my @comp = ($self->{CompareACE},
                 $file,
                 $file);
    print "Starting CompareACE\:\n";
    for my $i (0 .. $#comp){
        print"$comp[$i] ";
    };
    my $filehold = `@comp`;
    print "\nCompareACE run finished\n";
    open (FILE, "> $outfile");
    print FILE $filehold;
    close FILE;
    return;
};

=head3 run_tree

=head4 Parameters

=over 4

=item 1
First input file name 

=item 2
Output file name

=item 3
Correlation coefficent used to define clusters

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function performs heuristic clustering with Tree using the results from CompareACE

=back

=cut

sub run_tree{
    my $self = shift;
    my $file = shift;
    my $outfile = shift;
    my $cutoff = shift;
    my @tree = ($self->{Tree},
                 $file,
                 '-c', $cutoff);
    print "Starting Tree\:\n";
    for my $i (0 .. $#tree){
        print"$tree[$i] ";
    };
    my $filehold = `@tree`;
    print "\nTree run finished\n";
    open (FILE, "> $outfile");
    print FILE $filehold;
    close FILE;
    return;
};

=head3 run_scanace

=head4 Parameters

=over 4

=item 1
First input file name 

=item 2
Standard Deviation cutoff when searching for motif sites

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function uses scanace to search for sites in the given background file using the standard deviation cutoff

=back

=cut

#
sub run_scanace{
    my $self = shift;
    my $infile = shift;
    my $dev = shift;
    my @scanner = ($self->{ScanACE},
                   '-i', $infile,
                   '-all',
                   '-c', $dev,
                   '-m', $self->{ScanSites},
                   '-g', $self->{AlignACEBackground},
                   '-x', '-z', $self->{ScanACEBackground});
    print "Starting ScanACE\:\n";
    for my $i (0 .. $#scanner){
        print"$scanner[$i] ";
    };
    system @scanner;
    print "\nScanACE run finished\n";
    return;
};

=head3 run_motifstats

=head4 Parameters

=over 4

=item 1
Input file name 

=item 2
Output file name

=item 3
Length to search when determining positional bias

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function uses MotifStats to calculate the statistics from an AlignACE file using ScanACE results

=back

=cut

#
sub run_motifstats{
    my $self = shift;
    my $infile =  shift;
    my $outfile = shift;
    my $length = shift;
    my @comp = ($self->{MotifStats},
                $infile,
                '-w', $length);
    print "Starting MotifStats\:\n";
    for my $i (0 .. $#comp){
        print"$comp[$i] ";
    };
    my $file = `@comp`;
    open (FILE, "> $outfile");
    print FILE $file;
    close FILE;
    print "\nMotifStats run finished\n";
    return;
};

=head3 run_list_clusters

=head4 Parameters

=over 4

=item 1
Input file name 

=item 2
Output file name

=item 3
Cutoff used to when assingning cluster membership

=back

=head4 Returns

=over 4

=item 1 
Nothing

=back

=head4 Description

=over 4

=item 1
This function converts the output from Tree into a more usable format

=back

=cut

sub run_list_clusters{
    my $self = shift;
    my $infile =  shift;
    my $outfile = shift;
    my $cutoff =  shift;
    my @comp = ('perl',
                $self->{ListClusters},
                $infile,
                $cutoff);
    print "Starting list_clusters\:\n";
    for my $i (0 .. $#comp){
        print"$comp[$i] ";
    };
    my $file = `@comp`;
    open (FILE, "> $outfile");
    print FILE $file;
    close FILE;
    print "\nlist_clusters run finished\n";
    return;
};

1
