=head1 NAME

iPE::Levels - A class to keep track of the gc levels of a sequence.

=head1 DESCRIPTION

This object will take in a DNA sequence and based on the window size will create non-overlapping windows of the G+C% contained in each window.  The owning window of any base can be accessed from that base.

=head1 FUNCTIONS

=over 8

=cut

package iPE::Levels;
use iPE;
use iPE::Globals;
use iPE::Util::DNATools;
use strict;

=item new (members)

new creates a new Levels object.  The following are needed in the members hash reference:

=over 8

=item seqRef 

The DNA sequence as a string reference.

=item windowSize

The size of the nonoverlapping windows to detect gc content with.

=cut
sub new {
    my ($class, $m) = @_;
    my $this = bless {}, $class;

    die "Incomplete instantiation of $class.  Required keys are: ".
        "windowSize\n" #seqRef and 
        if(!defined($m->{windowSize})); #!defined($m->{seqRef}) || 

    $this->{$_."_"} = $m->{$_} for(keys (%$m));

    $this->{normalized_} = 0;
    $this->{totals_} = {};
    $this->{totals_}->{$_} = 0 for ("A", "C", "G", "T");

    return $this;
}

sub seqRef      { shift->{seqRef_}      }
sub windowSize  { shift->{windowSize_}  }
sub content     { shift->{content_}     }
sub normalized  { shift->{normalized_}  }

=item setLevels (sequence)

Sets the levels for the current sequence.  Adds to the cumulative total the levels thus far.

=cut
sub setLevels {
    my ($this, $seq) = @_;

    $this->{content_} = [];
    for(my $i = 0; $i < $seq->length; $i += $this->{windowSize_}) {
        my $win;
        if($seq->loaded) {
            $win = substr(${$seq->seqRef}, $i, $this->{windowSize_});
        }
        else {
            $win = $seq->seqReader->getSeq( $i, $this->{windowSize_});
        }
        my $level = levels($win);
        push @{$this->{content_}}, $level;
        msg(($i+1)." ".($i+$this->{windowSize_})." ".
            (100*($level->{C}+$level->{G}))."\n");

        $this->{totals_}->{$_} += $level->{$_} for (keys %{$this->{totals_}});
    }

}

=item normalizeTotals

Normalizes the total levels for use of the cumulative totals.

=cut
sub normalizeTotals {
    my ($this) = @_;

    die __PACKAGE__.": Attempt to re-normalize totals.\n" if($this->normalized);

    my $norm = 0;
    $norm += $this->{totals_}->{$_} for (keys %{$this->{totals_}});
    $this->{totals_}->{$_} /= $norm for (keys %{$this->{totals_}});

    $this->{normalized_} = 1;
}

=item cumulative

Gets the cumulative distribution of DNA characters for all sequences seen.

=cut
sub cumulative { 
    my($this) = @_;
    die __PACKAGE__.": attempt to get unnormalized cumulative levels.\n"
        if(!$this->normalized);
    $this->{totals_} 
}

=item gc (pos)

Return the isochore GC content at the position given on the forward strand.  The method for determining this is through a window size.  The position is fitted to the nearest window as defined by the global isochoreWindow option in iPE.

=cut
sub gc  { 
    my ($this, $pos) = @_;
    my $win = int $pos/$this->windowSize;
    return ($this->{content_}->[$win]->{G}+$this->{content_}->[$win]->{C})*100;
}

=item levels_at (pos)

Return a hash reference to the content at the given position on the forward strand.  Each key in the hash reference is one of the letters (A,C,G,T) and represents the levels of that letter.

=cut
sub levels_at { 
    my ($this, $pos) = @_;
    my $win = int $pos/$this->windowSize;
    return ($this->{content_}->[$win]);
}

=back

=head1 SEE ALSO

L<iPE>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu)

=cut

1;
