package MotifFunctions;
use strict;
use MotifObject;
use ScanFunctions;
use ScanObject;
use Storable;
use XML::Writer;
use IO::File;

=head1 Class:MotifFunctions

=head2 Attributes

=over 4

=item 1
$self->{MOTIFS} - A reference to an array of MotifObjects

=item 2 
$self->{GENES} - A reference to a hash containing the names of all the genes whose sequence contained the motifs

=item 3
$self->{SEQFILE} - Not sure what the difference between this attribute and $self-{FILE}

=item 4
$self->{TRANSFAC} - A reference to a hash containing the transfac hits associated with each MotifObject ?

=item 5
$self->{FILE} - Name of the sequence file from which the MotifObjects stored in this object were derived

=item 6
$self->{GENOMEFILE} - Name of the ScanACE background file 

=back

=head2 Methods

=head3 new

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
MotifFunctions object

=back

=head4 Description

=over 4

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

=back

=cut

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = {};
    $self->{MOTIFS} = ();
    $self->{GENES} = {};
    $self->{FILE} = '';
    $self->{SEQFILE} = '';
    $self->{GENOMEFILE} = '';
    bless($self, $class);
    return $self;
};

=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 for the current MotifFunctions object.

=back

=cut

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

=head3 get_genes

=head4 Parameters

=over 4

item 1
Reference to an hash containing gene names

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
Sets the genes stored within the current MotifFunctions object

=back

=cut

sub get_genes {
    my $self = shift;
    my $arrayref = \%{$self->{GENES}};
    return $arrayref;
}

=head3 set_genes

=head4 Parameters

=over 4

=item 1
Reference to an hash containing gene names

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sets the genes stored within the current MotifFunctions object.

=back

=cut

sub set_genes {
    my $self = shift;
    my $arrayref = shift;
    $self->{GENES} = %{$arrayref};
    return;
}

=head3 load_genes

=head4 Parameters

=over 4

=item 1
Name of a file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sets the genes stored within the current MotifFunctions object.

=back

=cut

sub load_genes{
    my ($self, $file) = @_;
    open (FILE, "< $file");
    my %holder = ();
    while (<FILE>){
        if ($_ =~ /\>(\S+)/){ $holder{$1} = { id => '1' } }
    };
    close FILE;
    $self->{GENES} = \%holder;
    return;
};

=head3 get_motifs

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
Reference to a hash containing the genes names for the MotifFunctions object

=back

=head4 Description

=over 4

=item 1
Returns a hash reference to the genes stored within the current MotifFunctions object.

=back

=cut

sub get_motifs {
    my $self = shift;
    my $arrayref = \@{$self->{MOTIFS}};
    return $arrayref;
}

=head3 get_number_motifs

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Number of motifs in the specified MotifFunctions object

=back

=head4 Description 

=over 4

=item 1
Finds the number of motifs in a MotifFunctions object

=back

=cut

sub get_number_motifs{
    my $self = shift;
    if (!defined $self->{MOTIFS}){return 0};
    my $motifs = $#{$self->{MOTIFS}} + 1;
    return $motifs;
}

=head3 get_motif_sites

=head4 Parameters

=over 4

item 1
The number of a motif in a MotifFunctions object

=back

=head4
Returns

=over 4

=item 1
A hash containing all of the sites in a the specified motif

=back

=head4 Description 

=over 4

=item 1
This function is an accessor function allowing a MotifFunctions object to get all of the ScanACE sites for a motif

=back

=cut

sub get_motif_sites{
    my ($self, $motif) = @_;
    my %sites =  $self->{MOTIFS}[$motif]->get_scan_sites();
    return %sites;
};

=head3 set_motifs

=head4 Parameters


=over 4

=item 1
Reference to an array containing MotifObjects

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sets the MotifObjects stored within the current MotifFunctions object. 

=back

=cut
sub set_motifs {
    my $self = shift;
    my $arrayref = shift;
    $self->{MOTIFS} = @{$arrayref};
    return;
}

=head3 store_motifs

=head4 Parameters

=over 4

=item 1
File in which to store the current MotifFunctions object

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Serializes the current MotifFunctions object

=back

=cut

sub store_motifs {
    my $self = shift;
    my $file = shift;
    print "Storing motif file\:\n$file\n";
    store $self, "$file";
    return;
};

=head3 retrieve_motifs

=head4 Parameters

=over 4

=item 1
Name of a file containing a serialized MotifFunctions Object

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sets the attributes of the current MotifFunctions object equal to those of the retrieved MotifFunctions object

=back

=cut

sub retrieve_motifs {
    my $self = shift;
    my $file = shift;
    print "Loading motif file\:\n$file\n";
    my $hold = retrieve("$file");
    $self->{MOTIFS} = $hold->{MOTIFS};
    $self->{GENES} = $hold->{GENES};
    $self->{FILE} = $hold->{FILE};
    $self->{SEQFILE} = $hold->{SEQFILE};
    $self->{GENOMEFILE} = $hold->{GENOMEFILE};
    return;
};

=head3 scanace_stats

=head4 Parameters

=over 4

=item 1
Name of the sequence file used to generate the motifs

=item 2
Name of the background sequence file

=item 3
Name of the ScanACE file generated from the background file using the motif 

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Iterates through all of the motifs calling ScanFunction on each motif

=back

=cut

sub scanace_stats {
    my $self = shift;
    $self->{SEQFILE}= shift;
    $self->{GENOMEFILE} =  shift;
    $self->{FILE} = shift;
    print "Calculating ScanACE statistics\:\n";
    my $temp = $self->{FILE};
    $temp =~ s/\.ace$//;
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $motif = $self->{MOTIFS}[$i]->get_motif_number();
        my $file = "$temp\_n"."$motif"."\.scn";
        print "$file\n";
        my $scan = new ScanFunctions;
        $scan->analysis($file, $self->{SEQFILE}, $self->{GENOMEFILE}, \@{$self->{MOTIFS}[$i]->{GENES}});
        $self->{MOTIFS}[$i]->put_scanstats($scan);
    };
    return;
};

=head3 load_clusters

=head4 Parameters

=over 4

=item 1
Name of a file containing the clusters of motifs (output of list_clusters.pl)

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Associates cluster membership information with each MotifObject stored within the current MotifFunctions object

=back

=cut

sub load_clusters {
    my $self = shift;
    my $file = shift;
    my @array = ();
    my $motif = undef;
    print "Loading cluster information from\:\n$file\n";
    $/ = 'Cluster';
    open(FILE, "< $file");
    while (<FILE>){push @array, [split(/\n/, $_)]};
    for my $i (1 .. $#array){
        for my $j (0 .. $#{$array[$i]}){
            if ($array[$i][$j] =~ /\S+\t+(\d+)/){
                $motif = $1-1;
                $self->{MOTIFS}[$motif]->put_cluster($i);
            };
        };
    };
    $/ = "\n";
    return;
};

sub load_clusters_to_transfac {
    
};

=head3 get_clusters

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
A hash containing the names of the finders that found a motif belonging to a cluster

=back

=head4 Description

=over 4

=item 1
Identifies the motif finders that are associated with a given cluster of motif. This function requires that cluster membership has already been assigned.

=back

=cut

sub get_clusters {
    my $self = shift;
    my %clusters = ();
    print "Getting cluster information\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $clust = $self->{MOTIFS}[$i]->get_cluster();
        my $finder = $self->{MOTIFS}[$i]->get_program();
        $clusters{$clust}{$finder}++;
    }
    return %clusters;
};

=head3 load_finders

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads motif finder information into each MotifObject.  This function requires that cluster membership has already been assigned.

=back

=cut

sub load_finders {
    my $self = shift;
    my %clusters = $self->get_clusters();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $clust = $self->{MOTIFS}[$i]->get_cluster();
        my %finders = %{$clusters{$clust}};
        $self->{MOTIFS}[$i]->set_finders(\%finders);
    }
    return;
};

#this method lists the cluster membership of all clusters and the associated motif stats
#the parameters are as follows:

=head3 list_cluster_membership_stats

=head4 Parameters

=over 4

=item 1
Name of a file to which the cluster membership stats will be written

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Prints the membership and associated stats for each cluster and its associated motifs to file

=back

=cut

sub list_cluster_membership_stats{
    my $self = shift;
    my $outfile = shift;
    open (OUT, ">$outfile") || die "Unable to open $outfile \n";
    my $i;
    my %ref;
    for ($i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
	if (exists($ref{$cluster})) {
	    my @memberIds = @{$ref{$cluster}->{members}};
	    push @memberIds , $i;
	    my $holder = {
		members => \@memberIds,
		size => $#memberIds + 1
	    };
	$ref{$cluster} = $holder;
        }
        else {
	    my @memberIds;
	    push @memberIds , $i;
	    my $holder = {
		members => \@memberIds,
		size => $#memberIds + 1
	    };
	    $ref{$cluster} = $holder;
	}
    }
    foreach my $cluster (keys(%ref)) {
	my $holder= $ref{$cluster};
	print OUT "Cluster"." ".$cluster." (".$ref{$cluster}->{size}." Members):\n";
	my @members = @{$holder->{members}};
	foreach my $member (@members) {
	    print OUT ${$self->{MOTIFS}}[$member]->list_stats($member)."\n";
	}
	print OUT "\n";
    }
    close OUT;
    return;
};

=head3 numberBestClusters

=head4 Parameters

=over 4

=item 1
none

=back

=head4 Returns

=over 4

=item 1 
Number of best clusters within the current MotifFunctions object

=back

=head4 Description

=over 4

=item 1
Gives you the number of best clusters within the current MotifFunctions object

=item 2
Useful for figuring out how many motifs to list in AlignACE format

=back

=cut

