=head1 NAME

iPE::Annotation::Feature - A feature component of a transcript

=head1 DESCRIPTION

A feature is defined as a state in a specified region of an annotation.  For the transcript that owns it, it is the only state the gHMM is in for those positions of the annotation.

A feature includes an iPE::State object as well as a start and end point of the region.

=head1 FUNCTIONS

=over 8

=cut

package iPE::Annotation::Feature;
use iPE::Util::DNATools;
use strict;


=item new (memberHash)

This creates a new Feature.  All information about the feature is given on instantiation.  The the passed hash reference is expected to have the following keys:

=over 8

=item state

The state of this feature.  Should be an iPE::State object.

=item start

The begin coordinate of the feature, in a 0-based index

=item end

The end coordinate of the feature, in a 0-based index

=item startFrame, endFrame

The start and end frame of the feature.  The start frame is the number of bases overhanging the lowest coordinate of the feature, and the end frame is the number of bases overhanging the highest coordinate of the feature.

=item transcript

The iPE::Transcript that contains this feature; required.

=item id

An optional field specifying the transcript id associated with this feature.

=back

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

    die "Incomplete instantiation of $class.  Required fields are \n".
        "state, start, end, startFrame, and endFrame.\n"
        if(!defined $m->{state} || !defined $m->{start} || !defined $m->{end} ||
           !defined $m->{startFrame} || !defined $m->{endFrame} ||
           !defined $m->{transcript});

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

    $this->{id_} = "" if(!defined($this->{id_}));

    $this->{nullRegions_} = [];

    return $this;
}

=item clone

Create a copy of an object instance.

=cut
sub clone {
    my ($this) = @_;
    bless {%$this}, ref($this);
}

=item state ()

Returns the state of the feature.

=cut
sub state { 
    my ($this, $state) = @_;
    $this->{state_} = $state if(defined($state));
    return $this->{state_};   
}

=item start ()

Returns the start coordinate of the feature.

=cut
sub start { 
    my ($this, $start) = @_;
    $this->{start_} = $start if(defined($start));
    return $this->{start_}   
}

=item end ()

Returns the end coordinate of the feature.

=cut
sub end   { 
    my ($this, $end) = @_;
    $this->{end_} = $end if(defined($end));
    return $this->{end_}     
}

=item transcript ()

Returns the transcript containing the feature object.

=cut
sub transcript {
    my ($this, $transcript) = @_;
    $this->{transcript_} = $transcript if(defined($transcript));
    return $this->{transcript_};
}


=item length ()

Returns the length of the feature.

=cut
sub length { return ($_[0]->{end_}-$_[0]->{start_}+1) }

=item strand ()

Returns the strand of the feature.

=cut
sub strand { shift->state->strand }

=item startFrame (), endFrame ()

Returns the starting and ending frame of the feature.

=cut
sub startFrame {
    my ($this, $startFrame) = @_;
    $this->{startFrame_} = $startFrame if(defined($startFrame));
    return $this->{startFrame_}   
}
sub endFrame {
    my ($this, $endFrame) = @_;
    $this->{endFrame_} = $endFrame if(defined($endFrame));
    return $this->{endFrame_}
}

=item nullRegions ()

Returns a reference to the (possibly empty) array of nullRegions for this feature.

=cut
sub nullRegions { shift->{nullRegions_} }

=item gcLevel ()

Returns the GC content of the DNA sequence at this feature, if it exists.  If no GC content was passed in, this will return undef.

=cut
sub gcLevel { $_[0]->{gcLevel_} }

=item id ()

Returns the transcript ID associated with the feature.  If none is specified, the empty string is returned.

=cut
sub id { shift->{id_} }

=item addNullRegion (nullRegion)

Add a null region (defined by an iPE::Annotation::NullRegion object) to this feature.  This blindly adds it to the feature, no bounds are checked.  The iPE::Annotation::NullDefinition object checks this.

=cut
sub addNullRegion {
    my ($this, $nullRegion) = @_;

    push @{$this->{nullRegions_}}, $nullRegion;
}

=item clearNullRegions ()

Clear the null regions from the transcript.  This would be useful if the feature is modified, and may no longer have any null regions.  (For example, changing a state to an altsplice state after annotation.)

=cut
sub clearNullRegions { shift->{nullRegions_} = []; }


=item setID (id)

Set the transcript id associated with this feature.

=cut
sub setID { $_[0]->{id_} = $_[1] }

=item setLevel (levels)

Set the level of the feature according to the iPE::GCContent object passed in.

=cut
sub setLevel {
    my ($this, $levels) = @_;

    my $center = ($this->start + $this->end)/2;
    my $levhash = $levels->levels_at($center);

    $this->{gcLevel_} = ($levhash->{G}+$levhash->{C})*100;
    $this->{levels_} = $levhash;
}

=back

=head1 SEE ALSO

L<iPE::Annotation::Transcript>, L<iPE::SegmentedAnnotation>, L<iPE::Annotation>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu).

=cut

1;
