package Bio::EnsEMBL::GlyphSet_wiggle_and_block;
use strict;
use base qw(Bio::EnsEMBL::GlyphSet);
sub draw_error {
my($self, $string ) = @_;
}
sub render_compact { return $_[0]->_render(); }
sub render_signal_map { return $_[0]->_render('wiggle'); }
sub render_signal_feature { return $_[0]->_render('both'); }
sub render_text {
my ($self, $wiggle) = @_;
my $container = $self->{'container'};
my $feature_type = $self->my_config('caption');
my $method = $self->can('export_feature') ? 'export_feature' : '_render_text';
my $export;
if ($wiggle ne 'wiggle') {
my $element_features = $self->can('element_features') ? $self->element_features : [];
my $strand = $self->strand;
my $strand_flag = $self->my_config('strand');
my $length = $container->length;
my @features = sort { $a->[1] <=> $b->[1] } map { ($strand_flag ne 'b' || $strand == $_->{'strand'}) && $_->{'start'} <= $length && $_->{'end'} >= 1 ? [ $_, $_->{'start'} ] : () } @$element_features;
foreach (@features) {
my $f = $_->[0];
$export .= $self->$method($f, $feature_type, undef, {
'seqname' => $f->{'hseqname'},
'start' => $f->{'start'} + ($f->{'hstrand'} > 0 ? $f->{'hstart'} : $f->{'hend'}),
'end' => $f->{'end'} + ($f->{'hstrand'} > 0 ? $f->{'hstart'} : $f->{'hend'}),
'strand' => '.',
'frame' => '.'
});
}
}
if ($wiggle) {
my $score_features = $self->can('score_features') ? $self->score_features : [];
my $name = $container->seq_region_name;
foreach my $f (@$score_features) {
my $pos = $f->seq_region_pos;
$export .= $self->$method($f, $feature_type, undef, { 'seqname' => $name, 'start' => $pos, 'end' => $pos });
}
}
return $export;
}
sub _render { ## Show both map and features
my $self = shift;
return $self->render_text(@_) if $self->{'text_export'};
## Check to see if we draw anything because of size!
my $max_length = $self->my_config( 'threshold' ) || 10000;
my $slice_length = $self->{'container'}->length;
my $wiggle_name = $self->my_config('wiggle_name') || $self->my_config('label') ;
if($slice_length > $max_length*1010) {
my $height = $self->errorTrack("$wiggle_name only displayed for less than $max_length Kb");
$self->_offset($height+4);
return 1;
}
## Now we try and draw the features
my $error = $self->draw_features( @_ );
return unless $error && $self->{'config'}->get_parameter('opt_empty_tracks')==1;
my $height = $self->errorTrack( "No $error in this region", 0, $self->_offset );
$self->_offset($height + 4);
return 1;
}
sub draw_block_features {
### Predicted features
### Draws the predicted features track
### Arg1: arrayref of Feature objects
### Arg2: colour of the track
### Returns 1
my ( $self, $features, $colour, $score ) = @_;
my $length = $self->{'container'}->length;
my $h = 10;
foreach my $f (@$features ) {
my $start = $f->start;
my $end = $f->end;
$start = 1 if $start < 1;
$end = $length if $end > $length;
$self->push($self->Rect({
'y' => $self->_offset,
'height' => $h,
'x' => $start -1,
'width' => $end - $start,
'absolutey' => 1, # in pix rather than bp
'colour' => $colour,
'zmenu' => $self->block_features_zmenu($f, $score),
}));
}
$self->_offset( $h+3 );
return 1;
}
sub draw_wiggle_plot {
### Wiggle plot
### Args: array_ref of features in score order, colour, min score for features, max_score for features, display label
### Description: draws wiggle plot using the score of the features
### Returns 1
my( $self, $features, $parameters ) = @_;
my $METHOD_ID = $self->my_config( 'method_link_species_set_id' );
my $zmenu = {
'type' => 'Location',
'action' => 'Align',
'align' => $METHOD_ID,
};
my $slice = $self->{'container'};
my $row_height = $self->my_config('height') || 60;
my $offset = $self->_offset();
my $P_MAX = $parameters->{'max_score'} > 0 ? $parameters->{'max_score'} : 0;
my $N_MIN = $parameters->{'min_score'} < 0 ? $parameters->{'min_score'} : 0;
my $pix_per_score = ($P_MAX-$N_MIN) ? $row_height / ( $P_MAX-$N_MIN ) : 0;
my $red_line_offset = $P_MAX * $pix_per_score;
my $colour = $self->my_colour('score')|| 'blue';
my $axis_colour = $self->my_colour('axis') || 'red';
my $label = $self->my_colour('score','text');
my $name = $self->my_config('short_name') || $self->my_config('name');
$label =~ s/\[\[name\]\]/$name/;
# Draw the axis ------------------------------------------------
$self->push( $self->Line({ # horzi line
'x' => 0,
'y' => $offset + $red_line_offset,
'width' => $slice->length,
'height' => 0,
'absolutey' => 1,
'colour' => $axis_colour,
'dotted' => 1,
}),$self->Line({ # vertical line
'x' => 0,
'y' => $offset,
'width' => 0,
'height' => $row_height,
'absolutey' => 1,
'absolutex' => 1,
'colour' => $axis_colour,
'dotted' => 1,
}));
# Draw max and min score ---------------------------------------------
my $display_max_score = sprintf("%.2f", $P_MAX);
my( $fontname_i, $fontsize_i ) = $self->get_font_details( 'innertext' );
my @res_i = $self->get_text_width(
0, $display_max_score, '', 'font'=>$fontname_i, 'ptsize' => $fontsize_i );
my $textheight_i = $res_i[3];
my $pix_per_bp = $self->scalex;
my $axis_label_flag = $parameters->{'axis_label'} ? "off": "on";
if ($axis_label_flag eq 'on'){
$self->push( $self->Text({
'text' => $display_max_score,
'width' => $res_i[2],
'textwidth' => $res_i[2],
'font' => $fontname_i,
'ptsize' => $fontsize_i,
'halign' => 'right',
'valign' => 'top',
'colour' => $axis_colour,
'height' => $textheight_i,
'y' => $offset,
'x' => -4 - $res_i[2],
'absolutey' => 1,
'absolutex' => 1,
'absolutewidth' => 1,
}));
if ($parameters->{'min_score'} < 0) {
my $display_min_score = sprintf("%.2f", $N_MIN);
my @res_min = $self->get_text_width(
0, $display_min_score, '', 'font'=>$fontname_i, 'ptsize' => $fontsize_i );
$self->push($self->Text({
'text' => $display_min_score,
'height' => $textheight_i,
'width' => $res_min[2],
'textwidth' => $res_min[2],
'font' => $fontname_i,
'ptsize' => $fontsize_i,
'halign' => 'right',
'valign' => 'bottom',
'colour' => $axis_colour,
'y' => $offset + $row_height - $textheight_i,
'x' => -4 - $res_min[2],
'absolutey' => 1,
'absolutex' => 1,
'absolutewidth' => 1,
}));
}
}
# Draw wiggly plot -------------------------------------------------
foreach my $f (@$features) {
my $START = $f->start < 1 ? 1 : $f->start;
my $END = $f->end > $slice->length ? $slice->length : $f->end;
my ($score, $min_score);
if ($f->isa("Bio::EnsEMBL::Variation::ReadCoverageCollection")){
$score = $f->read_coverage_max;
$min_score = $f->read_coverage_min;
} else {
$score = $f->score || 0;
}
# warn(join('*', $f, $START, $END, $score));
my $y = $score < 0 ? 0 : -$score * $pix_per_score;
$self->push($self->Rect({
'y' => $offset + $red_line_offset + $y,
'height' => abs( $score * $pix_per_score ),
'x' => $START-1,
'width' => $END - $START+1,
'absolutey' => 1,
'title' => sprintf("%.2f", $score),
'colour' => $colour,
}));
if ($min_score){
my $y = $score < 0 ? 0 : -$min_score * $pix_per_score;
$self->push($self->Rect({
'y' => $offset + $red_line_offset + $y,
'height' => abs( $min_score * $pix_per_score ),
'x' => $START-1,
'width' => $END - $START+1,
'absolutey' => 1,
'title' => sprintf("%.2f", $score),
'colour' => 'steelblue',
}));
}
}
$offset = $self->_offset($row_height);
# Add line of text -------------------------------------------
my @res_analysis = $self->get_text_width( 0, $label, '', 'font'=>$fontname_i, 'ptsize' => $fontsize_i );
$self->push( $self->Text({
'text' => $label,
'width' => $res_analysis[2],
'font' => $fontname_i,
'ptsize' => $fontsize_i,
'halign' => 'left',
'valign' => 'bottom',
'colour' => $colour,
'y' => $offset,
'height' => $textheight_i,
'x' => 1,
'absolutey' => 1,
'absolutex' => 1,
}) );
$self->_offset($textheight_i); #update offset
return 1;
}
sub draw_track_name {
### Predicted features
### Draws the name of the predicted features track
### Arg1: arrayref of Feature objects
### Arg2: colour of the track
### Returns 1
my ( $self, $name, $colour ) = @_;
my( $fontname_i, $fontsize_i ) = $self->get_font_details( 'innertext' );
my @res_analysis = $self->get_text_width(
0, $name, '', 'font'=>$fontname_i, 'ptsize' => $fontsize_i );
$self->push( $self->Text({
'text' => $name,
'height' => $res_analysis[3],
'width' => $res_analysis[2],
'font' => $fontname_i,
'ptsize' => $fontsize_i,
'halign' => 'left',
'valign' => 'bottom',
'colour' => $colour,
'y' => $self->_offset,
'x' => 1,
'absolutey' => 1,
'absolutex' => 1,
}));
$self->_offset($res_analysis[3]);
return 1;
}
sub draw_space_glyph {
### Draws a an empty glyph as a spacer
### Arg1 : (optional) integer for space height,
### Returns 1
my ($self, $space) = @_;
$space ||= 9;
$self->push( $self->Space({
'height' => $space,
'width' => 1,
'y' => $self->_offset,
'x' => 0,
'absolutey' => 1, # puts in pix rather than bp
'absolutex' => 1,
}));
$self->_offset($space);
return 1;
}
sub _offset {
### Arg1 : (optional) number to add to offset
### Description: Getter/setter for offset
### Returns : integer
my ($self, $offset) = @_;
$self->{'offset'} += $offset if $offset;
return $self->{'offset'} || 0;
}
1;
### Contact: Fiona Cunningham fc1@sanger.ac.uk