sub numberBestClusters {
    my $self = shift;
    my %ref = ();
    my $i = undef;
    for ($i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for ($i = 0; $i <= $#temp; $i++){
        if (defined($ref{$i})){push @list, $ref{$i}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;
    my $numberOfClusters = $#sorted + 1;
    return $numberOfClusters;
};



=head3 multiple_member_clusters

=head4 Parameters

=over 4

=item 1
Name of the file to which those cluster with members from multiple motif finders will be outputted

=item 2
The minimum number of programs that had to have found the motifs within a cluster in order for the cluster to be outputted to file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Copies the best MotifFunctions and genes from the supplied MotifFunctions object into the current MotifFunctions object

=item 2
Best cluster motifs are defined as the highest ranking motifs with respect to the last sort_ method call


=back

=cut

sub copy_best_clusters {
	my $self = shift;
	my $allClusters = shift;
	print "Before: \n";
	my @motifs = @{$allClusters->{MOTIFS}};
	print "After : \n";
	my %ref = ();
    my $i = undef;
    for ($i = $#motifs; $i >= 0; $i--){
        my $cluster = $motifs[$i]->get_cluster();
        $ref{$cluster} = { id => $i};
    };
    my @temp = keys %ref;
    my @list = ();
    for ($i = 0; $i <= $#temp; $i++){
        if (defined($ref{$i})){push @list, $ref{$i}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;
    for (my $i = 0;$i <= $#sorted ;$i++) {
    	push @{$self->{MOTIFS}}, ${$allClusters->{MOTIFS}}[$sorted[$i]];
    }
    $self->{GENES} = $allClusters->{GENES};
    return;
}

sub screen_motif_blocks {
    my $self = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if ($self->{MOTIFS}[$i]->block_fail()){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
}

sub screen_motif_blocks_fail {
    my $self = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if (!$self->{MOTIFS}[$i]->block_fail()){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
}

sub screen_known_transfac {
    my $self = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if (!$self->{MOTIFS}[$i]->check_transfac_hits()){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
}

sub screen_unknown_transfac {
    my $self = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if ($self->{MOTIFS}[$i]->check_transfac_hits()){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
}

sub screen_number_finders {
    my $self = shift;
    my $min = shift;
    my $max = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my %list = %{$self->{MOTIFS}[$i]->get_finders()};
        my @array = keys %list;
        if ($#array >= $min -1 and $#array <= $max - 1){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
};

sub screen_repeats {
    my $self = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $found = 0;
        my $descriptor = $self->{MOTIFS}[$i]->get_descriptor();
        if (exists $$descriptor{PALENDROME}){$found = 1};
        if (exists $$descriptor{REPEAT}){$found = 1};
        if ($found){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
};

sub screen_group_cutoff {
    my $self = shift;
    my $cutoff = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if (!defined $self->{MOTIFS}[$i]->get_group()){next};
        if ($self->{MOTIFS}[$i]->get_group() <= $cutoff){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
}

=head3 multiple_member_clusters

=head4 Parameters

=over 4

=item 1
Name of an file to which the clusters with multiple members will be outputed

=item 2
Minimum number of unique program which the motifs objects within a cluster must have been generated by in order to be outputted to file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
This method outputs to file all of the clusters that contain motifs from at least n motif finders, where n is a user specified parameter

=item 2
This method will NOT work unless the program attribute of the MotifObjects stored within the current MotifFunctions object have been set
=back

=cut

sub multiple_member_clusters {
    my $self = shift;
    my $outfile = shift;
    my $minNumber = shift;
    my $i ;
    my %ref;
    for ($i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
	if (exists($ref{$cluster})) {
	    my @memberIds = @{$ref{$cluster}->{members}};
	    push @memberIds , $i;
	    my $holder = {
		members => \@memberIds,
		size => $#memberIds + 1
	    };
	$ref{$cluster} = $holder;
        }
        else {
	    my @memberIds;
	    push @memberIds , $i;
	    my $holder = {
		members => \@memberIds,
		size => $#memberIds + 1
	    };
	    $ref{$cluster} = $holder;
	}
    }
    open (OUT, ">$outfile" ) || die "Unable to open $outfile \n";	
    foreach my $cluster (keys(%ref)) {
	my $holder= $ref{$cluster};
	my @members = @{$holder->{members}};
	my %foundPrograms;
	foreach my $member (@members) {
	    print OUT ${$self->{MOTIFS}}[$member]->{PROGRAM}."\t".${$self->{MOTIFS}}[$member]->list_stats($member)."\n";
	    if (!exists($foundPrograms{${$self->{MOTIFS}}[$member]->{PROGRAM}})) {
		$foundPrograms{${$self->{MOTIFS}}[$member]->{PROGRAM}} = 1;
	    }
	}
	my @keys = keys (%foundPrograms);
	    if ($#keys + 1 >= $minNumber) {
	    print OUT "Cluster"." ".$cluster." (".$ref{$cluster}->{size}." Members):\n";
	    foreach my $member (@members) {
		print OUT ${$self->{MOTIFS}}[$member]->{PROGRAM}."\t".${$self->{MOTIFS}}[$member]->{TOTALRANK}."\t";
		print OUT ${$self->{MOTIFS}}[$member]->list_stats($member)."\n";
	    }
	    print OUT "\n";
	}
    }
    close OUT;
    return;
}

=head3 best_clusters

=head4 Parameters

=over 4

=item 1
Name of an file to which the best motifs will be written (in an AlignACE format file)

=item 2
Name of an file to which the best motifs' stats will be written 

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Best motifs are defined with respect to the last call to a sort_ method

=back

=cut

sub best_clusters{
    my $self = shift;
    my $file = shift;
    my $stats = shift;
    my %ref = ();
    my $i = undef;
    for ($i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for ($i = 0; $i <= $#temp; $i++){
        if (defined($ref{$temp[$i]})){push @list, $ref{$temp[$i]}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;

    open(OUT, "> $file");
    my @unique = keys %{$self->{GENES}};
    my %ref1 = ();
    for my $i (0 .. $#unique){$ref1{$unique[$i]} = {pos => $i}};
    print OUT "Input sequences\:\n";
    for my $i (0 .. $#unique){print OUT "\#$i\t$unique[$i]\n"};
    for my $i (0 .. $#sorted){
        my $motif = $i + 1;
        print OUT "\nMotif $motif\n";
        print OUT $self->{MOTIFS}[$sorted[$i]]->list_record(\%ref1) . "\n";
        print OUT $self->{MOTIFS}[$sorted[$i]]->get_actaster . "\n";
        print OUT "MAP Score\: ". $self->{MOTIFS}[$sorted[$i]]->get_motifscore;
        print OUT "\n";
    };
    close OUT;
    open(STAT, "> $stats");
    for my $i (0 .. $#sorted){
        my $motifnum = $i + 1;
        print STAT $self->{MOTIFS}[$sorted[$i]]->list_stats($motifnum) . "\n";
    };
    close STAT;
    return;
};

=head3 best_clusters_load

=head4 Parameters

=over 4

=item 1
Reference to a new MotifFunctions object that that will hold the highest scoring members of each motif cluster 

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
The highest scoring member of each cluster is loaded into a new MotifFunctions object

=back

=cut

sub best_clusters_load{
    my $self = shift;
    my $motifs = shift;
    my %ref = ();
    for (my $i = $#{$motifs->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $motifs->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for (my $i = 0; $i <= $#temp; $i++){
        if (defined($ref{$temp[$i]})){push @list, $ref{$temp[$i]}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;
    for my $i (0 .. $#sorted){
        push @{$self->{MOTIFS}}, $motifs->{MOTIFS}[$sorted[$i]]
    };
    for my $i (0 .. $#{$self->{MOTIFS}}){
        $self->{MOTIFS}[$i]->list_genes($self->{GENES});
    };
    return;
};

=head3 load_transfac_list

=head4 Parameters

=over 4

=item 1
Name of an file to containing a transfac format list of motifs

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads a transfac list into the current MotifFunctions object

=item 2
When comparing motifs identified to a transfac motifs file it is necessary to get the name of the appropriate transcription factor.  This info is not stored within the transfac motifs file and hence must be obtained from this list.

=back

=cut

sub load_transfac_list{
    my $self = shift;
    $self->{TRANSFAC} = ();
    print "Assigning Transfac ID's\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $motif = $i;
        my $gene = $self->{MOTIFS}[$i]->get_gene_element('0');
        $self->{TRANSFAC}{$gene} = { MOTIF => $motif };
    };
    return;
};

sub load_transfac{
    my $self = shift;
    my $transfile = shift;
    $self->load_alignace($transfile, 'all', 'AlignACE');
    $self->load_transfac_list();
    return;
};

=head3 get_transfac_list

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
The list of transfac motifs

=back

=head4 Description 

=over 4

=item 1
Gets the reference to the hash containing the transfac ids

=back

=cut

sub get_transfac_list{
    my $self = shift;
    return \%{$self->{TRANSFAC}};
};

=head3 put_transfac_list

=head4 Parameters

=over 4

item 1
Takes a reference to a hash containing tranfac ids

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function puts a tranfac list into a MotifFunctions object

=back

=cut

sub put_transfac_list{
    my $self = shift;
    my $hashref = shift;
    %{$self->{TRANSFAC}} = %{$hashref};
    return;
};

=head3 put_transfac_id

=head4 Parameters

=over 4

=item 1
Name of a file containing the transfac id lists

=item 2
Correlation to use to define transfac hits

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Needs a description

=back

=cut

sub put_transfac_id{
    my $self = shift;
    my $file = shift;
    my $value = shift;
    for my $i (0 .. $#{$self->{MOTIFS}}){
        $self->{MOTIFS}[$i]->set_correlation($value);
    };
    my %hash = ();
    $/ = "\n";
    print "Assigning transfac identifications\n$file\n";
    open(FILE, "< $file");
    while (<FILE>){
        chomp $_;
        my @params = split(/\t/, $_);
        my $motif = $params[1] - 1;
        my $id = $self->{TRANSFAC}{$params[3]}->{MOTIF};
        my $corr = $self->{MOTIFS}[$motif]->get_correlation;
        if($corr < $params[4]){
            $self->{MOTIFS}[$motif]->put_transfac_id($id, $params[4]);
        };
    };
    return;
};

sub put_transfac_id_pfm{
    my $self = shift;
    my $file = shift;
    my $value = shift;
    my $transfac = shift;
    my %hash = ();
    #for my $i (0 .. $#{$self->{MOTIFS}}){
    #    $self->{MOTIFS}[$i]->clear_transfac_hits();
    #};
    $/ = "\n";
    print "Assigning transfac identifications\n$file\n";
    open(FILE, "< $file");
    while (<FILE>){
        chomp $_;
        my ($motif_source, $index, $transfac_source, $transfac_index, $pearson) = split(/\t/, $_);
        $index--; $transfac_index--; 
        if ($index <= $#{$self->{MOTIFS}}){
            if($pearson >= $value){
                $self->{MOTIFS}[$index]->load_transfac_hit($pearson, $transfac_index, $transfac);
            };
        };
    };
    close FILE;
    return;
};

sub get_transfac_logos{
    my $self = shift;
    my @logos = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $logo =  $self->{MOTIFS}[$i]->get_logo();
        my $ori = $self->{MOTIFS}[$i]->get_orientation();
        my $element = { MOTIF => $logo, ORI => $ori };
        push @logos, $element;
    };
    return \@logos;
};

=head3 load_stats

=head4 Parameters

=over 4

=item 1
The name of a MotifStats file.

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads the MotifStats from the user specified MotifStats file into the current MotifFunctions object

=item 2
Statistics are associated with the correct MotifObject stored within the current MotifFunctions object

=back

=cut

sub load_stats{
    my $self = shift;
    my $file = shift;
    my $finder = shift;
    print "Loading MotifStats statistics\:\n$file\n";
    open(FILE, "< $file");
    my %hash = ();
    while (<FILE>){
        chomp;
        my @args = split(/\t/, $_);
        $hash{$finder}{$args[1]} = {file => $args[0],
                                    group => $args[3],
                                    posscore => $args[4],
                                    position => $args[5],
                                    consensus => $args[6]
                                    };
    };
    close FILE;
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my @args = $self->{MOTIFS}[$i]->get_info;
        if (defined $hash{$args[0]}{$args[1]}->{file}){
            $self->{MOTIFS}[$i]->put_stats($hash{$args[0]}{$args[1]}->{file},
                                    $hash{$args[0]}{$args[1]}->{group},
                                    $hash{$args[0]}{$args[1]}->{posscore},
                                    $hash{$args[0]}{$args[1]}->{position},
                                    $hash{$args[0]}{$args[1]}->{consensus}
                                    );
        };
    };
    return;
};

=head3 list_alignace

=head4 Parameters

=over 4

=item 1
Name of the file to which the an AlignACE format of the motifs stored within the current MotifFunctions object will be outputted

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Generates an AlignACE format file for all of the MotifObjects stored within the current MotifFunctions object

=back

=cut

sub list_alignace{
    my $self = shift;
    my $file = shift;
    my $number = shift;
    print "Listing AlignACE format file\:\n$file\n";
    if ($number =~ /all/){$number = $#{$self->{MOTIFS}} + 1 };
    $number = $number - 1;
    if ($number > $#{$self->{MOTIFS}}){$number = $#{$self->{MOTIFS}}};
    open(OUT, "> $file");
    my @unique = keys %{$self->{GENES}};
    my %ref = ();
    for my $i (0 .. $#unique){$ref{$unique[$i]} = {pos => $i}};
    print OUT "Input sequences\:\n";
    for my $i (0 .. $#unique){print OUT "\#$i\t$unique[$i]\n"};
    for my $i (0 .. $number){
        my $motif = $i + 1;
        print OUT "\nMotif $motif\n";
        print OUT $self->{MOTIFS}[$i]->list_record(\%ref) . "\n";
        print OUT $self->{MOTIFS}[$i]->get_actaster . "\n";
        print OUT "MAP Score\: ". $self->{MOTIFS}[$i]->get_motifscore;
        print OUT "\n";
        #if ($i < $#{$self->{MOTIFS}}){print OUT "\n"};
    };
    close OUT;
    return;
};

=head3 load_alignace

=head4 Parameters

=over 4

=item 1
Name of the AlignACE format file containing motifs

=item 2
The number of motifs to load into the current MotifFunctions object

=item 3
The name of the program that was the ultimate source of the AlignACE format file inputed

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads a user specified number of motifs from an AlignACE format file into the current MotifFunctions object.  MotifObjects are created for each of the corresponding motifs.

=item 2
If 'all' is specified as the number of motifs then all of the motifs within the AlignACE format file will be loaded

=back

=cut

#$proto->load_alignace($file, $number_of_motifs, $finder)
sub load_alignace{
    my $self = shift;
    my $file = shift;
    my $numbermotifs = shift;
    my $finder = shift;
    print "Loading AlignACE format file\:\n$file\n";
    $self->{FILE} = $file;
    $/ = 'Motif';
    my @array = ();
    my %refs = ();
    open(FILE, "< $file");
    while (<FILE>){push @array, [split(/\n/, $_)]};
    $/ = "\n";
    for my $i (0 .. $#{$array[0]}){
        if($array[0][$i] =~ /\#(\d+)\s+(\S+)/){
            my $number = $1;
            my $gene = $2;
            if ($gene =~ /(NM\_\d{6})\_\d+/){$gene = $1};
            #print "alignace $gene\n";
            $self->{GENES}{$gene} = { id => '1' };
            $refs{$number} = { id => $gene }
        };
    };
    if ($numbermotifs !~ /\d+/){$numbermotifs = $#array};
    if ($#array < $numbermotifs){$numbermotifs = $#array};
    for my $i (1 .. $numbermotifs){
        my $MotifRecord = MotifObject->new();
        if($array[$i][0] =~ /(\d+)/){$MotifRecord->put_origin($finder, $1)};
        for my $j (0 .. $#{$array[$i]}){
            if($array[$i][$j] =~ /([AGTC]+)\s+(\d+)\s+(\d+)\s+(\d+)/){
                my ($seq, $name, $pos, $ori) = ($1, $2, $3, $4);
                $MotifRecord->put_element($seq, $refs{$name}->{id}, $pos, $ori)
            };
            if($array[$i][$j] =~ /MAP Score\:\s+(\S+)/){$MotifRecord->put_motifscore($1)};
        };
        $MotifRecord->set_aster();
        $MotifRecord->set_actaster();
        push @{$self->{MOTIFS}}, $MotifRecord;
    };
    close FILE;
    for my $i (0 .. $#{$self->{MOTIFS}}){$self->{MOTIFS}[$i]->set_genes()};
    $self->calculate_pfms();
    return;
};

sub block_filter{
    my $self = shift;
    my $info = shift;
    my $blocksize = shift;
    my $correlation = shift;
    my $ungapped = shift;
    my $gapped = shift;
    foreach my $motif (@{$self->{MOTIFS}}){
        $motif->set_blocks($blocksize, $info); #build into data structure
    };
    $self->get_repeats('0', $correlation, $ungapped, $gapped);
    return;
};

=head3 load_bioprospector

=head4 Parameters

=over 4

=item 1
Name of the Bioprospector format file containing motifs

=item 2
The number of motifs to load into the current MotifFunctions object

=item 3
The name of the program that was the ultimate source of the BioProspector format file inputed

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads a user specified number of motifs from a BioProspector format file into the current MotifFunctions object.  MotifObjects are created for each of the corresponding motifs.

=item 2
If 'all' is specified as the number of motifs then all of the motifs within the BioProspector format file will be loaded

=back

=cut

sub load_bioprospector{
    my $self = shift;
    my $file = shift;
    my $numbermotifs = shift;
    my $finder = shift;
    print "Loading BioProspector format file\:\n$file\n";
    $self->{FILE} = $file;
    $/ = 'Motif #';
    my @array = ();
    my %refs = ();
    open(FILE, "< $file");
    while (<FILE>){push @array, [split(/\n/, $_)]};
    $/ = "\n";
    if ($#array < $numbermotifs){$numbermotifs = $#array};
    for my $i (1 .. $numbermotifs){
        my $MotifRecord = MotifObject->new();
        if($array[$i][0] =~ /(\d+)/){$MotifRecord->put_origin($finder, $1)};
        for my $j (0 .. $#{$array[$i]}){
            if($array[$i][$j] =~ /\>(\S+)\s+seg\s+\d+\s+([fr]+)(\d+)\s+\-\d+\s+([AGTC]+)/){
                my $gene = $1; my $direct = $2; my $distance = $3; my $seq = $4;
                if ($gene =~ /(NM\_\d{6})\_\d+/){$gene = $1};
                if ($direct =~ /f/){$direct = '1'}else{$direct = '0'};
                $self->{GENES}{$gene} = { id => '1' };
                $MotifRecord->put_element($seq, $gene, $distance, $direct)
            };
            if($array[$i][$j] =~ /MotifScore\s+(\S+)\;+/){$MotifRecord->put_motifscore($1)};
        };
        $MotifRecord->set_aster();
        $MotifRecord->set_actaster();
        push @{$self->{MOTIFS}}, $MotifRecord
    };
    close FILE;
    for my $i (0 .. $#{$self->{MOTIFS}}){$self->{MOTIFS}[$i]->set_genes()};
    $self->calculate_pfms();
    return;
};

=head3 load_mdscan

=head4 Parameters

=over 4

=item 1
Name of the MDscan format file containing motifs

=item 2
The number of motifs to load into the current MotifFunctions object

=item 3
The name of the program that was the ultimate source of the MDscan format file inputed

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads a user specified number of motifs from an MDscan format file into the current MotifFunctions object.  MotifObjects are created for each of the corresponding motifs.

=item 2
If 'all' is specified as the number of motifs then all of the motifs within the MDscan format file will be loaded

=back

=cut

sub load_mdscan{
    my $self = shift;
    my $file = shift;
    my $numbermotifs = shift;
    my $finder = shift;
    print "Loading MDscan format file\:\n$file\n";
    $self->{FILE} = $file;
    $/ = 'Mtf';
    my @array = ();
    my %refs = ();
    open(FILE, "< $file");
    while (<FILE>){push @array, [split(/\n/, $_)]};
    $/ = "\n";
    if ($#array < $numbermotifs){$numbermotifs = $#array};
    for my $i (1 .. $numbermotifs){
        my $MotifRecord = MotifObject->new();
        if($array[$i][0] =~ /(\d+)/){$MotifRecord->put_origin($finder, $1)};
        for my $j (0 .. $#{$array[$i]}){
            if($array[$i][$j] =~ /\>(\S+)\s+\S+\s+([bf]+)(\d+)\s+([AGTCN]+)/){
                my $gene = $1; my $direct = $2; my $distance = $3; my $seq = $4;
                if ($gene =~ /(NM\_\d{6})\_\d+/){$gene = $1};
                if ($direct =~ /f/){$direct = '1'}else{$direct = '0'};
                $self->{GENES}{$gene} = { id => '1' };
                $MotifRecord->put_element($seq, $gene, $distance, $direct)
            };
            if($array[$i][$j] =~ /Score1\s+(\S+)\s+Segment/){$MotifRecord->put_motifscore($1)};
        };
        $MotifRecord->set_aster();
        $MotifRecord->set_actaster();
        push @{$self->{MOTIFS}}, $MotifRecord
    };
    close FILE;
    for my $i (0 .. $#{$self->{MOTIFS}}){$self->{MOTIFS}[$i]->set_genes()};
    $self->calculate_pfms();
    return;
};

=head3 load_meme

=head4 Parameters

=over 4

=item 1
Name of the MEME format file containing motifs

=item 2
The number of motifs to load into the current MotifFunctions object

=item 3
The name of the program that was the ultimate source of the MEME format file inputed

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Loads a user specified number of motifs from an MEME format file into the current MotifFunctions object.  MotifObjects are created for each of the corresponding motifs.

=item 2
If 'all' is specified as the number of motifs then all of the motifs within the MEME format file will be loaded

=back

=cut

sub load_meme{
    my $self = shift;
    my $file = shift;
    my $numbermotifs = shift;
    my $finder = shift;
    print "Loading MEME format file\:\n$file\n";
    $self->{FILE} = $file;
    $numbermotifs = $numbermotifs - 1;
    $/ = 'Time';
    my @array = ();
    my %refs = ();
    open(FILE, "< $file");
    while (<FILE>){push @array, [split(/\n/, $_)]};
    $/ = "\n";
    if ($#array - 1 < $numbermotifs){$numbermotifs = $#array - 1};
    for my $i (0 .. $numbermotifs){
        my $MotifRecord = MotifObject->new();
        for my $j (0 .. $#{$array[$i]}){
            if($array[$i][$j] =~ /(\S+)\s+([\+\-]+)\s+(\d+)\s+\S+\s+[AGTCN]+\s+([AGTCN]+)\s+[AGTCN]+/){
                my $gene = $1; my $direct = $2; my $distance = $3; my $seq = $4;
                if ($gene =~ /(NM\_\d{6})\_\d+/){$gene = $1};
                if ($direct =~ /\+/){$direct = '1'} else{$direct = '0'};
                $self->{GENES}{$gene} = { id => '1' };
                $MotifRecord->put_element($seq, $gene, $distance, $direct)
            };
            if($array[$i][$j] =~ /MOTIF\s+(\d+)/){$MotifRecord->put_origin($finder, $1)};
            if($array[$i][$j] =~ /llr\s+\=\s+(\S+)\s+E\-value/){$MotifRecord->put_motifscore($1)};
            if($array[$i][$j] =~ /block/){last};
        };
        $MotifRecord->set_aster();
        $MotifRecord->set_actaster();
        push @{$self->{MOTIFS}}, $MotifRecord;
    };
    close FILE;
    for my $i (0 .. $#{$self->{MOTIFS}}){$self->{MOTIFS}[$i]->set_genes()};
    $self->calculate_pfms();
    return;
};

=head3 parse_transfac

=head4 Parameters

=over 4

=item 1
Output filename

=item 2
Organism type

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
This function creates a MotifFunctions object that will hold motifs generated from transfac

=back

=cut

#$proto->parse_transfac($file, $organism);
sub parse_transfac
{
    my $self = shift;
    my $file = shift;
    my $type = shift;
    my %motifs = ();    
    my @newarray = ();
    my @poshold = ();    
    $/ = '//';
    open(FILE, "< $file");
    while (<FILE>){push @newarray, [split(/\n/, $_)]};
    close FILE;
    $/ = "\n";
    my $link = { B => 'bacteria', F => 'fungi', I => 'insect', N => 'nematode', P => 'plant', V => 'vertebrate' };
    for my $a (0 .. $#newarray)
    {
        my ($transname, $organism, $transid, $quality, $name) = undef;
        @poshold = ();
        for my $b (0 .. $#{$newarray[$a]} - 1)
        {
            if ($newarray[$a][$b] =~ /AC\s+(.+)/) {$transname = $1 };
            if ($newarray[$a][$b] =~ /ID\s+(\w+)\$(\w+)\_(\S+)/) {$organism = $1; $transid = $2, $quality = $3  };
            if ($newarray[$a][$b] =~ /NA\s+(.+)/) {$name = $1 };
            if ($newarray[$a][$b] =~ /\d+\s+A\:(\d+\.\d+)\s+C\:(\d+\.\d+)\s+G\:(\d+\.\d+)\s+T\:(\d+\.\d+)/) {
                my $a = $1; my $c = $2; my $g = $3; my $t = $4; my $sum = $a + $c + $g + $t;
                my $af = $a/$sum; my $cf = $c/$sum; my $gf = $g/$sum; my $tf = $t/$sum;
                my $bases = { A => $af, C => $cf, G => $gf, T => $tf };
                push @poshold, $bases
            };
        };
        if ($organism !~ /$type/){next};
        $motifs{$link->{$organism}}{$transid}{$quality} = {PFM => [@poshold]}
    };
    my @genes = keys %{$motifs{$link->{$type}}};
    for my $i (0 .. $#genes){
        my @sources = keys %{$motifs{$link->{$type}}{$genes[$i]}};
        my @sorted = sort { $a cmp $b } @sources;
        my $holder = MotifObject->new();
        my @pfm = @{$motifs{$link->{$type}}{$genes[$i]}{$sorted[0]}->{PFM}};
        $self->{GENES}{$genes[$i]} = { id => '1' };
        $holder->load_pfm($motifs{$link->{$type}}{$genes[$i]}{$sorted[0]}->{PFM});
        $holder->pfm_to_motif($genes[$i]);
        $holder->set_aster();
        $holder->set_actaster();
        push @{$self->{MOTIFS}}, $holder;
    };
    print '';
    return;
};

sub parse_transfac_exp
{
    my $self = shift;
    my $file = shift;
    my @motifs = ();    
    my @newarray = ();
    my @poshold = ();    
    $/ = '>';
    open(FILE, "< $file");
    while (<FILE>){push @newarray, [split(/\n/, $_)]};
    close FILE;
    $/ = "\n";
    for my $i (1 .. $#newarray)
    {
        my ($transname, $organism, $transid, $quality, $name) = undef;
        @poshold = ();
        for my $j (0 .. $#{$newarray[$i]})
        {
            if ($newarray[$i][$j] =~ /\w+\t+(\d+\.\d+)\t+(\d+\.\d+)\t+(\d+\.\d+)\t+(\d+\.\d+)/) {
                my $a = $1; my $c = $2; my $g = $3; my $t = $4; my $sum = $a + $c + $g + $t;
                my $af = $a/$sum; my $cf = $c/$sum; my $gf = $g/$sum; my $tf = $t/$sum;
                my $bases = { A => $af, C => $cf, G => $gf, T => $tf };
                push @poshold, $bases
            };
        };
        my $holder = MotifObject->new();
        $holder->load_pfm(\@poshold);
        my $motifname = 'Mot'.$i;
        $self->{GENES}{$motifname} = { id => '1' };
        $holder->pfm_to_motif($motifname);
        $holder->set_aster();
        $holder->set_actaster();
        push @{$self->{MOTIFS}}, $holder;
    };
    return;
};

sub calculate_pfms{
    my $self = shift;
    foreach my $motif (@{$self->{MOTIFS}}){
        $motif->calculate_pfm();
    };
    return;
};

sub get_repeats{
    my $self = shift;
    my $info_cutoff = shift;
    my $correlation_cutoff = shift;
    my $ungapped = shift;
    my $gapped = shift;
    foreach my $motif (@{$self->{MOTIFS}}){
        my $length = $motif->get_pfm_length();
        my $blockref = $motif->get_blocks();
        $motif->check_blocks($ungapped, $gapped);
        if ($blockref){
            for my $block (0 .. $#$blockref){
                my $block_width = $blockref->[$block]->{END} - $blockref->[$block]->{START} + 1;
                my $array1ref = $motif->get_pfm_fragment($blockref->[$block]->{START}, $blockref->[$block]->{END});
                my $array1revref = get_reverse_motif($array1ref);
                my $array2ref = $motif->get_pfm();
                my $descriptor = offset_correlation($array1ref, $array2ref, $info_cutoff, $correlation_cutoff, $blockref->[$block]->{END});
                if ($descriptor){
                    my %element = (BLOCKSTART => $blockref->[$block]->{START},
                                    BLOCKEND => $blockref->[$block]->{END},
                                    MATCHSTART => $descriptor->{OFFSET},
                                    MATCHEND => ($descriptor->{OFFSET} + $block_width - 1),
                                    CORRELATION => $descriptor->{SCORE}
                                  );
                    $motif->put_descriptor('REPEAT', \%element);
                };
                $descriptor = correlation($array1revref, $array2ref, $info_cutoff, $correlation_cutoff);
                if ($descriptor){
                    my %element = (BLOCKSTART => $blockref->[$block]->{START},
                                    BLOCKEND => $blockref->[$block]->{END},
                                    MATCHSTART => $descriptor->{OFFSET},
                                    MATCHEND => ($descriptor->{OFFSET} + $block_width - 1),
                                    CORRELATION => $descriptor->{SCORE}
                                    );
                    $motif->put_descriptor('PALENDROME', \%element);
                };
            }
        };
    };
};

sub get_reverse_motif {
    my $pfm_ref = shift;
    my @reverse_pfm_ref = ();
    for (my $i = $#$pfm_ref; $i >= 0; $i--){
        my $element = {T => $$pfm_ref[$i]->{A},
                       A => $$pfm_ref[$i]->{T},
                       G => $$pfm_ref[$i]->{C},
                       C => $$pfm_ref[$i]->{G},
                       INFO => $$pfm_ref[$i]->{INFO}
                      };
        push @reverse_pfm_ref, $element 
    };
    return \@reverse_pfm_ref;
};

sub get_palendromes{
    my $self = shift
};

sub correlation{
    my $array1ref = shift; #shorter motif
    my $array2ref = shift; #longer motif
    my $info_cutoff = shift; #the bits of information required to be used in correlation
    my $correlation_cutoff = shift; #report best match over this cutoff
    my $coefficient = -1;
    my $offset = 0;
    for my $i (0 .. ($#{$array2ref} - $#{$array1ref})){
        my ($sumXY, $sumX, $sumY, $sumXsq, $sumYsq, $N) = 0;
        my $corr = undef;
        for my $j (0 .. $#{$array1ref}){
            if (${$array1ref}[$j]->{INFO} > $info_cutoff){
                $N += 4;
                $sumX += ($array1ref->[$j]->{A} + $array1ref->[$j]->{T} + $array1ref->[$j]->{G} + $array1ref->[$j]->{C});
                $sumXsq += ($array1ref->[$j]->{A}**2 + $array1ref->[$j]->{T}**2 + $array1ref->[$j]->{G}**2 + $array1ref->[$j]->{C}**2);
                $sumY += ($array2ref->[$j+$i]->{A} + $array2ref->[$j+$i]->{T} + $array2ref->[$j+$i]->{G} + $array2ref->[$j+$i]->{C});
                $sumYsq += ($array2ref->[$j+$i]->{A}**2 + $array2ref->[$j+$i]->{T}**2 + $array2ref->[$j+$i]->{G}**2 + $array2ref->[$j+$i]->{C}**2);
                $sumXY += ($array1ref->[$j]->{A} * $array2ref->[$j+$i]->{A} +
                           $array1ref->[$j]->{T} * $array2ref->[$j+$i]->{T} +
                           $array1ref->[$j]->{G} * $array2ref->[$j+$i]->{G} +
                           $array1ref->[$j]->{C} * $array2ref->[$j+$i]->{C});
            };
        };
        $corr = (($N * $sumXY) - ($sumX * $sumY))/sqrt((($N * $sumXsq) - $sumX**2)*(($N * $sumYsq) - $sumY**2));
        if ($corr > $coefficient){$coefficient = $corr; $offset = $i};
    };
    if ($coefficient >= $correlation_cutoff){
        my $best_match = {OFFSET => $offset, SCORE =>$coefficient};
        return $best_match;
    }else {return 0}
    
};

sub offset_correlation{
    my $array1ref = shift; #shorter motif
    my $array2ref = shift; #longer motif
    my $info_cutoff = shift; #the bits of information required to be used in correlation
    my $correlation_cutoff = shift; #report best match over this cutoff
    my $offset_start = shift;
    $offset_start++;
    my $coefficient = -1;
    my $offset = 0;
    if ($offset_start + $#{$array1ref} <= $#{$array2ref}){
        for my $i ($offset_start .. ($#{$array2ref} - $#{$array1ref})){
            my ($sumXY, $sumX, $sumY, $sumXsq, $sumYsq, $N) = 0;
            my $corr = undef;
            for my $j (0 .. $#{$array1ref}){
                if (${$array1ref}[$j]->{INFO} > $info_cutoff){
                    $N += 4;
                    $sumX += ($array1ref->[$j]->{A} + $array1ref->[$j]->{T} + $array1ref->[$j]->{G} + $array1ref->[$j]->{C});
                    $sumXsq += ($array1ref->[$j]->{A}**2 + $array1ref->[$j]->{T}**2 + $array1ref->[$j]->{G}**2 + $array1ref->[$j]->{C}**2);
                    $sumY += ($array2ref->[$j+$i]->{A} + $array2ref->[$j+$i]->{T} + $array2ref->[$j+$i]->{G} + $array2ref->[$j+$i]->{C});
                    $sumYsq += ($array2ref->[$j+$i]->{A}**2 + $array2ref->[$j+$i]->{T}**2 + $array2ref->[$j+$i]->{G}**2 + $array2ref->[$j+$i]->{C}**2);
                    $sumXY += ($array1ref->[$j]->{A} * $array2ref->[$j+$i]->{A} +
                               $array1ref->[$j]->{T} * $array2ref->[$j+$i]->{T} +
                               $array1ref->[$j]->{G} * $array2ref->[$j+$i]->{G} +
                               $array1ref->[$j]->{C} * $array2ref->[$j+$i]->{C});
                };
            };
            $corr = (($N * $sumXY) - ($sumX * $sumY))/sqrt((($N * $sumXsq) - $sumX**2)*(($N * $sumYsq) - $sumY**2));
            if ($corr > $coefficient){$coefficient = $corr; $offset = $i};
        };
        if ($coefficient >= $correlation_cutoff){
            my $best_match = {OFFSET => $offset, SCORE =>$coefficient};
            return $best_match;
        }else {return 0}
    };
    return;
};

=head3 list_stats

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Lists the stats that would be listed by MotifStats associated with each of the MotifObjects stored within the current MotifFunctions object.

=back

=cut

sub list_stats{
    my $self = shift;
    my $file = shift;
    my $number = shift;
    print "Listing MotifStats\:\n$file\n";
    $number--;
    if ($number > $#{$self->{MOTIFS}}){$number = $#{$self->{MOTIFS}}};
    open(FILE, "> $file");
    for my $i (0 .. $number){
        my $motifnum = $i + 1;
        print FILE $self->{MOTIFS}[$i]->list_stats($motifnum) . "\n";
    };
    close FILE;
    return;
};

=head3 list_stats_full

=head4 Parameters

=over 4

=item 1
Name of output file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Lists all of the stats associated with each of the MotifObjects stored within the current MotifFunctions object.

=back

=cut

sub list_stats_full{
    my $self = shift;
    my $file = shift;
    print "Listing Stats\:\n$file\n";
    open(FILE, "> $file");
    print FILE "\#\tMotif\tRank\tGroup\tRank\tSite\tRank\tRatio\tRank\tBits\tRank\tTotal\t";
    print FILE "Hits\tAve\tStDev\tHits\tAve\tStDev\tCorr\tId\tFinders\tConsensus\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my @temp = ();
        push @temp, ($i + 1);
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_motifscore());
        push @temp, $self->{MOTIFS}[$i]->get_motifscore_rank();
        
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_group());
        push @temp, $self->{MOTIFS}[$i]->get_group_rank();
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_site());
        push @temp, $self->{MOTIFS}[$i]->get_site_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_ratio());
        push @temp, $self->{MOTIFS}[$i]->get_ratio_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_bits());
        push @temp, $self->{MOTIFS}[$i]->get_bit_rank();
        push @temp, $self->{MOTIFS}[$i]->get_total_rank();
        
        push @temp, $self->{MOTIFS}[$i]->get_testhits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testsd());
        
        push @temp, $self->{MOTIFS}[$i]->get_genomehits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomeave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomesd());
        
        my $coefficient = $self->{MOTIFS}[$i]->get_correlation('0');
        if ($coefficient){push @temp, sprintf("%.2f", $coefficient)}else{push @temp, ''};
        push @temp, sprintf("%.4s", $self->{MOTIFS}[$i]->get_id('0'));
        my $clust = $self->{MOTIFS}[$i]->get_finders();
        my @progs = ();
        if (exists $$clust{AlignACE}){push @progs, 'AA'};
        if (exists $$clust{BioProspector}){push @progs, 'BP'};
        if (exists $$clust{MDscan}){push @progs, 'MD'};
        if (exists $$clust{MEME}){push @progs, 'ME'};
        push @temp, join(', ', @progs);
        push @temp, $self->{MOTIFS}[$i]->list_consensus();
        print FILE join("\t", @temp)."\n";
    };
    close FILE;
    return;
};


sub load_stats_full{
    my $self = shift;
    my $file = shift;
    my $transfac = shift;
    print "Loading MotifStats statistics\:\n$file\n";
    open(FILE, "< $file");
    while (<FILE>){
        chomp;
        my @args = split(/\t/, $_);
        if ($args[0] =~ /\d+/){
            my $motif = $args[0] - 1;
            if (!exists $self->{MOTIFS}[$motif]){next};
            my $scan = new ScanFunctions;
            $self->{MOTIFS}[$motif]->put_scanstats($scan);
            $self->{MOTIFS}[$motif]->set_motifscore($args[1]);
            $self->{MOTIFS}[$motif]->set_motifscore_rank($args[2]);
            $self->{MOTIFS}[$motif]->set_group($args[3]);
            $self->{MOTIFS}[$motif]->set_group_rank($args[4]);
            $self->{MOTIFS}[$motif]->set_site($args[5]);
            $self->{MOTIFS}[$motif]->set_site_rank($args[6]);
            $self->{MOTIFS}[$motif]->set_ratio($args[7]);
            $self->{MOTIFS}[$motif]->set_ratio_rank($args[8]);
            $self->{MOTIFS}[$motif]->set_bits($args[9]);
            $self->{MOTIFS}[$motif]->set_bits_rank($args[10]);
            $self->{MOTIFS}[$motif]->set_total_rank($args[11]);
            $self->{MOTIFS}[$motif]->set_testhits($args[12]);
            $self->{MOTIFS}[$motif]->set_testave($args[13]);
            $self->{MOTIFS}[$motif]->set_testsd($args[14]);
            $self->{MOTIFS}[$motif]->set_genomehits($args[15]);
            $self->{MOTIFS}[$motif]->set_genomeave($args[16]);
            $self->{MOTIFS}[$motif]->set_genomesd($args[17]);
            my @trans = split(/\,/, $args[18]);
            for my $x (0 .. $#trans){
                my @pair = split(/\:/, $trans[$x]);
                $self->{MOTIFS}[$motif]->put_transfac_id($pair[0], $pair[1], $transfac);
            };
            $self->{MOTIFS}[$motif]->put_consensus($args[21]);
            my %finders = ();
            if ($args[19] =~ /AA/){$finders{AlignACE}++};
            if ($args[19] =~ /BP/){$finders{BioProspector}++};
            if ($args[19] =~ /MD/){$finders{MDscan}++};
            if ($args[19] =~ /ME/){$finders{MEME}++};
            $self->{MOTIFS}[$motif]->set_finders(\%finders);
        };
    };
    close FILE;
    return;
};

sub load_dummy_stats{
    my $self = shift;
    for my $motif (0 ..  $#{$self->{MOTIFS}}){
            if (!exists $self->{MOTIFS}[$motif]){next};
            my $scan = new ScanFunctions;
            $self->{MOTIFS}[$motif]->put_scanstats($scan);
            $self->{MOTIFS}[$motif]->set_motifscore('1');
            $self->{MOTIFS}[$motif]->set_motifscore_rank('1');
            $self->{MOTIFS}[$motif]->set_group('1');
            $self->{MOTIFS}[$motif]->set_group_rank('1');
            $self->{MOTIFS}[$motif]->set_site('1');
            $self->{MOTIFS}[$motif]->set_site_rank('1');
            $self->{MOTIFS}[$motif]->set_ratio('1');
            $self->{MOTIFS}[$motif]->set_ratio_rank('1');
            $self->{MOTIFS}[$motif]->set_bits('1');
            $self->{MOTIFS}[$motif]->set_bits_rank('1');
            $self->{MOTIFS}[$motif]->set_total_rank('1');
            $self->{MOTIFS}[$motif]->set_testhits('1');
            $self->{MOTIFS}[$motif]->set_testave('1');
            $self->{MOTIFS}[$motif]->set_testsd('1');
            $self->{MOTIFS}[$motif]->set_genomehits('1');
            $self->{MOTIFS}[$motif]->set_genomeave('1');
            $self->{MOTIFS}[$motif]->set_genomesd('1');
            my %finders = ();
            $finders{AlignACE}++;
            $self->{MOTIFS}[$motif]->set_finders(\%finders);
    };
    return;
}

sub load_stats_full_notrans{
    my $self = shift;
    my $file = shift;
    my $transfac = shift;
    print "Loading MotifStats statistics\:\n$file\n";
    open(FILE, "< $file");
    while (<FILE>){
        chomp;
        my @args = split(/\t/, $_);
        if ($args[0] =~ /\d+/){
            my $motif = $args[0] - 1;
            if (!exists $self->{MOTIFS}[$motif]){next};
            my $scan = new ScanFunctions;
            $self->{MOTIFS}[$motif]->put_scanstats($scan);
            $self->{MOTIFS}[$motif]->set_motifscore($args[1]);
            $self->{MOTIFS}[$motif]->set_motifscore_rank($args[2]);
            $self->{MOTIFS}[$motif]->set_group($args[3]);
            $self->{MOTIFS}[$motif]->set_group_rank($args[4]);
            $self->{MOTIFS}[$motif]->set_site($args[5]);
            $self->{MOTIFS}[$motif]->set_site_rank($args[6]);
            $self->{MOTIFS}[$motif]->set_ratio($args[7]);
            $self->{MOTIFS}[$motif]->set_ratio_rank($args[8]);
            $self->{MOTIFS}[$motif]->set_bits($args[9]);
            $self->{MOTIFS}[$motif]->set_bits_rank($args[10]);
            $self->{MOTIFS}[$motif]->set_total_rank($args[11]);
            $self->{MOTIFS}[$motif]->set_testhits($args[12]);
            $self->{MOTIFS}[$motif]->set_testave($args[13]);
            $self->{MOTIFS}[$motif]->set_testsd($args[14]);
            $self->{MOTIFS}[$motif]->set_genomehits($args[15]);
            $self->{MOTIFS}[$motif]->set_genomeave($args[16]);
            $self->{MOTIFS}[$motif]->set_genomesd($args[17]);
            $self->{MOTIFS}[$motif]->put_consensus($args[21]);
            my %finders = ();
            if ($args[19] =~ /AA/){$finders{AlignACE}++};
            if ($args[19] =~ /BP/){$finders{BioProspector}++};
            if ($args[19] =~ /MD/){$finders{MDscan}++};
            if ($args[19] =~ /ME/){$finders{MEME}++};
            $self->{MOTIFS}[$motif]->set_finders(\%finders);
        };
    };
    close FILE;
    return;
};

sub list_bits{
    my $self = shift;
    my $file = shift;
    print "Listing Stats\:\n$file\n";
    open(FILE, "> $file");
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $bits = $self->{MOTIFS}[$i]->get_bits();
        my $chars = length($self->{MOTIFS}[$i]->get_aster());
        my $bitsper = $bits/$chars;
        print FILE "$bits\t$bitsper\n";
    };
    close FILE;
    return;
};

sub list_stats_full2{
    my $self = shift;
    my $file = shift;
    print "Listing Stats\:\n$file\n";
    open(FILE, "> $file");
    print FILE "\#\tMotif\tRank\tGroup\tRank\tSite\tRank\tRatio\tRank\tBits\tRank\tTotal\t";
    print FILE "Hits\tAve\tStDev\tHits\tAve\tStDev\tCorr\tId\tFinders\tConsensus\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my @temp = ();
        push @temp, ($i + 1);
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_motifscore());
        push @temp, $self->{MOTIFS}[$i]->get_motifscore_rank();
        
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_group());
        push @temp, $self->{MOTIFS}[$i]->get_group_rank();
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_site());
        push @temp, $self->{MOTIFS}[$i]->get_site_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_ratio());
        push @temp, $self->{MOTIFS}[$i]->get_ratio_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_bits());
        push @temp, $self->{MOTIFS}[$i]->get_bit_rank();
        push @temp, $self->{MOTIFS}[$i]->get_total_rank();
        
        push @temp, $self->{MOTIFS}[$i]->get_testhits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testsd());
        
        push @temp, $self->{MOTIFS}[$i]->get_genomehits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomeave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomesd());
        
        my @trans = ();
        if ($self->{MOTIFS}[$i]->check_transfac_hits()){
            my $trans_hits = $self->{MOTIFS}[$i]->check_transfac_hits();
            for my $j (0 .. ($trans_hits - 1)){
                my $coeff = $self->{MOTIFS}[$i]->get_correlation($j);
                if ($coeff =~ /\d+/){$coeff = sprintf("%.2f", $coeff)}
                my $id = $self->{MOTIFS}[$i]->get_id($j);
                if ($id =~ /\S+/ and $coeff =~ /\S+/){
                    push @trans, "$id\:$coeff";
                };
            };
        };
        
        push @temp, join(',', @trans);
        my $clust = $self->{MOTIFS}[$i]->get_finders();
        my @progs = ();
        if (exists $$clust{AlignACE}){push @progs, 'AA'};
        if (exists $$clust{BioProspector}){push @progs, 'BP'};
        if (exists $$clust{MDscan}){push @progs, 'MD'};
        if (exists $$clust{MEME}){push @progs, 'ME'};
        my @des = ();
        my $descriptor = $self->{MOTIFS}[$i]->get_descriptor();
        if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
        if (exists $$descriptor{REPEAT}){push @des, 'TR'};
        if (exists $$descriptor{GAPPED}){push @des, 'GAP'};
        if (exists $$descriptor{UNGAPPED}){push @des, 'UNGAP'};
        if (exists $$descriptor{FAIL}){push @des, 'FAIL'};
        push @temp, join(',', @progs);
        push @temp, join(',', @des);
        push @temp, $self->{MOTIFS}[$i]->list_consensus();
        print FILE join("\t", @temp)."\n";
    };
    close FILE;
    return;
};

sub list_stats_sets_clusters{
    my $self = shift;
    my $file = shift;
    print "Listing Stats\:\n$file\n";
    open(FILE, "> $file");
    print FILE "\#\tMotif\tRank\tGroup\tRank\tSite\tRank\tRatio\tRank\tBits\tRank\tTotal\t";
    print FILE "Hits\tAve\tStDev\tHits\tAve\tStDev\tSet\tCluster\tFactors\tFinders\tDescriptor\tConsensus\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my @temp = ();
        push @temp, ($i + 1);
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_motifscore());
        push @temp, $self->{MOTIFS}[$i]->get_motifscore_rank();
        
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_group());
        push @temp, $self->{MOTIFS}[$i]->get_group_rank();
        push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_site());
        push @temp, $self->{MOTIFS}[$i]->get_site_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_ratio());
        push @temp, $self->{MOTIFS}[$i]->get_ratio_rank();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_bits());
        push @temp, $self->{MOTIFS}[$i]->get_bit_rank();
        push @temp, $self->{MOTIFS}[$i]->get_total_rank();
        
        push @temp, $self->{MOTIFS}[$i]->get_testhits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testsd());
        
        push @temp, $self->{MOTIFS}[$i]->get_genomehits();
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomeave());
        push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomesd());
        
        push @temp, $self->{MOTIFS}[$i]->get_set();
        push @temp, $self->{MOTIFS}[$i]->get_cluster();
        
        my @trans = ();
        if ($self->{MOTIFS}[$i]->check_transfac_hits()){
            my $trans_hits = $self->{MOTIFS}[$i]->check_transfac_hits();
            for my $j (0 .. ($trans_hits - 1)){
                my $coeff = $self->{MOTIFS}[$i]->get_correlation($j);
                if ($coeff =~ /\d+/){$coeff = sprintf("%.2f", $coeff)}
                my $id = $self->{MOTIFS}[$i]->get_id($j);
                if ($id =~ /\S+/ and $coeff =~ /\S+/){
                    push @trans, "$id\:$coeff";
                };
            };
        };
        
        push @temp, join(',', @trans);
        my $clust = $self->{MOTIFS}[$i]->get_finders();
        my @progs = ();
        if (exists $$clust{AlignACE}){push @progs, 'AA'};
        if (exists $$clust{BioProspector}){push @progs, 'BP'};
        if (exists $$clust{MDscan}){push @progs, 'MD'};
        if (exists $$clust{MEME}){push @progs, 'ME'};
        my @des = ();
        my $descriptor = $self->{MOTIFS}[$i]->get_descriptor();
        if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
        if (exists $$descriptor{REPEAT}){push @des, 'TR'};
        if (exists $$descriptor{GAPPED}){push @des, 'GAP'};
        if (exists $$descriptor{UNGAPPED}){push @des, 'UNGAP'};
        if (exists $$descriptor{FAIL}){push @des, 'FAIL'};
        push @temp, join(',', @progs);
        push @temp, join(',', @des);
        push @temp, $self->{MOTIFS}[$i]->list_consensus();
        print FILE join("\t", @temp)."\n";
    };
    close FILE;
    return;
};

sub list_stats_force{
    my $self = shift;
    my $file = shift;
    print "Listing Stats\:\n$file\n";
    open(FILE, "> $file");
    print FILE "\#\tMotif\tRank\tGroup\tRank\tSite\tRank\tRatio\tRank\tBits\tRank\tTotal\t";
    print FILE "Hits\tAve\tStDev\tHits\tAve\tStDev\tCorr\tId\tFinders\tConsensus\n";
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my @temp = ();
        push @temp, ($i + 1);
        if ($self->{MOTIFS}[$i]->get_motifscore()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_motifscore());}else{push @temp, ''};
        if ($self->{MOTIFS}[$i]->get_motifscore_rank()){push @temp, $self->{MOTIFS}[$i]->get_motifscore_rank();}else{push @temp, ''};
        
        if($self->{MOTIFS}[$i]->get_group()){push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_group());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_group_rank()){push @temp, $self->{MOTIFS}[$i]->get_group_rank();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_site()){push @temp, sprintf("%.2g", $self->{MOTIFS}[$i]->get_site());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_site_rank()){push @temp, $self->{MOTIFS}[$i]->get_site_rank();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_ratio()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_ratio());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_ratio_rank()){push @temp, $self->{MOTIFS}[$i]->get_ratio_rank();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_bits()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_bits());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_bit_rank()){push @temp, $self->{MOTIFS}[$i]->get_bit_rank();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_total_rank()){push @temp, $self->{MOTIFS}[$i]->get_total_rank();}else{push @temp, ''};
        
        if($self->{MOTIFS}[$i]->get_testhits()){push @temp, $self->{MOTIFS}[$i]->get_testhits();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_testave()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testave());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_testsd()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_testsd());}else{push @temp, ''};
        
        if($self->{MOTIFS}[$i]->get_genomehits()){push @temp, $self->{MOTIFS}[$i]->get_genomehits();}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_genomeave()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomeave());}else{push @temp, ''};
        if($self->{MOTIFS}[$i]->get_genomesd()){push @temp, sprintf("%.2f", $self->{MOTIFS}[$i]->get_genomesd());}else{push @temp, ''};
        
        my @trans = ();
        if ($self->{MOTIFS}[$i]->check_transfac_hits()){
            my $trans_hits = $self->{MOTIFS}[$i]->check_transfac_hits();
            for my $j (0 .. ($trans_hits - 1)){
                my $coeff = $self->{MOTIFS}[$i]->get_correlation($j);
                if ($coeff =~ /\d+/){$coeff = sprintf("%.2f", $coeff)}
                my $id = $self->{MOTIFS}[$i]->get_id($j);
                push @trans, "$id\:$coeff";
            };
        };
        
        push @temp, join(',', @trans);
        my $clust = $self->{MOTIFS}[$i]->get_finders();
        my @progs = ();
        if (exists $$clust{AlignACE}){push @progs, 'AA'};
        if (exists $$clust{BioProspector}){push @progs, 'BP'};
        if (exists $$clust{MDscan}){push @progs, 'MD'};
        if (exists $$clust{MEME}){push @progs, 'ME'};
        my @des = ();
        my $descriptor = $self->{MOTIFS}[$i]->get_descriptor();
        if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
        if (exists $$descriptor{REPEAT}){push @des, 'TR'};
        if (exists $$descriptor{GAPPED}){push @des, 'GAP'};
        if (exists $$descriptor{UNGAPPED}){push @des, 'UNGAP'};
        if (exists $$descriptor{FAIL}){push @des, 'FAIL'};
        push @temp, join(',', @progs);
        push @temp, join(',', @des);
        push @temp, $self->{MOTIFS}[$i]->list_consensus();
        print FILE join("\t", @temp)."\n";
    };
    close FILE;
    return;
};


=head3 sort_score

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by their individual motif finder score.  Hence, it makes little sense to call this method on a MotifFunctions object containing motifs from multiple finders.

=item 2
While sorting this method also sets the MOTIFRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_motifscore{
    my $self = shift;
    print "Sorting by motif score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_motifscore };
        push @array, $ref;
    };
    my @sorted = sort { $b->{value} <=> $a->{value} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_motifscore

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the motifscore rank for each motif in a MotifFunctions object

=back

=cut

sub rank_motifscore{
    my $self = shift;
    print "Ranking by motif score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_motifscore };
        push @array, $ref;
    };
    my @sorted = sort { $b->{value} <=> $a->{value} } @array;
    my $lastScore = -10;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_motifscore();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_motifscore_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_motifscore_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_motifscore_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

=head3 sort_group

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by group specificity score.

=item 2
While sorting this method also sets the GROUPRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_group{
    my $self = shift;
    print "Sorting by group specificity\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = {motif => $i,
                   groupspec => $self->{MOTIFS}[$i]->get_group };
        push @array, $ref;
    };
    my @sorted = sort {$a->{groupspec} <=> $b->{groupspec} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_group

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the group specificity rank for each motif in a MotifFunctions object

=back

=cut

sub rank_group{
    my $self = shift;
    print "Ranking by group score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_group };
        push @array, $ref;
    };
    my @sorted = sort { $a->{value} <=> $b->{value} } @array;
    my $lastScore = 1000;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_group();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_group_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_group_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_group_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

=head3 sort_motifscore

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by motif score.

=item 2
While sorting this method also sets the GROUPRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_support{
    my $self = shift;
    print "Sorting by support score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = {motif => $i,
                   score => $self->{MOTIFS}[$i]->get_support };
        push @array, $ref;
    };
    my @sorted = sort {$b->{score} <=> $a->{score} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_support

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the support score rank for each motif in a MotifFunctions object

=back

=cut

sub rank_support{
    my $self = shift;
    print "Ranking by group score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_support };
        push @array, $ref;
    };
    my @sorted = sort { $b->{value} <=> $a->{value} } @array;
    my $lastScore = 0;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_support();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_support_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_support_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_support_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

#I have added two lines of code to this method to update the likelihood rank
#of each of the motifobjects stored within the MotifFunctions object
=head3 sort_likelihood

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by their frequency ratio. 

=item 2
While sorting this method also sets the LIKELYHOODRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_ratio{
    my $self = shift;
    print "Sorting by frequency ratio\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = {motif => $i,
                   score => $self->{MOTIFS}[$i]->get_ratio };
        push @array, $ref;
    };
    my @sorted = sort {$b->{score} <=> $a->{score} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_ratio

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the ratio score rank for each motif in a MotifFunctions object

=back

=cut

sub rank_ratio{
    my $self = shift;
    print "Ranking by group score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_ratio };
        push @array, $ref;
    };
    my @sorted = sort { $b->{value} <=> $a->{value} } @array;
    my $lastScore = 0;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_ratio();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_ratio_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_ratio_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_ratio_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

=head3 sort_site

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by their site specificity score. 

=item 2
While sorting this method also sets the LIKELYHOODRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_site{
    my $self = shift;
    print "Sorting by site specificity ratio\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = {motif => $i,
                   score => $self->{MOTIFS}[$i]->get_site };
        push @array, $ref;
    };
    my @sorted = sort {$a->{score} <=> $b->{score} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_site

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the site specificity rank for each motif in a MotifFunctions object

=back

=cut

sub rank_site{
    my $self = shift;
    print "Ranking by group score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_site };
        push @array, $ref;
    };
    my @sorted = sort { $a->{value} <=> $b->{value} } @array;
    my $lastScore = 1000;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_site();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_site_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_site_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_site_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

#Added two lines so that each motif object stored within the MotifFunction also
#stores its bit rank 
=head3 sort_bits

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by their bit score. 

=item 2
While sorting this method also sets the BITRANK attribute of each MotifObject stored within the current MotifFunctions object

=back

=cut

sub sort_bits{
    my $self = shift;
    print "Sorting by likelihood ratio\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = {motif => $i,
                   score => $self->{MOTIFS}[$i]->get_bits() };
        push @array, $ref;
    };
    my @sorted = sort {$b->{score} <=> $a->{score} } @array;
    my @sortedrecords = ();
    for my $z (0 .. $#sorted){
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

=head3 rank_bits

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the bit score rank for each motif in a MotifFunctions object

=back

=cut

sub rank_bits{
    my $self = shift;
    print "Ranking by group score\n";
    my @array = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $ref = { motif => $i,
                   value => $self->{MOTIFS}[$i]->get_bits };
        push @array, $ref;
    };
    my @sorted = sort { $b->{value} <=> $a->{value} } @array;
    my $lastScore = 0;
    for my $z (0 .. $#sorted){
        my $score = $self->{MOTIFS}[$sorted[$z]->{motif}]->get_bits();;
	if ($score == $lastScore) {
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
            my $rank = $lastMotif->get_bit_rank();
            $self->{MOTIFS}[$sorted[$z]->{motif}]->set_bits_rank($rank);
            $lastScore = $score;
        }
        else{
	    my $rank = $z + 1; #again, rank will be relative to one
	    $self->{MOTIFS}[$sorted[$z]->{motif}]->set_bits_rank($rank);
	    $lastScore = $score;
	};
    };
    return;
}

#I have added this new method in order to sort on total rank
#there is one issue that I worry about: That this method will be called before ranks have been set
#I will simultaneously set the total rank of each motif within the MotifFunctions object
#motifObject->set_total_rank will bomb out if at least one individual rank has not been set
#prior to this method call
=head3 sort_totalrank

=head4 Parameters

=over 4

=item 1
None

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Sorts all of the MotifObjects stored within the current MotifFunctions object by their totalrank. 

=item 2
While sorting this method also sets the TOTALRANK attribute of each MotifObject stored within the current MotifFunctions object

=item 3
Total rank will be defined with respect to all of the ranks that have been previously defined by calling sort_ methods
=back

=cut

sub sort_totalrank {
    my $self = shift;
    print "Setting up the Total Rank \n";
    my @totalRanks;
    for my $i (0 .. $#{$self->{MOTIFS}}) {
	my $motif = $self->{MOTIFS}[$i];
	my $rankSum = 0;
	if ($motif->get_motifscore_rank()) {
	    $rankSum += $motif->get_motifscore_rank;
	}
	if ($motif->get_group_rank()) {
	    $rankSum += $motif->get_group_rank;
	}
	if ($motif->get_site_rank()) {
	    $rankSum += $motif->get_site_rank;
	}
	if ($motif->get_ratio_rank()) {
	    $rankSum += $motif->get_ratio_rank;
	}
	if ($motif->get_bit_rank()) {
	    $rankSum += $motif->get_bit_rank;
	}
        if ($motif->get_support_rank()) {
	    $rankSum += $motif->get_support_rank;
	}
	my $holder = {motif => $i,
	    rankSum => $rankSum
	};
	push @totalRanks, $holder;
    }
    print "Sorting by Total Rank \n";
    my @sorted = sort {$a->{rankSum} <=> $b->{rankSum} } @totalRanks;
    my @sortedrecords = ();
    my $lastScore = -1;
    for my $z (0 .. $#sorted){
        my $score = $sorted[$z]->{rankSum};	
        push @sortedrecords, $self->{MOTIFS}[$sorted[$z]->{motif}];
	if ($lastScore == $score) {
	    #print "got in!";
	    my $lastMotif = $self->{MOTIFS}[$sorted[$z - 1]->{motif}];
	    my $rank = $lastMotif->get_total_rank();
	    $sortedrecords[$z]->set_total_rank($rank);
	    $lastScore = $score;
        }
        else {
	    my $rank = $z + 1; #again, rank will be relative to one
	    #print "Setting the ranks to $rank \n";
	    $sortedrecords[$z]->set_total_rank($rank);
	    $lastScore = $score;
	}
    };
    @{$self->{MOTIFS}} = @sortedrecords;
    return;
};

#A method to list the total rank of all of the Motif Objects within a MotifFunction

=head3 list_totalrank

=head4 Parameters

=over 4

=item 1
Name of the file to output to

=item 2
Number of motifs whose total rank will be listed in the output file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Essentially calls the list_total_rank() on each MotifObject stored within the current MotifFunctions object

=item 2
Will list the file source, total rank, motif score, the group specificity score, the positional specificity score, the average position, the frequency ratio, and the bits score

=item 3
It is really important to note that the output is highly dependent upon the MotifObject's method list_total_rank

=item 4
In its current state this method is deprecated. However, it is still completely functional as long as the MotifObject list_total_rank() method is working.

=back

=cut

sub list_totalrank{
	my $self = shift;
	my $file = shift;
    my $number = shift;
    print "Listing MotifStats\:\n$file\n";
    $number--;
    if ($number > $#{$self->{MOTIFS}}){$number = $#{$self->{MOTIFS}}};
    open(FILE, "> $file");
    for my $i (0 .. $number){
        my $motifnum = $i + 1;
        print FILE $self->{MOTIFS}[$i]->list_total_rank() . "\n";
    };
    close FILE;
    return;
};

=head3 list_all_ranks

=head4 Parameters

=over 4

=item 1
Name of the file to output to

=item 2
Number of motifs whose total rank will be listed in the output file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Essentially calls the list_all_ranks() on each MotifObject stored within the current MotifFunctions object

=item 2
In its current state this method will output as follows: File, group specificity rank, motif score rank, bit score rank, site specificity rank, total rank, consensus sequence

=item 3
It is really important to note that the output is highly dependent upon the MotifObject's method list_all_ranks

=item 4
If a particular rank is yet to be defined (by calling sort_), a 0 is listed as a place holder

=back

=cut

sub list_all_ranks {
	my $self = shift;
	my $file = shift;
    my $number = shift;
    print "Listing MotifStats\:\n$file\n";
    $number--;
    if ($number > $#{$self->{MOTIFS}}){$number = $#{$self->{MOTIFS}}};
    open(FILE, "> $file");
    for my $i (0 .. $number){
        my $motifnum = $i + 1;
        print FILE $self->{MOTIFS}[$i]->list_all_ranks() . "\n";
    };
    close FILE;
    return;
}

#a method to list all of the stats and ranks of the best cluster members according to the most recent sorting

=head3 best_clusters_all

=head4 Parameters

=over 4

=item 1
Name of the file to output to

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Essentially calls the list_stats and list_ranks() on each MotifObject stored within the current MotifFunctions object

=item 2
In its current state this method will output as follows: File, group specificity rank, motif score rank, bit score rank, site specificity rank, total rank, consensus sequence, group specificity rank, motif score rank, bit score rank, site specificity rank, total rank, consensus sequence

=item 3
If a particular rank is yet to be defined (by calling sort_), a 0 is listed as a place holder

=back

=cut

sub best_clusters_all {
	my $self = shift;
    my $file = shift;
    my %ref = ();
    my $i = undef;
    for ($i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for ($i = 0; $i <= $#temp; $i++){
        if (defined($ref{$i})){push @list, $ref{$i}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;

    open(OUT, "> $file");
    for my $i (0 .. $#sorted){
        print OUT $self->{MOTIFS}[$sorted[$i]]->list_stats($i)."\t";
        print OUT $self->{MOTIFS}[$sorted[$i]]->list_ranks() . "\n";
    };
    close OUT;
    return;
}

sub eliminate_fragments {
    my $self = shift;
    my $width = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        if ($self->{MOTIFS}[$i]->fragment_check($width)){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs
};

=head3 push_motifs

=head4 Parameters

=over 4

=item 1
Another MotifFunctions object

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Pushes all of the MotifObjects stored within the MotifFunctions objectpassed into the current MotifFunctions object

=item 2
Also pushes all of the genes from the MotifFunctions object passed onto the current MotifFunctions object

=back

=cut

sub push_motifs{
    my $self = shift;
    my $motifrefput = shift;
    for my $z (0 .. $#{$motifrefput->{MOTIFS}}){
        push @{$self->{MOTIFS}}, $motifrefput->{MOTIFS}[$z];
    };
    my @genes = keys %{$motifrefput->{GENES}};
    for my $c (0 .. $#genes){
        $self->{GENES}{$genes[$c]} = { id => '1' }
    };
    return;
};

=head3 push_top_motif

=head4 Parameters

=over 4

=item 1
Another MotifFunctions object

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Pushes the top motif from one MotifFunctions object into a new MotifFunctions object

=item 2
Also pushes all of the genes from the MotifFunctions object passed onto the current MotifFunctions object

=back

=cut

sub push_top_motif{
    my $self = shift;
    my $motifrefput = shift;
    push @{$self->{MOTIFS}}, $motifrefput->{MOTIFS}[0];
    my @genes = keys %{$motifrefput->{GENES}};
    for my $c (0 .. $#genes){
        $self->{GENES}{$genes[$c]} = { id => '1' }
    };
    return;
};

=head3 get_motif_svg

=head4 Parameters

=over 4

item 1
File handle reference, XML writer reference, motif number

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function converts the contents of a MotifObject into svg graphics 

=back

=cut

sub get_motif_svg{
    my ($self, $io, $writer,  $motif) = @_;
    my $motif_length = length($self->{MOTIFS}[$motif]->get_aster());
    my $number = $self->{MOTIFS}[$motif]->get_motif_number();
    my $image_height = 130;
    my $image_width = ($motif_length * 24) + 100;

    

    my $across = 0;
    $writer->startTag('g');
    my @info = $self->{MOTIFS}[$motif]->get_info_array();
    if ($self->{MOTIFS}[$motif]->get_orientation()){
        for my $x (0 .. $#info){    
            my $height = 0;
            for my $w (0 .. 3){
                if ($info[$x][$w]->{info} > 0){
                    $writer->startTag('g',
                        transform => "translate\($across\,$height\)");
                    my $size_char = ($info[$x][$w]->{info} * 2);
                    my $color = undef;
                    if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                    if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                    if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                    if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                    $writer->startTag('text',
                        style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                        transform => "scale\(1\,$size_char\)");
                    $writer->characters("$info[$x][$w]->{base}");
                    $writer->endTag('text');
                    $writer->endTag('g');
                    $height = $height - ($info[$x][$w]->{info} * 50)
                };
            };
            $across = $across + 24;
        };
    }
    else{
        for (my $x = $#info; $x >= 0; $x--){    
            my $height = 0;
            for my $w (0 .. 3){
                if ($info[$x][$w]->{info} > 0){
                    $writer->startTag('g',
                        transform => "translate\($across\,$height\)");
                    my $size_char = ($info[$x][$w]->{info} * 2);
                    my $color = undef;
                    my $base = undef;
                    if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                    if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                    if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                    if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                    $writer->startTag('text',
                        style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                        transform => "scale\(1\,$size_char\)");
                    $writer->characters("$base");
                    $writer->endTag('text');
                    $writer->endTag('g');
                    $height = $height - ($info[$x][$w]->{info} * 50)
                };
            };
            $across = $across + 24;
        };
    };
    $writer->endTag('g');
    return;
};

=head3 logo_writer

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the motifscore rank for each motif in a MotifFunctions object

=back

=cut

sub logo_writer
{
    my $self = shift;
    my $outdir = shift;
    my $root = shift;
    my $trans = shift;
    for my $y (0 .. $#{$self->{MOTIFS}}){
        my $motif_length = length($self->{MOTIFS}[$y]->get_aster());
        my $number = $self->{MOTIFS}[$y]->get_motif_number();
        my $image_height = 130;
        my $image_width = ($motif_length * 24) + 100;
        my $outfile = undef;
        if ($trans){
            my $motif = "$self->{TRANSFAC}{$self->{MOTIFS}[$y]->{MOTIFNUMBER}}->{MOTIF}";
            $outfile = "$outdir\/$motif\_$root"."\_motif"."$number\.svg";
        }
        else{
            $outfile = "$outdir\/$root"."\_motif"."$number\.svg";
        };
        
        my $io = new IO::File;
        $io->open ("> $outfile");
        my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
        
        $writer->xmlDecl('UTF-8');
        $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
            'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

        $writer->startTag(
            'svg',
            transform => "scale\(2\.0\,1\.25\)",
            height => $image_height,
            width  => $image_width
            );

        $writer->emptyTag(
            'rect',
            height => $image_height,
            width  => $image_width,
            fill   => 'white'
            );

        $writer->startTag(
            'g',
            id => 'motif-page',
            transform => 'translate(62,110)'
            );
        
        my $endline = $image_width - 50;
        
        $writer->startTag(
            'polyline',
            'fill'    => 'none',
            'stroke'  => 'black',
            'stroke-width' => '2',
            'points' => "50\,20 50\,110 $endline\, 50",
            );
        $writer->endTag('polyline');

        my $across = 0;
        $writer->startTag('g');
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        $writer->endTag('g');
        $writer->endTag('svg');
        $writer->end();
    };
    return;
};

sub logo_writer2
{
    my $self = shift;
    my $outdir = shift;
    my $root = shift;
    my $trans = shift;
    for my $y (0 .. $#{$self->{MOTIFS}}){
        my $motif_length = length($self->{MOTIFS}[$y]->get_aster());
        my $number = $self->{MOTIFS}[$y]->get_motif_number();
        my $image_height = 130;
        my $image_width = ($motif_length * 24) + 100;
        my $outfile = undef;
        if ($trans){
            my $motif = "$self->{TRANSFAC}{$self->{MOTIFS}[$y]->{MOTIFNUMBER}}->{MOTIF}";
            $outfile = "$outdir\/$motif\_$root"."\_motif"."$number\.svg";
        }
        else{
            $outfile = "$outdir\/$root"."\_motif"."$number\.svg";
        };
        
        my $io = new IO::File;
        $io->open ("> $outfile");
        my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
        
        $writer->xmlDecl('UTF-8');
        $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
            'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

        $writer->startTag(
            'svg',
            transform => "scale\(2\.0\,1\.25\)",
            height => $image_height,
            width  => $image_width
            );

        $writer->emptyTag(
            'rect',
            height => $image_height,
            width  => $image_width,
            fill   => 'white'
            );

        $writer->startTag(
            'g',
            id => 'motif-page',
            transform => 'translate(62,110)'
            );

        $self->get_motif_svg($io, $writer, $y);
        $writer->endTag('g');
        my $endline = $image_width - 50;
        $writer->emptyTag(
            'polyline',
            style => 'fill: none;stroke-width: 2; stroke: black;',
            points => "46 20\, 49 20\, 49 65\, 46 65\, 49 65\, 49 111\, 46 111\, $endline 111",
            );
        
        my $blocks = $self->{MOTIFS}[$y]->get_blocks();
        if ($blocks){
            if ($self->{MOTIFS}[$y]->get_orientation()){
                for my $z (0 .. $#{$blocks}){
                    my $startblock = 52 + ($$blocks[$z]->{START} * 24);
                    my $endblock = 48 + (($$blocks[$z]->{END}+1) * 24);
                    $writer->emptyTag(
                    'polyline',
                    style => 'fill: none;stroke-width: 8; stroke: grey;',
                    points => "$startblock 12\, $endblock 12",
                    );
                };
            }
            else{
                for my $z (0 .. $#{$blocks}){
                    my $startblock = 52 + (($motif_length - $$blocks[$z]->{END} - 1) * 24);
                    my $endblock = 48 + (($motif_length - $$blocks[$z]->{START}) * 24);
                    $writer->emptyTag(
                    'polyline',
                    style => 'fill: none;stroke-width: 8; stroke: grey;',
                    points => "$startblock 12\, $endblock 12",
                    );
                };
            }
        };
        
        $writer->endTag('svg');
        $writer->end();
        };
    return;
};

sub logo_block_writer
{
    my $self = shift;
    my $io = shift;
    my $writer = shift;
    my $nmotifs = shift;
    my $totalmotifs = $self->get_number_motifs();
    if ($totalmotifs < $nmotifs){$nmotifs = $totalmotifs};
    $nmotifs--;
    for my $y (0 .. $nmotifs){
        my ($xcor, $ycor) = ('0', ($y*30));
        $writer->startTag(
            'g',
            id => 'motif-page',
            transform => "translate\($xcor\,$ycor\)"
            );
        $writer->startTag(
            'g',
            transform => "scale\(0\.4\,0\.25\)"
            );
        $self->get_motif_svg($io, $writer, $y);
        $writer->endTag('g');
        $writer->endTag('g');
    };
    return ($nmotifs);
};

=head3 logo_writer_rev

=head4 Parameters

=over 4

item 1
none

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function sets the motifscore rank for each motif in a MotifFunctions object

=back

=cut

sub logo_writer_rev
{
    my $self = shift;
    my $outdir = shift;
    my $root = shift;
    my $trans = shift;
    for my $y (0 .. $#{$self->{MOTIFS}}){
        my $motif_length = length($self->{MOTIFS}[$y]->get_aster());
        my $number = $self->{MOTIFS}[$y]->get_motif_number();
        my $image_height = 130;
        my $image_width = ($motif_length * 24) + 100;
        my $outfile = undef;
        if ($trans){
            my $motif = "$self->{TRANSFAC}{$self->{MOTIFS}[$y]->{MOTIFNUMBER}}->{MOTIF}";
            $outfile = "$outdir\/$motif\_$root"."\_motif"."$number\.svg";
        }
        else{
            $outfile = "$outdir\/$root"."\_motif"."$number\.svg";
        };
        
        my $io = new IO::File;
        $io->open ("> $outfile");
        my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
        
        $writer->xmlDecl('UTF-8');
        $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
            'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

        $writer->startTag(
            'svg',
            transform => "scale\(2\.0\,1\.25\)",
            height => $image_height,
            width  => $image_width
            );

        $writer->emptyTag(
            'rect',
            height => $image_height,
            width  => $image_width,
            fill   => 'white'
            );

        $writer->startTag(
            'g',
            id => 'motif-page',
            transform => 'translate(62,110)'
            );

        my $across = 0;
        $writer->startTag('g');
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        $writer->endTag('g');
        $writer->endTag('svg');
        $writer->end();
    };
    return;
};

=head3 motif_writer_id

=head4 Parameters

=over 4

=item 1
Name of the .svg file to output to

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Needs a description

=back

=cut

sub motif_writer_id
{
    my $self = shift;
    my $outfile = shift;
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    my $motif_length = 10;
    my $image_height = 100 + (30 * ($num_motif+1));
    my $image_width = 1200;

    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,50)'
        );
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    $writer->startTag('text',
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    $writer->startTag('text',
        dx=>"70;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    $writer->startTag('text',
        dx=>"120;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Group Spec");
    $writer->endTag('text');

    $writer->startTag('text',
        dx=>"220;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("ID");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"300;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("LOGO");
    $writer->endTag('text');
    $writer->endTag('g');
    
    my $distance = 30;
    #if ($num_motif > 9) {$num_motif = 9};
    for my $y (0 .. $num_motif)
    {
        my $motif_index = $y + 1;
        
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("Motif $motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"70;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $score = $self->{MOTIFS}[$y]->get_motifscore();
        $writer->characters("$score");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"140;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = $self->{MOTIFS}[$y]->get_group();
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"210;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = $self->{MOTIFS}[$y]->get_id();
        $writer->characters("$id");
        $writer->endTag('text');
        
        my $across = 700;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
};

=head3 motif_writer_full

=head4 Parameters

=over 4

=item 1
Name of the file to output the .svg file to

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Writes a .svg file for the top 10 motifs according to the last sort_ method call

=back

=cut

sub motif_writer_full
{
    my $self = shift;
    my $outfile = shift;
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    my $motif_length = 10;
    my $image_height = 100 + (30 * ($num_motif + 1));
    my $image_width = 1200;

    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,50)'
        );
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('text',
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Number");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Group");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Spec");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Freq");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ratio");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Bit");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Test");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Back");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');

    $writer->startTag('text',
        dx=>"650;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Transfac");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"790;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    
    my $distance = 60;
    if ($num_motif > 9) {$num_motif = 9};
    for my $y (0 .. $num_motif)
    {
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("Motif $motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"70;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $score = $self->{MOTIFS}[$y]->get_motifscore();
        $writer->characters("$score");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"140;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = $self->{MOTIFS}[$y]->get_group();
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"205;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $likelihood = $self->{MOTIFS}[$y]->get_ratio();
        $writer->characters("$likelihood");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"250;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $bits = $self->{MOTIFS}[$y]->get_bits();
        $writer->characters("$bits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"315;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"370;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = $self->{MOTIFS}[$y]->get_testave();
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"420;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = $self->{MOTIFS}[$y]->get_testsd();
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"480;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomehits = $self->{MOTIFS}[$y]->get_genomehits();
        $writer->characters("$genomehits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"540;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomeave = $self->{MOTIFS}[$y]->get_genomeave();
        $writer->characters("$genomeave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"600;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomesd = $self->{MOTIFS}[$y]->get_genomesd();
        $writer->characters("$genomesd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"660;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = $self->{MOTIFS}[$y]->get_id();
        $writer->characters("$id");
        $writer->endTag('text');
        
        my $across = 1900;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

=head2 motif_writer_best_clusters

=head4 Parameters

=over 4

=item 1
Name of the .svg file to output to

=item 2
Number of best cluster members to output to the .svg file

=back

=head4 Returns

=over 4

=item 1 
nothing

=back

=head4 Description

=over 4

=item 1
Writes .svg files for the number of best motifs specified by the user

=back

=cut

sub motif_writer_best_clusters
{
    my $self = shift;
    my $outfile = shift;
    my $numberClusters = shift;
    print "Writing motif graphics\n$outfile\n";
    my $motif_length = 10;
    my $image_width = 1200;
    my %ref;
    for (my $i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for (my $i = 0; $i <= $#temp; $i++){
        if (defined($ref{$i})){push @list, $ref{$i}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;
    if ($numberClusters > $#sorted) {
	$numberClusters = $#sorted;
    }
    my @clusterIds;
    for (my $i = 0;$i < $numberClusters ;$i++) {
	push @clusterIds, $sorted[$i];
    }
    my $image_height = 50 * $numberClusters;
    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,50)'
        );
    $writer->startTag('g',
        id => "header",
        style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('text',
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Number");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Group");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Spec");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Freq");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ratio");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Bit");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Test");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Back");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');

    $writer->startTag('text',
        dx=>"650;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Transfac");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"790;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    
    my $distance = 60;
    foreach my $y (@clusterIds)
    {
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("Motif $motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"70;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $score = $self->{MOTIFS}[$y]->get_motifscore();
        $writer->characters("$score");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"140;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = $self->{MOTIFS}[$y]->get_group();
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"205;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $likelihood = $self->{MOTIFS}[$y]->get_ratio();
        $writer->characters("$likelihood");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"250;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $bits = $self->{MOTIFS}[$y]->get_bits();
        $writer->characters("$bits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"315;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"370;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = $self->{MOTIFS}[$y]->get_testave();
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"420;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = $self->{MOTIFS}[$y]->get_testsd();
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"480;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomehits = $self->{MOTIFS}[$y]->get_genomehits();
        $writer->characters("$genomehits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"540;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomeave = $self->{MOTIFS}[$y]->get_genomeave();
        $writer->characters("$genomeave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"600;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomesd = $self->{MOTIFS}[$y]->get_genomesd();
        $writer->characters("$genomesd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"660;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = $self->{MOTIFS}[$y]->get_id();
        $writer->characters("$id");
        $writer->endTag('text');
        
        my $across = 1900;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        
        $writer->endTag('g');
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

=head3 motif_writer_best_clusters_id

=head4 Parameters

=over 4

item 1
Filename to write, Number of cluster members to write

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function writes out the best member from each cluster.  The best member is determined by sort order of the motifs. 

=back

=cut

sub motif_writer_best_clusters_id
{
    my $self = shift;
    my $outfile = shift;
    my $numberClusters = shift;
    my %ids = %{$_[0]};
    print "Writing motif graphics\n$outfile\n";
    my $motif_length = 10;
    my $image_width = 1200;
	my %ref;
	for (my $i = $#{$self->{MOTIFS}}; $i >= 0; $i--){
        my $cluster = $self->{MOTIFS}[$i]->get_cluster();
        $ref{$cluster} = { id => $i };
    };
    my @temp = keys %ref;
    my @list = ();
    for (my $i = 0; $i <= $#temp; $i++){
        if (defined($ref{$i})){push @list, $ref{$i}->{id}};
    };
    my @sorted = sort {$a <=> $b} @list;
    if ($numberClusters > $#sorted) {
	$numberClusters = $#sorted;
    }
    my @clusterIds;
    for (my $i = 0;$i < $numberClusters ;$i++) {
	push @clusterIds, $sorted[$i];
    }
    my $image_height = 50 * $numberClusters;
    my $io = new IO::File;
    $io->open (">> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,50)'
        );
    
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('text',
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Number");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Motif");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"70;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Group");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"140;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Spec");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Freq");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"200;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ratio");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Bit");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"250;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Score");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Test");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"310;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"370;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"420;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Back");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"480;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Ave");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"540;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Hits");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Std");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"600;",
        dy=>"20;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Dev");
    $writer->endTag('text');

    $writer->startTag('text',
        dx=>"650;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Transfac");
    $writer->endTag('text');
    
    $writer->startTag('text',
        dx=>"790;",
        style => "fill\:black\;text\-anchor\:front\;");
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    
    my $distance = 60;

    foreach my $y (@clusterIds){
	if (!exists($ids{$self->{MOTIFS}[$y]->get_id()})) {next};
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("Motif $motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"70;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $score = $self->{MOTIFS}[$y]->get_motifscore();
        $writer->characters("$score");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"140;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = $self->{MOTIFS}[$y]->get_group();
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"205;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $likelihood = $self->{MOTIFS}[$y]->get_ratio();
        $writer->characters("$likelihood");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"250;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $bits = $self->{MOTIFS}[$y]->get_bits();
        $writer->characters("$bits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"315;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"370;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = $self->{MOTIFS}[$y]->get_testave();
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"420;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = $self->{MOTIFS}[$y]->get_testsd();
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"480;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomehits = $self->{MOTIFS}[$y]->get_genomehits();
        $writer->characters("$genomehits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"540;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomeave = $self->{MOTIFS}[$y]->get_genomeave();
        $writer->characters("$genomeave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"600;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomesd = $self->{MOTIFS}[$y]->get_genomesd();
        $writer->characters("$genomesd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"660;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = $self->{MOTIFS}[$y]->get_id();
        $writer->characters("$id");
        $writer->endTag('text');
        
        my $across = 1900;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

=head3 motif_writer_full2

=head4 Parameters

=over 4

item 1
Output filename

item 2
Correlation cutoff 

=back

=head4
Returns

=over 4

=item 1
Nothing

=back

=head4 Description 

=over 4

=item 1
This function writes out all of the motifs contained in in a MotifFunctions object.

=item 2
Reports all statistical information from ScanFunctions and all rank informtion from MotifObject

=back

=cut

sub motif_writer_full2
{
    my $self = shift;
    my $outfile = shift;
    my $corrcut = shift;
    my %clusters = $self->get_clusters();
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    my $motif_length = 10;
    my $image_height = 300 + (30 * ($num_motif + 1));
    my $image_width = 1500;

    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,200)'
        );
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('g',
        transform => "translate\(10\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(50\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif Score");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(130\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif Score Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(170\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(250\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(290\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(370\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificy Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(410\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Ratio Score");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(490\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Ratio Score Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(530\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Bit Score");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(610\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Bit Score Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(650\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Total Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(690\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(740\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Average Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(790\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("StDev Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(840\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Background Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(890\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Average Background Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(940\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("StDev Background Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');

    $writer->startTag('g',
        transform => "translate\(990\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC Correlation");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(1030\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC ID");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(1100\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif Finders");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(1220\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    $writer->endTag('g');
    
    my $distance = 30;
    for my $y (0 .. $num_motif)
    {
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("$motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"40;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $score = sprintf("%.2e", $self->{MOTIFS}[$y]->get_motifscore());
        $writer->characters("$score");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"120;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $motifrank = $self->{MOTIFS}[$y]->get_motifscore_rank();
        $writer->characters("$motifrank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"160;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = sprintf("%.2e", $self->{MOTIFS}[$y]->get_group());
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"240;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $grouprank = $self->{MOTIFS}[$y]->get_group_rank();
        $writer->characters("$grouprank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"280;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $site = sprintf("%.2e", $self->{MOTIFS}[$y]->get_site());
        $writer->characters("$site");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"360;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $siterank = $self->{MOTIFS}[$y]->get_site_rank();
        $writer->characters("$siterank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"400;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $ratio = sprintf("%.2e", $self->{MOTIFS}[$y]->get_ratio());
        $writer->characters("$ratio");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"480;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $ratiorank = $self->{MOTIFS}[$y]->get_ratio_rank();
        $writer->characters("$ratiorank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"520;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $bits = sprintf("%.2e", $self->{MOTIFS}[$y]->get_bits());
        $writer->characters("$bits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"600;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $bitsrank = $self->{MOTIFS}[$y]->get_bit_rank();
        $writer->characters("$bitsrank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"640;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $totalrank = $self->{MOTIFS}[$y]->get_total_rank();
        $writer->characters("$totalrank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"680;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"730;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testave());
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"780;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testsd());
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"830;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomehits = $self->{MOTIFS}[$y]->get_genomehits();
        $writer->characters("$genomehits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"880;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomeave = sprintf("%.2f", $self->{MOTIFS}[$y]->get_genomeave());
        $writer->characters("$genomeave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"930;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $genomesd = sprintf("%.2f", $self->{MOTIFS}[$y]->get_genomesd());
        $writer->characters("$genomesd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"980;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $corr = '';
        if ($self->{MOTIFS}[$y]->get_correlation(0) =~ /\d+/){
             $corr = sprintf("%.2f", $self->{MOTIFS}[$y]->get_correlation(0));
             if ($corr < $corrcut){$corr = ''};
        };
        $writer->characters("$corr");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"1020;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = sprintf("%.6s", $self->{MOTIFS}[$y]->get_id(0));
        $id =~ tr/_//;
        $writer->characters("$id");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"1090;",
            style => "fill\:black\;text\-anchor\:front\;");
	my %clust = %{$self->{MOTIFS}[$y]->get_finders()};
        my @progs = ();
        if (exists $clust{AlignACE}){push @progs, 'AA'};
        if (exists $clust{BioProspector}){push @progs, 'BP'};
        if (exists $clust{MDscan}){push @progs, 'MD'};
        if (exists $clust{MEME}){push @progs, 'ME'};
        my $finders = join(', ', @progs);

        $writer->characters("$finders");
        $writer->endTag('text');
        
        my $across = 3030;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');

        if ($self->{MOTIFS}[$y]->get_transfac_info_array('0')){
        $across = 3250;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        @info = $self->{MOTIFS}[$y]->get_transfac_info_array('0');
        if ($self->{MOTIFS}[$y]->get_transfac_ori()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        };
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

sub motif_writer_group
{
    my $self = shift;
    my $outfile = shift;
    my $corrcut = shift;
    my %clusters = $self->get_clusters();
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    my $motif_length = 10;
    my $image_height = 300 + (30 * ($num_motif + 1));
    my $image_width = 1500;

    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,200)'
        );
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('g',
        transform => "translate\(10\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(50\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(130\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(160\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(240\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificy Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(280\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(330\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Average Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(380\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("StDev Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(430\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC Correlation");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(470\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC ID");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(540\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif Finders");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(660\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Block Filter");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(690\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Repeats");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(770\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    $writer->endTag('g');
    
    my $distance = 30;
    for my $y (0 .. $num_motif)
    {
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("$motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"40;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = sprintf("%.2e", $self->{MOTIFS}[$y]->get_group());
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"120;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $grouprank = $self->{MOTIFS}[$y]->get_group_rank();
        $writer->characters("$grouprank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"150;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $site = sprintf("%.2e", $self->{MOTIFS}[$y]->get_site());
        $writer->characters("$site");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"230;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $siterank = $self->{MOTIFS}[$y]->get_site_rank();
        $writer->characters("$siterank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"270;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"320;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testave());
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"370;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testsd());
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"420;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $corr = sprintf("%.2f", $self->{MOTIFS}[$y]->get_correlation(0));
        if ($corr < $corrcut){$corr = ''};
        $writer->characters("$corr");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"460;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = sprintf("%.6s", $self->{MOTIFS}[$y]->get_id(0));
        $id =~ tr/_//;
        $writer->characters("$id");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"530;",
            style => "fill\:black\;text\-anchor\:front\;");
	my %clust = %{$self->{MOTIFS}[$y]->get_finders()};
        my @progs = ();
        if (exists $clust{AlignACE}){push @progs, 'AA'};
        if (exists $clust{BioProspector}){push @progs, 'BP'};
        if (exists $clust{MDscan}){push @progs, 'MD'};
        if (exists $clust{MEME}){push @progs, 'ME'};
        my $finders = join(', ', @progs);

        $writer->characters("$finders");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"650;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $filter = '';
        my $descriptor = $self->{MOTIFS}[$y]->get_descriptor();
        if (exists $$descriptor{FAIL}){$filter = 'F'}
        else {$filter = 'P'};
        $writer->characters("$filter");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"680;",
            style => "fill\:black\;text\-anchor\:front\;");
        my @des = ();
        if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
        if (exists $$descriptor{REPEAT}){push @des, 'TR'};
        my $repeat = join(',', @des);
        $writer->characters("$repeat");
        $writer->endTag('text');
        
        my $across = 1920;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');

        if ($self->{MOTIFS}[$y]->get_transfac_info_array('0')){
        $across = 3250;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        @info = $self->{MOTIFS}[$y]->get_transfac_info_array('0');
        if ($self->{MOTIFS}[$y]->get_transfac_ori()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        };
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

sub motif_writer_sets
{
    my $self = shift;
    my $outfile = shift;
    my $corrcut = shift;
    my %clusters = $self->get_clusters();
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    my $motif_length = 10;
    my $image_height = 300 + (30 * ($num_motif + 1));
    my $image_width = 1500;

    my $io = new IO::File;
    $io->open ("> $outfile");
    my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
    $writer->xmlDecl('UTF-8');
    $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
        'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');

    $writer->startTag(
        'svg',
        height => $image_height,
        width  => $image_width
        );

    $writer->emptyTag(
        'rect',
        height => $image_height,
        width  => $image_width,
        fill   => 'white'
        );

    $writer->startTag(
        'g',
        id => 'motif-page',
        transform => 'translate(50,200)'
        );
    $writer->startTag('g',
            id => "header",
            style => 'font-family:Arial-BoldMT;font-size:14;');
    
    $writer->startTag('g',
        transform => "translate\(10\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(50\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(130\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Group Specificity Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(160\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificity");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(240\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Site Specificy Rank");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(280\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(330\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Average Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(380\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("StDev Testset Sites");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(430\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC Correlation");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(470\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("TRANSFAC ID");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(540\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Motif Finders");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(660\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Sets");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(760\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Repeats");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    
    $writer->startTag('g',
        transform => "translate\(840\,0\)");
    $writer->startTag('g',
        transform => "rotate\(-90\)");
    $writer->startTag('text',
        style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
    $writer->characters("Logo");
    $writer->endTag('text');
    $writer->endTag('g');
    $writer->endTag('g');
    $writer->endTag('g');
    
    my $distance = 30;
    for my $y (0 .. $num_motif)
    {
        my $motif_index = $y + 1;
        $writer->startTag('g',
            id => "motif\_$y",
            transform => "translate\(0\,$distance\)",
            style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('text',
            style => "fill\:black\;text\-anchor\:front\;");
        $writer->characters("$motif_index");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"40;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $group = sprintf("%.2e", $self->{MOTIFS}[$y]->get_group());
        $writer->characters("$group");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"120;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $grouprank = $self->{MOTIFS}[$y]->get_group_rank();
        $writer->characters("$grouprank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"150;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $site = sprintf("%.2e", $self->{MOTIFS}[$y]->get_site());
        $writer->characters("$site");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"230;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $siterank = $self->{MOTIFS}[$y]->get_site_rank();
        $writer->characters("$siterank");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"270;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testhits = $self->{MOTIFS}[$y]->get_testhits();
        $writer->characters("$testhits");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"320;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testave = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testave());
        $writer->characters("$testave");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"370;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $testsd = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testsd());
        $writer->characters("$testsd");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"420;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $corr = sprintf("%.2f", $self->{MOTIFS}[$y]->get_correlation(0));
        if ($corr < $corrcut){$corr = ''};
        $writer->characters("$corr");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"460;",
            style => "fill\:black\;text\-anchor\:front\;");
        my $id = sprintf("%.6s", $self->{MOTIFS}[$y]->get_id(0));
        $id =~ tr/_//;
        $writer->characters("$id");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"530;",
            style => "fill\:black\;text\-anchor\:front\;");
	my %clust = %{$self->{MOTIFS}[$y]->get_finders()};
        my @progs = ();
        if (exists $clust{AlignACE}){push @progs, 'AA'};
        if (exists $clust{BioProspector}){push @progs, 'BP'};
        if (exists $clust{MDscan}){push @progs, 'MD'};
        if (exists $clust{MEME}){push @progs, 'ME'};
        my $finders = join(', ', @progs);

        $writer->characters("$finders");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"650;",
            style => "fill\:black\;text\-anchor\:front\;");
        my %ref = %{$self->{MOTIFS}[$y]->get_sets()};
	my @sets =  keys %ref;
        @sets = sort @sets;
        my $holder = join(', ', @sets);
        $writer->characters("$holder");
        $writer->endTag('text');
        
        $writer->startTag('text',
            dx=>"750;",
            style => "fill\:black\;text\-anchor\:front\;");
        my @des = ();
        my $descriptor = $self->{MOTIFS}[$y]->get_descriptor();
        if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
        if (exists $$descriptor{REPEAT}){push @des, 'TR'};
        my $repeat = join(',', @des);
        $writer->characters("$repeat");
        $writer->endTag('text');
        
        my $across = 2080;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        my @info = $self->{MOTIFS}[$y]->get_info_array();
        if ($self->{MOTIFS}[$y]->get_orientation()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');

        if ($self->{MOTIFS}[$y]->get_transfac_info_array('0')){
        $across = 3250;
        $writer->startTag('g',
            transform => "scale\(0\.4\,0\.25\)");
        @info = $self->{MOTIFS}[$y]->get_transfac_info_array('0');
        if ($self->{MOTIFS}[$y]->get_transfac_ori()){
            for my $x (0 .. $#info){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$info[$x][$w]->{base}");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        }
        else{
            for (my $x = $#info; $x >= 0; $x--){    
                my $height = 0;
                for my $w (0 .. 3){
                    if ($info[$x][$w]->{info} > 0){
                        $writer->startTag('g',
                            transform => "translate\($across\,$height\)");
                        my $size_char = ($info[$x][$w]->{info} * 2);
                        my $color = undef;
                        my $base = undef;
                        if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                        if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                        if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                        if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                        $writer->startTag('text',
                            style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                            transform => "scale\(1\,$size_char\)");
                        $writer->characters("$base");
                        $writer->endTag('text');
                        $writer->endTag('g');
                        $height = $height - ($info[$x][$w]->{info} * 50)
                    };
                };
                $across = $across + 24;
            };
        };
        $writer->endTag('g');
        };
        $writer->endTag('g');
        $distance = $distance + 30;   
    };
    $writer->endTag('g');
    $writer->endTag('svg');
    $writer->end();
    return;
};

sub motif_writer_sets_pages
{
    my $self = shift;
    my $outfile = shift;
    my $corrcut = shift;
    my $perpage = shift;
    my %clusters = $self->get_clusters();
    print "Writing motif graphics\n$outfile\n";
    my $num_motif = $#{$self->{MOTIFS}};
    
    my $loops = int($num_motif/$perpage);
    for my $loop (0 .. $loops){
        my @nameparts = split(/\./, $outfile);
        my $pagenumber = $loop + 1;
        $nameparts[$#nameparts-1] = $nameparts[$#nameparts-1].'_page'.$pagenumber;
        my $outfile2 = join '.', @nameparts;
        my $motif_length = 10;
        my $image_height = 300 + (30 * ($perpage + 1));
        my $image_width = 1500;
    
        my $io = new IO::File;
        $io->open ("> $outfile2");
        my $writer = new XML::Writer(OUTPUT => $io, DATA_MODE => 1, DATA_INDENT => 1);
        $writer->xmlDecl('UTF-8');
        $writer->doctype('svg', '-//W3C//DTD SVG 1.1 Basic//EN',
            'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd');
    
        $writer->startTag(
            'svg',
            height => $image_height,
            width  => $image_width
            );
    
        $writer->emptyTag(
            'rect',
            height => $image_height,
            width  => $image_width,
            fill   => 'white'
            );
    
        $writer->startTag(
            'g',
            id => 'motif-page',
            transform => 'translate(50,200)'
            );
        $writer->startTag('g',
                id => "header",
                style => 'font-family:Arial-BoldMT;font-size:14;');
        
        $writer->startTag('g',
            transform => "translate\(10\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Motif");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(50\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Group Specificity");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(130\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Group Specificity Rank");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(160\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Site Specificity");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(240\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Site Specificy Rank");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(280\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Testset Sites");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(330\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Average Testset Sites");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(380\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("StDev Testset Sites");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(430\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("TRANSFAC Correlation");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(470\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("TRANSFAC ID");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(540\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Motif Finders");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(660\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Sets");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(760\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Repeats");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        
        $writer->startTag('g',
            transform => "translate\(840\,0\)");
        $writer->startTag('g',
            transform => "rotate\(-90\)");
        $writer->startTag('text',
            style => 'fill:black;text-anchor:front;font-family:Arial-BoldMT;font-size:14;');
        $writer->characters("Logo");
        $writer->endTag('text');
        $writer->endTag('g');
        $writer->endTag('g');
        $writer->endTag('g');
        
        my $distance = 30;
        my $starty = $perpage * $loop;
        my $endy = ($perpage * ($loop+1))-1;
        if ($endy >= $num_motif){$endy = $num_motif};
        for my $y ($starty .. $endy)
        {
            my $motif_index = $y + 1;
            $writer->startTag('g',
                id => "motif\_$y",
                transform => "translate\(0\,$distance\)",
                style => 'font-family:Arial-BoldMT;font-size:14;');
            
            $writer->startTag('text',
                style => "fill\:black\;text\-anchor\:front\;");
            $writer->characters("$motif_index");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"40;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $group = sprintf("%.2e", $self->{MOTIFS}[$y]->get_group());
            $writer->characters("$group");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"120;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $grouprank = $self->{MOTIFS}[$y]->get_group_rank();
            $writer->characters("$grouprank");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"150;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $site = sprintf("%.2e", $self->{MOTIFS}[$y]->get_site());
            $writer->characters("$site");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"230;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $siterank = $self->{MOTIFS}[$y]->get_site_rank();
            $writer->characters("$siterank");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"270;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $testhits = $self->{MOTIFS}[$y]->get_testhits();
            $writer->characters("$testhits");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"320;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $testave = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testave());
            $writer->characters("$testave");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"370;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $testsd = sprintf("%.2f", $self->{MOTIFS}[$y]->get_testsd());
            $writer->characters("$testsd");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"420;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $corr = sprintf("%.2f", $self->{MOTIFS}[$y]->get_correlation(0));
            if ($corr < $corrcut){$corr = ''};
            $writer->characters("$corr");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"460;",
                style => "fill\:black\;text\-anchor\:front\;");
            my $id = sprintf("%.6s", $self->{MOTIFS}[$y]->get_id(0));
            $id =~ tr/_//;
            $writer->characters("$id");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"530;",
                style => "fill\:black\;text\-anchor\:front\;");
            my %clust = %{$self->{MOTIFS}[$y]->get_finders()};
            my @progs = ();
            if (exists $clust{AlignACE}){push @progs, 'AA'};
            if (exists $clust{BioProspector}){push @progs, 'BP'};
            if (exists $clust{MDscan}){push @progs, 'MD'};
            if (exists $clust{MEME}){push @progs, 'ME'};
            my $finders = join(', ', @progs);
    
            $writer->characters("$finders");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"650;",
                style => "fill\:black\;text\-anchor\:front\;");
            my %ref = %{$self->{MOTIFS}[$y]->get_sets()};
            my @sets =  keys %ref;
            @sets = sort @sets;
            my $holder = join(', ', @sets);
            $writer->characters("$holder");
            $writer->endTag('text');
            
            $writer->startTag('text',
                dx=>"750;",
                style => "fill\:black\;text\-anchor\:front\;");
            my @des = ();
            my $descriptor = $self->{MOTIFS}[$y]->get_descriptor();
            if (exists $$descriptor{PALENDROME}){push @des, 'PAL'};
            if (exists $$descriptor{REPEAT}){push @des, 'TR'};
            my $repeat = join(',', @des);
            $writer->characters("$repeat");
            $writer->endTag('text');
            
            my $across = 2080;
            $writer->startTag('g',
                transform => "scale\(0\.4\,0\.25\)");
            my @info = $self->{MOTIFS}[$y]->get_info_array();
            if ($self->{MOTIFS}[$y]->get_orientation()){
                for my $x (0 .. $#info){    
                    my $height = 0;
                    for my $w (0 .. 3){
                        if ($info[$x][$w]->{info} > 0){
                            $writer->startTag('g',
                                transform => "translate\($across\,$height\)");
                            my $size_char = ($info[$x][$w]->{info} * 2);
                            my $color = undef;
                            if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                            if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                            if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                            if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                            $writer->startTag('text',
                                style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                                transform => "scale\(1\,$size_char\)");
                            $writer->characters("$info[$x][$w]->{base}");
                            $writer->endTag('text');
                            $writer->endTag('g');
                            $height = $height - ($info[$x][$w]->{info} * 50)
                        };
                    };
                    $across = $across + 24;
                };
            }
            else{
                for (my $x = $#info; $x >= 0; $x--){    
                    my $height = 0;
                    for my $w (0 .. 3){
                        if ($info[$x][$w]->{info} > 0){
                            $writer->startTag('g',
                                transform => "translate\($across\,$height\)");
                            my $size_char = ($info[$x][$w]->{info} * 2);
                            my $color = undef;
                            my $base = undef;
                            if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                            if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                            if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                            if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                            $writer->startTag('text',
                                style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                                transform => "scale\(1\,$size_char\)");
                            $writer->characters("$base");
                            $writer->endTag('text');
                            $writer->endTag('g');
                            $height = $height - ($info[$x][$w]->{info} * 50)
                        };
                    };
                    $across = $across + 24;
                };
            };
            $writer->endTag('g');
    
            if ($self->{MOTIFS}[$y]->get_transfac_info_array('0')){
            $across = 3250;
            $writer->startTag('g',
                transform => "scale\(0\.4\,0\.25\)");
            @info = $self->{MOTIFS}[$y]->get_transfac_info_array('0');
            if ($self->{MOTIFS}[$y]->get_transfac_ori()){
                for my $x (0 .. $#info){    
                    my $height = 0;
                    for my $w (0 .. 3){
                        if ($info[$x][$w]->{info} > 0){
                            $writer->startTag('g',
                                transform => "translate\($across\,$height\)");
                            my $size_char = ($info[$x][$w]->{info} * 2);
                            my $color = undef;
                            if ($info[$x][$w]->{base} =~ /G/) {$color = 'orange'};
                            if ($info[$x][$w]->{base} =~ /C/) {$color = 'blue'};
                            if ($info[$x][$w]->{base} =~ /T/) {$color = 'red'};
                            if ($info[$x][$w]->{base} =~ /A/) {$color = 'green'};
                            $writer->startTag('text',
                                style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                                transform => "scale\(1\,$size_char\)");
                            $writer->characters("$info[$x][$w]->{base}");
                            $writer->endTag('text');
                            $writer->endTag('g');
                            $height = $height - ($info[$x][$w]->{info} * 50)
                        };
                    };
                    $across = $across + 24;
                };
            }
            else{
                for (my $x = $#info; $x >= 0; $x--){    
                    my $height = 0;
                    for my $w (0 .. 3){
                        if ($info[$x][$w]->{info} > 0){
                            $writer->startTag('g',
                                transform => "translate\($across\,$height\)");
                            my $size_char = ($info[$x][$w]->{info} * 2);
                            my $color = undef;
                            my $base = undef;
                            if ($info[$x][$w]->{base} =~ /G/) {$color = 'blue'; $base = 'C'};
                            if ($info[$x][$w]->{base} =~ /C/) {$color = 'orange'; $base = 'G'};
                            if ($info[$x][$w]->{base} =~ /T/) {$color = 'green'; $base = 'A'};
                            if ($info[$x][$w]->{base} =~ /A/) {$color = 'red'; $base = 'T'};
                            $writer->startTag('text',
                                style => "font\-family\:Arial\-BoldMT\;font\-size\:33\;fill\:$color\;text\-anchor\:middle\;",
                                transform => "scale\(1\,$size_char\)");
                            $writer->characters("$base");
                            $writer->endTag('text');
                            $writer->endTag('g');
                            $height = $height - ($info[$x][$w]->{info} * 50)
                        };
                    };
                    $across = $across + 24;
                };
            };
            $writer->endTag('g');
            };
            $writer->endTag('g');
            $distance = $distance + 30;   
        };
        $writer->endTag('g');
        $writer->endTag('svg');
        $writer->end();
    };
    return;
};


sub screen_number_sets {
    my $self = shift;
    my $min = shift;
    my $max = shift;
    my $motifs = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my %list = %{$self->{MOTIFS}[$i]->get_sets()};
        my @array = keys %list;
        if ($#array >= $min -1 and $#array <= $max - 1){
            push @{$motifs}, $self->{MOTIFS}[$i];
        };
    };
    $self->{MOTIFS} = $motifs;
    return;
};

sub load_sets {
    my $self = shift;
    my %clusters = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $clust = $self->{MOTIFS}[$i]->get_cluster();
        my $set = $self->{MOTIFS}[$i]->get_set();
        $clusters{$clust}{$set} = 1;
    };
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $clust = $self->{MOTIFS}[$i]->get_cluster();
        my %finders = %{$clusters{$clust}};
        $self->{MOTIFS}[$i]->set_sets(\%finders);
    };
    return;
};

sub put_sets{
    my $self = shift;
    my $set = shift;
    my %holder = ();
    for my $i (0 .. $#{$self->{MOTIFS}}){
        $self->{MOTIFS}[$i]->put_set($set);
    }
};

sub geometric_mean{
    my $self = shift;
    my $motifcount = $self->get_number_motifs();
    if ($motifcount <= 0){return 0};
    my $logsum = 0;
    for my $i (0 .. $#{$self->{MOTIFS}}){
        my $group = $self->{MOTIFS}[$i]->get_group();
        my $log = log($group)/log(10);
        $logsum += $log;
    }
    my $logmean = $logsum/$motifcount;
    return 10**$logmean;
};

1
