package Bio::EnsEMBL::GlyphSet::codons;
use strict;
use base qw(Bio::EnsEMBL::GlyphSet);
sub _init {
my ($self) = @_;
my $container = $self->{'container'};
my $height = 3; # Pixels in height for glyphset
my $padding = 1; # Padding
my $max_length = $self->my_config('threshold') || 50; # In Kbases...
my $stop_col = $self->my_colour( 'stop' ) || 'red';
my $start_col = $self->my_colour( 'start' ) || 'green';
# This is the threshold calculation to display the start/stop codon track warning
# if the track length is too long.
return $self->errorTrack("Start/Stop codons only displayed for less than $max_length Kb.")
unless $container->length < $max_length*1001;
my ($data,$offset,$strand,$base);
if($self->cache('__codon__cache__')) {
# Reverse strand (2nd to display) so we retrieve information from the codon cache
$offset = 3; # For drawing loop look at elements 3,4, 7,8, 11,12
$strand = -1; # Reverse strand
$base = 6 * $height + 3 * $padding; # Start at the bottom
$data = $self->cache('__codon__cache__'); # retrieve data from cache
} else {
$offset = 1; # For drawing loop look at elements 1,2, 5,6, 9,10
$strand = 1; # Forward strand
$base = 0; # Start at the top
# As this is the first time around we will have to create the cache in the @data array
my $seq = $container->seq(); # Get the sequence
# 13 blank arrays so the display loop doesn't error {under -w}
$data = [ undef,[],[],[],[],[],[],[],[],[],[],[],[] ];
# Start/stop codons on the forward strand have value 1/2
# Start/stop codons on the reverse strand have value 3/4
my %h = qw( ATG 1 TAA 2 TAG 2 TGA 2 CAT 3 TTA 4 CTA 4 TCA 4 );
# The value is used as the index in the array to store the information.
# [ For each "phase" this is incremented by 4 ]
foreach my $phase(0..2) {
pos($seq) = $phase;
# Perl regexp from hell! Well not really but it's a fun line anyway....
# step through the string three characters at a time
# if the three characters are in the h (codon hash) then
# we push the co-ordinate element on to the $v'th array in the $data
# array. Also update the current offset by 3...
while( $seq =~ /(...)/g ) {
push @{$data->[$h{$1}]},pos($seq)-3 if $h{$1};
}
# At the end of the phase loop lets move the storage indexes forward by 4
$h{$_} += 4 foreach keys %h;
}
# Store the information in the codon cache for the reverse strand
$self->cache('__codon__cache__',$data);
}
# The twelve elements in the @data array,
# @{$config->{'__codon__cache__'}}
# are:
# 1 => coordinates of phase 0 start codons on forward-> strand
# 2 => coordinates of phase 0 stop codons on forward-> strand
# 3 => coordinates of phase 0 start codons on <-reverse strand
# 4 => coordinates of phase 0 stop codons on <-reverse strand
#
# 5 => coordinates of phase 2 start codons on forward-> strand
# 6 => coordinates of phase 2 stop codons on forward-> strand
# 7 => coordinates of phase 2 start codons on <-reverse strand
# 8 => coordinates of phase 2 stop codons on <-reverse strand
#
# 9 => coordinates of phase 3 start codons on forward-> strand
# 10 => coordinates of phase 3 stop codons on forward-> strand
# 11 => coordinates of phase 3 start codons on <-reverse strand
# 12 => coordinates of phase 3 stop codons on <-reverse strand
my $fullheight = $height * 2 + $padding;
foreach my $phase (0..2){
# Glyphs are 3 basepairs wide
foreach(@{$data->[ $offset + $phase * 4 ]}) { # start codon info
my $glyph = $self->Rect({
'x' => $_,
'y' => $base + (2-$phase) * $fullheight * $strand,
'width' => 3,
'height' => $height-1,
'colour' => $start_col,
'absolutey' => 1,
});
$self->push($glyph);
}
foreach(@{$data->[ $offset + $phase * 4 + 1]}) {
my $glyph = $self->Rect({
'x' => $_,
'y' => $base + ((2-$phase) * $fullheight + $height) * $strand,
'width' => 3,
'height' => $height-1,
'colour' => $stop_col,
'absolutey' => 1,
});
$self->push($glyph);
}
}
}
1;