package Bio::EnsEMBL::GlyphSet_transcript;
use strict;
use base qw(Bio::EnsEMBL::GlyphSet);
no warnings "uninitialized";
use Sanger::Graphics::Bump;
use Bio::EnsEMBL::Utils::Eprof qw(eprof_start eprof_end);
use Time::HiRes;
sub text_label { return undef; }
sub gene_text_label { return undef; }
sub features { return []; }
sub href { return undef; }
sub gene_href { return undef; }
## Let us define all the renderers here...
## ... these are just all wrappers - the parameter is 1 to draw labels
## ... 0 otherwise...
sub render_gene_label { my $self = shift; $self->render_genes( 1 ); }
sub render_gene_nolabel { my $self = shift; $self->render_genes( 0 ); }
sub render_collapsed_label { my $self = shift; $self->render_collapsed( 1 ); }
sub render_collapsed_nolabel { my $self = shift; $self->render_collapsed( 0 ); }
sub render_transcript_label { my $self = shift; $self->render_transcripts( 1 ); }
sub render_transcript { my $self = shift; $self->render_transcripts( 1 ); }
sub render_normal { my $self = shift; $self->render_transcripts( 1 ); }
sub render_transcript_nolabel { my $self = shift; $self->render_transcripts( 0 ); }
sub render_collapsed {
my ($self,$labels) = @_;
return $self->render_text('transcript', 'collapsed') if $self->{'text_export'};
my $Config = $self->{'config'};
my $strand_flag = $self->my_config('strand');
my $db = $self->my_config('db');
my $selected_db = $self->core('db');
my $selected_gene = $self->core('g');
my $container = exists $self->{'container'}{'ref'} ? $self->{'container'}{'ref'} : $self->{'container'};
my $y = 0;
my $h = 8;
my %highlights;
@highlights{$self->highlights} = (); # build hashkeys of highlight list
my %used_colours = ();
my( $fontname, $fontsize ) = $self->get_font_details( 'outertext' );
my $pix_per_bp = $self->scalex;
my $strand = $self->strand();
my $length = $container->length;
my $transcript_drawn = 0;
$self->_init_bump;
my $compara = $Config->{'compara'};
my $link = $compara ? $Config->get_parameter( 'opt_join_transcript') : 0;
my $join_col1 = 'blue';
my $join_col2 = 'chocolate1';
my $join_z = -10;
foreach my $gene ( @{$self->features()} ) { # For alternate splicing diagram only draw transcripts in gene
my $gene_strand = $gene->strand;
next if $gene_strand != $strand && $strand_flag eq 'b';
## Get all the exons which overlap the region for this gene....
my @exons = map { $_->start > $length || $_->end < 1 ? () : $_ } map { @{$_->get_all_Exons()} } @{$gene->get_all_Transcripts()};
next unless @exons;
$transcript_drawn = 1;
my $gene_stable_id = $gene->stable_id;
my $gene_key = $self->gene_key( $gene );
my $Composite = $self->Composite({'y'=>$y,'height'=>$h, 'title' => $self->gene_title( $gene ) });
$Composite->{'href'} = $self->gene_href( $gene, %highlights );
my $colour = $self->my_colour( $gene_key );
my $label = $self->my_colour( $gene_key , 'text' );
my $hilight = ( $selected_db eq $db && $selected_gene eq $gene_stable_id && $gene_stable_id ) ? 'highlight1' : undef;
$used_colours{ $label } = $colour;
my $Composite2 = $self->Composite({'y'=>$y,'height'=>$h});
foreach my $exon (@exons) {
my $s = $exon->start;
my $e = $exon->end;
$s = 1 if $s < 0;
$e = $length if $e>$length;
$Composite2->push($self->Rect({
'x' => $s-1, 'y' => $y, 'width' => $e-$s+1,
'height' => $h, 'colour'=>$colour, 'absolutey' => 1
}));
}
my $start = $gene->start < 1 ? 1 : $gene->start;;
my $end = $gene->end > $length ? $length : $gene->end;
$Composite2->push($self->Rect({
'x' => $start, 'width' => $end-$start+1,
'height' => 0, 'y' => int($y+$h/2), 'colour' => $colour, 'absolutey' =>1,
}));
# Calculate and draw the coding region of the exon
# only draw the coding region if there is such a region
if($self->can('join')) {
my @tags;
@tags = $self->join( $gene->stable_id ) if $gene && $gene->can( 'stable_id' );
foreach (@tags) {
$self->join_tag( $Composite2, $_, 0, $self->strand==-1 ? 0 : 1, 'grey60' );
$self->join_tag( $Composite2, $_, 1, $self->strand==-1 ? 0 : 1, 'grey60' );
}
}
my $tsid;
my @GENE_TAGS;
if( $link && ( $compara eq 'primary' || $compara eq 'secondary' )) {
if( $gene_stable_id ) {
my $alt_alleles = $gene->get_all_alt_alleles();
if( $Config->{'previous_species'} ) {
foreach my $msid ( $self->get_homologous_gene_ids( $gene_stable_id, $Config->{'previous_species'} ) ) {
$self->join_tag( $Composite2, $Config->{'slice_id'}."#$gene_stable_id#$msid", 0.5, 0.5 , $join_col1, 'line', $join_z );
}
push @GENE_TAGS, map { $Config->{'slice_id'}. "=@{[$_->stable_id]}=$gene_stable_id" } @{$alt_alleles};
}
if( $Config->{'next_species'} ) {
foreach my $msid ( $self->get_homologous_gene_ids( $gene_stable_id, $Config->{'next_species'} ) ) {
$self->join_tag( $Composite2, ($Config->{'slice_id'}+1)."#$msid#$gene_stable_id", 0.5, 0.5 , $join_col1, 'line', $join_z );
}
push @GENE_TAGS, map { ($Config->{'slice_id'}+1). "=$gene_stable_id=@{[$_->stable_id]}" } @{$alt_alleles};
}
}
}
#join alt_alleles
foreach( @GENE_TAGS ) {
$self->join_tag( $Composite2, $_, 0.5, 0.5 , $join_col2, 'line', $join_z ) ;
}
$Composite->push($Composite2);
my $bump_height = $h + 2;
if( $self->my_config('show_labels') ne 'off' && $labels ) {
if(my $text_label = $self->gene_text_label($gene) ) {
my @lines = split "\n", $text_label;
$lines[0] = "< $lines[0]" if $strand < 1;
$lines[0] = $lines[0].' >' if $strand >= 1;
for( my $i=0; $i<@lines; $i++ ){
my $line = $lines[$i].' ';
my( $txt, $bit, $w,$th ) = $self->get_text_width( 0, $line, '', 'ptsize' => $fontsize, 'font' => $fontname );
$Composite->push( $self->Text({
'x' => $Composite->x(),
'y' => $y + $h + $i*($th+1),
'height' => $th,
'width' => $w / $pix_per_bp,
'font' => $fontname,
'ptsize' => $fontsize,
'halign' => 'left',
'colour' => $colour,
'text' => $line,
'absolutey' => 1,
}));
$bump_height += $th+1;
}
}
}
########## bump it baby, yeah! bump-nology!
my $bump_start = int($Composite->x * $pix_per_bp);
my $bump_end = $bump_start + int($Composite->width * $pix_per_bp)+1;
my $row = $self->bump_row( $bump_start, $bump_end );
########## shift the composite container by however much we're bumped
$Composite->y($Composite->y() - $strand * $bump_height * $row);
$Composite->colour($hilight) if defined $hilight;
$self->push($Composite);
}
if($transcript_drawn) {
my $type = $self->my_config('name');
my %legend_old = @{$Config->{'legend_features'}{$type}{'legend'}||[]};
foreach(keys %legend_old) {
$used_colours{$_} = $legend_old{$_};
}
my @legend = %used_colours;
$Config->{'legend_features'}{$type} = {
'priority' => $self->_pos,
'legend' => \@legend
};
## my ($key, $priority, $legend) = $self->legend( $colours );
# define which legend_features should be displayed
# this is being used by GlyphSet::gene_legend
## $Config->{'legend_features'}->{$key} = {
## 'priority' => $priority,
## 'legend' => $legend
## } if defined($key);
} elsif( $Config->get_parameter( 'opt_empty_tracks')!=0) {
$self->errorTrack( "No ".$self->error_track_name()." in this region" );
}
}
sub render_transcripts {
my ($self,$labels) = @_;
return $self->render_text('transcript') if $self->{'text_export'};
my $Config = $self->{'config'};
my( $fontname, $fontsize ) = $self->get_font_details( 'outertext' );
my $strand_flag = $self->my_config('strand');
my $container = exists $self->{'container'}{'ref'} ? $self->{'container'}{'ref'} : $self->{'container'};
my $target = $self->get_parameter('single_Transcript');
my $target_gene = $self->get_parameter('single_Gene' );
my $db = $self->my_config('db');
my $selected_db = $self->core('db');
my $selected_gene = $self->core('g');
my $selected_trans= $self->core('t');
my $y = 0;
my $h = $self->my_config('height') || ( $target ? 30 : 8 );
#Single transcript mode - set height to 30 - width to 8!
my $non_coding_height = ($self->my_config('non_coding_scale')||0.75) * $h;
my $non_coding_start = ($h-$non_coding_height)/2;
my %highlights;
@highlights{$self->highlights} = (); # build hashkeys of highlight list
my %used_colours = ();
my $pix_per_bp = $self->scalex;
$self->_init_bump;
my $strand = $self->strand();
my $length = $container->length;
my $transcript_drawn = 0;
my $compara = $Config->{'compara'};
my $link = $compara ? $Config->get_parameter( 'opt_join_transcript') : 0;
foreach my $gene ( @{$self->features()} ) { # For alternate splicing diagram only draw transcripts in gene
my $gene_strand = $gene->strand;
my $gene_stable_id = $gene->can('stable_id') ? $gene->stable_id() : undef;
next if $gene_strand != $strand && $strand_flag eq 'b'; # skip features on wrong strand....
next if $target_gene && $gene_stable_id ne $target_gene;
my %TAGS = (); my @GENE_TAGS;
my $tsid;
if( $link && ( $compara eq 'primary' || $compara eq 'secondary' ) && $link ) {
if( $gene_stable_id ) {
my $alt_alleles = $gene->get_all_alt_alleles();
#vega stuff to link alt-alleles on longest transcript
my $alltrans = $gene->get_all_Transcripts;
my @s_alltrans = sort {$a->length <=> $b->length} @{$alltrans};
my $long_trans = pop @s_alltrans;
$tsid = $long_trans->stable_id;
my @long_trans;
foreach my $gene (@{$alt_alleles}) {
my $vtranscripts = $gene->get_all_Transcripts;
my @sorted_trans = sort {$a->length <=> $b->length} @{$vtranscripts};
push @long_trans,(pop @sorted_trans);
}
if( $Config->{'previous_species'} ) {
my( $psid, $pid, $href ) = $self->get_homologous_peptide_ids_from_gene( $gene_stable_id, $Config->{'previous_species'} );
push @{$TAGS{$psid}}, map { $Config->{'slice_id'}. "#$_#$pid" } @{$href};
push @GENE_TAGS, map { $Config->{'slice_id'}. "=@{[$_->stable_id]}=$tsid" } @long_trans;
}
if( $Config->{'next_species'} ) {
my( $psid, $pid, $href ) = $self->get_homologous_peptide_ids_from_gene( $gene_stable_id, $Config->{'next_species'} );
push @{$TAGS{$psid}}, map { ($Config->{'slice_id'}+1). "#$pid#$_" } @{$href};
push @GENE_TAGS, map { ($Config->{'slice_id'}+1). "=$tsid=@{[$_->stable_id]}" } @long_trans;
}
}
}
my $join_col1 = 'blue';
my $join_col2 = 'chocolate1';
my $join_z = -10;
foreach my $transcript (@{$gene->get_all_Transcripts()}) {
my $transcript_stable_id = $transcript->stable_id;
next if $transcript->start > $length || $transcript->end < 1;
my @exons = sort {$a->start <=> $b->start} grep { $_ } @{$transcript->get_all_Exons()};#sort exons on their start coordinate
#$self->datadump( $gene_stable_id, \%TAGS );
# Skip if no exons for this transcript
next if (@exons == 0);
# If stranded diagram skip if on wrong strand
next if (@exons[0]->strand() != $gene_strand && $self->{'do_not_strand'}!=1 );
# For exon_structure diagram only given transcript
next if $target && ($transcript->stable_id() ne $target);
$transcript_drawn=1;
my $Composite = $self->Composite({'y'=>$y,'height'=>$h,'title'=>$self->title($transcript,$gene) });
$Composite->{'href'} = $self->href( $gene, $transcript, %highlights );
my $colour_key = $self->transcript_key($transcript,$gene);
my $colour = $self->my_colour( $colour_key );
my $label = $self->my_colour( $colour_key , 'text' );
my $hilight = $selected_db eq $db && $transcript_stable_id ? ( $selected_trans eq $transcript_stable_id ? 'highlight2'
: $selected_gene eq $gene_stable_id ? 'highlight1'
: undef
)
: undef
;
($colour,$label) = ('orange','Other') unless $colour;
$used_colours{ $label } = $colour;
my $coding_start = defined ( $transcript->coding_region_start() ) ? $transcript->coding_region_start : -1e6;
my $coding_end = defined ( $transcript->coding_region_end() ) ? $transcript->coding_region_end : -1e6;
my $Composite2 = $self->Composite({'y'=>$y,'height'=>$h});
if( $transcript->translation ) {
foreach( @{$TAGS{$transcript->translation->stable_id}||[]} ) {
$self->join_tag( $Composite2, $_, 0.5, 0.5 , $join_col1, 'line', $join_z ) ;
}
}
foreach( @GENE_TAGS) {
if ($transcript->stable_id eq $tsid) {
$self->join_tag( $Composite2, $_, 0.5, 0.5 , $join_col2, 'line', $join_z ) ;
}
}
for(my $i = 0; $i < @exons; $i++) {
my $exon = @exons[$i];
next unless defined $exon; #Skip this exon if it is not defined (can happen w/ genscans)
my $next_exon = ($i < $#exons) ? @exons[$i+1] : undef; #First draw the exon
# We are finished if this exon starts outside the slice
last if $exon->start() > $length;
my($box_start, $box_end);
# only draw this exon if is inside the slice
if($exon->end() > 0 ) { #calculate exon region within boundaries of slice
$box_start = $exon->start();
$box_start = 1 if $box_start < 1 ;
$box_end = $exon->end();
$box_end = $length if$box_end > $length;
if($box_start < $coding_start || $box_end > $coding_end ) {
# The start of the transcript is before the start of the coding
# region OR the end of the transcript is after the end of the
# coding regions. Non coding portions of exons, are drawn as
# non-filled rectangles
#Draw a non-filled rectangle around the entire exon
$Composite2->push($self->Rect({
'x' => $box_start -1 ,
'y' => $y+$non_coding_start,
'width' => $box_end-$box_start +1,
'height' => $non_coding_height,
'bordercolour' => $colour,
'absolutey' => 1,
}));
}
# Calculate and draw the coding region of the exon
my $filled_start = $box_start < $coding_start ? $coding_start : $box_start;
my $filled_end = $box_end > $coding_end ? $coding_end : $box_end;
# only draw the coding region if there is such a region
if( $filled_start <= $filled_end ) {
#Draw a filled rectangle in the coding region of the exon
$Composite2->push( $self->Rect({
'x' => $filled_start -1,
'y' => $y,
'width' => $filled_end - $filled_start + 1,
'height' => $h,
'colour' => $colour,
'absolutey' => 1
}));
}
} #we are finished if there is no other exon defined
last unless defined $next_exon;
my $intron_start = $exon->end() + 1; #calculate the start and end of this intron
my $intron_end = $next_exon->start()-1;
next if($intron_end < 0); #grab the next exon if this intron is before the slice
last if($intron_start > $length); #we are done if this intron is after the slice
#calculate intron region within slice boundaries
$box_start = $intron_start < 1 ? 1 : $intron_start;
$box_end = $intron_end > $length ? $length : $intron_end;
my $intron;
if( $box_start == $intron_start && $box_end == $intron_end ) {
# draw an wholly in slice intron
$Composite2->push($self->Intron({
'x' => $box_start -1,
'y' => $y,
'width' => $box_end-$box_start + 1,
'height' => $h,
'colour' => $colour,
'absolutey' => 1,
'strand' => $gene->strand,
}));
} else {
# else draw a "not in slice" intron
$Composite2->push($self->Line({
'x' => $box_start -1 ,
'y' => $y+int($h/2),
'width' => $box_end-$box_start + 1,
'height' => 0,
'absolutey' => 1,
'colour' => $colour,
'dotted' => 1,
}));
} # enf of intron-drawing IF
}
if($self->can('join')) {
my @tags;
@tags = $self->join( $gene->stable_id ) if $gene && $gene->can('stable_id');
foreach (@tags) {
$self->join_tag( $Composite2, $_, 0, $self->strand==-1 ? 0 : 1, 'grey60' );
$self->join_tag( $Composite2, $_, 1, $self->strand==-1 ? 0 : 1, 'grey60' );
}
}
$Composite->push($Composite2);
my $bump_height = 1.5 * $h;
if( $self->my_config('show_labels') ne 'off' && $labels ) {
if(my $text_label = $self->text_label($gene, $transcript) ) {
my @lines = split "\n", $text_label;
$lines[0] = "< $lines[0]" if $strand < 1;
$lines[0] = $lines[0].' >' if $strand >= 1;
for( my $i=0; $i<@lines; $i++ ){
my $line = $lines[$i].' ';
my( $txt, $bit, $w,$th ) = $self->get_text_width( 0, $line, '', 'ptsize' => $fontsize, 'font' => $fontname );
$Composite->push( $self->Text({
'x' => $Composite->x(),
'y' => $y + $h + $i*($th+1),
'height' => $th,
'width' => $w / $pix_per_bp,
'font' => $fontname,
'ptsize' => $fontsize,
'halign' => 'left',
'colour' => $colour,
'text' => $line,
'absolutey' => 1,
}));
$bump_height += $th+1;
}
}
}
########## bump it baby, yeah! bump-nology!
my $bump_start = int($Composite->x * $pix_per_bp);
my $bump_end = $bump_start + int($Composite->width * $pix_per_bp)+1;
my $row = $self->bump_row( $bump_start, $bump_end );
########## shift the composite container by however much we're bumped
$Composite->y($Composite->y() - $strand * $bump_height * $row);
$Composite->colour($hilight) if(defined $hilight && !defined $target);
$self->push($Composite);
if(0 && $target) {
# check the strand of one of the transcript's exons
my ($trans_exon) = @{$transcript->get_all_Exons};
if($trans_exon->strand() == 1) {
$self->push($self->Line({
'x' => 0,
'y' => -4,
'width' => $length,
'height' => 0,
'absolutey' => 1,
'colour' => $colour
}));
$self->push( $self->Poly({
'points' => [
$length - 4/$pix_per_bp,-2,
$length ,-4,
$length - 4/$pix_per_bp,-6],
'colour' => $colour,
'absolutey' => 1,
}));
} else {
$self->push($self->Line({
'x' => 0,
'y' => $h+4,
'width' => $length,
'height' => 0,
'absolutey' => 1,
'colour' => $colour
}));
$self->push($self->Poly({
'points' => [ 4/$pix_per_bp,$h+6,
0, $h+4,
4/$pix_per_bp,$h+2],
'colour' => $colour,
'absolutey' => 1,
}));
}
}
}
}
if($transcript_drawn) {
my $type = $self->_type;
my %legend_old = @{$Config->{'legend_features'}{$type}{'legend'}||[]};
foreach(keys %legend_old) { $used_colours{$_} = $legend_old{$_}; }
my @legend = %used_colours;
$Config->{'legend_features'}->{$type} = {
'priority' => $self->_pos,
'legend' => \@legend
};
## my ($key, $priority, $legend) = $self->legend( $colours );
# define which legend_features should be displayed
# this is being used by GlyphSet::gene_legend
## $Config->{'legend_features'}->{$key} = {
## 'priority' => $priority,
## 'legend' => $legend
## } if defined($key);
} elsif( $Config->get_parameter( 'opt_empty_tracks')!=0) {
$self->errorTrack( "No ".$self->error_track_name()." in this region" );
}
}
#============================================================================#
#
# The following three subroutines are designed to get homologous peptide ids
#
#============================================================================#
sub get_homologous_gene_ids {
## Get homologous gene ids for given gene....
my( $self, $gene_id, $species ) = @_;
my $compara_db = $self->{'container'}->adaptor->db->get_db_adaptor('compara');
my $ma = $compara_db->get_MemberAdaptor;
my $qy_member = $ma->fetch_by_source_stable_id("ENSEMBLGENE",$gene_id);
return () unless (defined $qy_member);
my $ha = $compara_db->get_HomologyAdaptor;
my @homologues;
foreach my $homology (@{$ha->fetch_by_Member_paired_species($qy_member, $species)}){
foreach my $member_attribute (@{$homology->get_all_Member_Attribute}) {
my ($member, $attribute) = @{$member_attribute};
next if ($member->stable_id eq $qy_member->stable_id);
push @homologues, $member->stable_id;
}
}
return @homologues;
}
sub get_homologous_peptide_ids_from_gene {
## Get homologous protein ids for given gene....
my( $self, $gene_id, $species ) = @_;
my $compara_db = $self->{'container'}->adaptor->db->get_db_adaptor('compara');
return unless $compara_db;
my $ma = $compara_db->get_MemberAdaptor;
return () unless $ma;
my $qy_member = $ma->fetch_by_source_stable_id("ENSEMBLGENE",$gene_id);
return () unless (defined $qy_member);
my $ha = $compara_db->get_HomologyAdaptor;
my @homologues;
my $STABLE_ID = undef;
my $peptide_id = undef;
foreach my $homology (@{$ha->fetch_by_Member_paired_species($qy_member, $species)}){
foreach my $member_attribute (@{$homology->get_all_Member_Attribute}) {
my ($member, $attribute) = @{$member_attribute};
if( $member->stable_id eq $qy_member->stable_id ) {
unless( $STABLE_ID) {
my $T = $ma->fetch_by_dbID( $peptide_id = $attribute->peptide_member_id );
$STABLE_ID = $T->stable_id;
}
} else {
push @homologues, $attribute->peptide_member_id;
}
}
}
return ( $STABLE_ID, $peptide_id, \@homologues );
}
sub get_homologous_peptide_ids {
my( $self, $gene_id, $species ) = @_;
my $compara_db = $self->{'container'}->adaptor->db->get_db_adaptor('compara');
my $peptide_sql = qq(select m.stable_id
from homology_member as hm, member as m, source as s, genome_db as gd,
homology_member as ohm, member as om, genome_db as ogd
where m.member_id = hm.peptide_member_id and hm.homology_id = ohm.homology_id and
ohm.peptide_member_id = om.member_id and
om.source_id = s.source_id and m.source_id = s.source_id and s.source_name = 'ENSEMBLPEP' and
m.genome_db_id = gd.genome_db_id and gd.name = ? and
om.genome_db_id = ogd.genome_db_id and ogd.name = ? and
om.stable_id = ?);
( my $current_species = $self->{'container'}{web_species} ) =~ s/_/ /g;
( my $other_species = $species ) =~ s/_/ /g;
my $results = $compara_db->prepare( $peptide_sql );
$results->execute( $other_species, $current_species, $gene_id );
return map {@$_} @{$results->fetchall_arrayref};
}
#============================================================================#
#
# Helper functions....
#
#============================================================================#
sub title {
### Generate title tag (which will be used to render z-menu...)
my( $self, $transcript, $gene ) = @_;
my $title = 'Transcript: '.$transcript->stable_id;
if( $gene->stable_id ) {
$title .= '; Gene: '.$gene->stable_id;
}
$title .= '; Location: '.$transcript->seq_region_name.':'.$transcript->seq_region_start.'-'.$transcript->seq_region_end;
return $title
}
sub gene_title {
### Generate title tag for gene (which will be used to render z-menu...)
my( $self, $gene ) = @_;
my $title = 'Gene: '.$gene->stable_id;
$title .= '; Location: '.$gene->seq_region_name.':'.$gene->seq_region_start.'-'.$gene->seq_region_end;
return $title;
}
sub render_genes {
my $self = shift;
return $self->render_text('gene') if $self->{'text_export'};
my $vc = $self->{'container'};
my $type = $self->check();
my $h = 8;
my $FONT = $self->species_defs->ENSEMBL_STYLE->{'GRAPHIC_FONT'};
my $FONTSIZE = $self->species_defs->ENSEMBL_STYLE->{'GRAPHIC_FONTSIZE'} *
$self->species_defs->ENSEMBL_STYLE->{'GRAPHIC_OUTERTEXT'};
my %highlights;
@highlights{$self->highlights} = (); # build hashkeys of highlight list
$self->_init_bump();
my $vc_length = $vc->length;
my $pix_per_bp = $self->scalex;
my $max_length = $self->my_config('threshold') || 1e6;
my $max_length_nav = $self->my_config('navigation_threshold') || 50e3;
my $navigation = $self->my_config('navigation') || 'on';
if( $vc_length > ($max_length*1001)) {
$self->errorTrack("Genes only displayed for less than $max_length Kb.");
return;
}
my $show_navigation = $navigation eq 'on' && ( $vc->length() < $max_length_nav * 1001 );
#First of all let us deal with all the EnsEMBL genes....
my $offset = $vc->start - 1;
my %gene_objs;
my $F = 0;
my $fontname = $self->species_defs->ENSEMBL_STYLE->{'GRAPHIC_FONT'}; # "Small";
my $database = $self->my_config( 'db' );
my $used_colours = {};
my $FLAG = 0;
## We need to store the genes to label...
my @GENES_TO_LABEL = ();
my $genes = $self->features( 1 );
my $strand_flag = $self->my_config('strand');
my $strand = $self->strand();
foreach my $g (@$genes) {
my $gene_strand = $g->strand;
next if $gene_strand != $strand && $strand_flag eq 'b';
my $gene_key = $self->gene_key( $g );
my $gene_col = $self->my_colour( $gene_key );
my $gene_type = $self->my_colour( $gene_key, 'text' );
my $label = $g->external_name || $g->stable_id;
# my $high = exists $highlights{ lc($gene_label) } || exists $highlights{ lc($g->stable_id) };
my $high = $g->stable_id eq $self->{'config'}{'_core'}{'parameters'}{'g'};
my $start = $g->start;
my $end = $g->end;
my ($chr_start, $chr_end) = $self->slice2sr( $start, $end );
next if $end < 1 || $start > $vc_length;
$start = 1 if $start<1;
$end = $vc_length if $end > $vc_length;
my $HREF;
my $rect = $self->Rect({
'x' => $start-1,
'y' => 0,
'width' => $end - $start+1,
'height' => $h,
'colour' => $gene_col,
'absolutey' => 1,
});
$rect->{'title'} = ( $g->external_name ? $g->external_name.'; ':'' ).
"Gene: ".$g->stable_id."; Location: ".
$g->seq_region_name.':'.$g->seq_region_start.'-'.$g->seq_region_end;
if($show_navigation) {
$rect->{'href'} = $self->_url({'type'=>'Gene','action'=>'Summary','g'=>$g->stable_id,'db'=>$database});
}
push @GENES_TO_LABEL , {
'start' => $start,
'label' => $label,
'end' => $end,
'href' => $rect->{'href'},
'title' => $rect->{'title'},
'gene' => $g,
'col' => $gene_col,
'highlight' => $high
};
my $bump_start = int($rect->x() * $pix_per_bp);
my $bump_end = $bump_start + int($rect->width()*$pix_per_bp) +1;
my $row = $self->bump_row( $bump_start, $bump_end );
$rect->y($rect->y() + (6 * $row ));
$rect->height(4);
$self->push($rect);
$self->unshift($self->Rect({
'x' => $start -1 - 1/$pix_per_bp,
'y' => $rect->y()-1,
'width' => $end - $start +1 + 2/$pix_per_bp,
'height' => $rect->height()+2,
'colour' => 'highlight2',
'absolutey' => 1,
})) if $high;
$FLAG=1;
}
if($FLAG) { ## NOW WE NEED TO ADD THE LABELS_TRACK.... FOLLOWED BY THE LEGEND
my $GL_FLAG = $self->get_parameter( 'opt_gene_labels' );
$GL_FLAG = 1 unless defined($GL_FLAG);
$GL_FLAG = shift if @_;
$GL_FLAG = 0 if ( $self->my_config( 'label_threshold' ) || 50e3 )*1001 < $vc->length;
if( $GL_FLAG ) {
my $START_ROW = $self->_max_bump_row+1;
$self->_init_bump;
my($a,$b,$c,$H) = $self->get_text_width( 0,'X_y','','font'=>$FONT,'ptsize'=>$FONTSIZE);
foreach my $gr ( @GENES_TO_LABEL ) {
my( $txt, $part, $W, $H2 ) = $self->get_text_width( 0, "$gr->{'label'} ", '', 'font' => $FONT, 'ptsize' => $FONTSIZE );
my $tglyph = $self->Text({
'x' => $gr->{'start'}-1 + 4/$pix_per_bp,
'y' => 0,
'height' => $H,
'width' => $W / $pix_per_bp,
'font' => $FONT,
'halign' => 'left',
'ptsize' => $FONTSIZE,
'colour' => $gr->{'col'},
'text' => "$gr->{'label'}",
'title' => $gr->{'title'},
'href' => $gr->{'href'},
'absolutey' => 1,
});
my $bump_start = int($tglyph->{'x'} * $pix_per_bp) - 4;
my $bump_end = $bump_start + int($tglyph->width()*$pix_per_bp) +1;
my $row = $self->bump_row( $bump_start, $bump_end );
$tglyph->y($tglyph->{'y'} + $row * (2+$H) + ($START_ROW-1) * 6);
$self->push(
$tglyph,
# Draw little taggy bit to indicate start of gene
$self->Rect({
'x' => $gr->{'start'}-1,
'y' => $tglyph->y + 2,
'width' => 0,
'height' => 4,
'bordercolour' => $gr->{'col'},
'absolutey' => 1,
}),
$self->Rect({
'x' => $gr->{'start'}-1,
'y' => $tglyph->y + 2 + 4,
'width' => 3/$pix_per_bp,
'height' => 0,
'bordercolour' => $gr->{'col'},
'absolutey' => 1,
})
);
$self->unshift($self->Rect({
'x' => $gr->{'start'}-1 - 1/$pix_per_bp,
'y' => $tglyph->y()+1,
'width' => $tglyph->width() +1 + 2/$pix_per_bp,
'height' => $tglyph->height()+2,
'colour' => 'highlight2',
'absolutey' => 1,
})) if $gr->{'highlight'};
}
}
#$Config->{'legend_features'}->{$type} = {
# 'priority' => $Config->get( $type, 'pos' ),
# 'legend' => $self->legend( $used_colours )
# };
}
}
#sub legend {
# my( $self, $colours ) = @_;
# my @legend = ();
# my %X;
# foreach my $Y ( values %$colours ) { $X{$Y->[1]} = $Y->[0]; }
# my @legend = %X;
# return \@legend;
#}
sub render_text {
my $self = shift;
my ($feature_type, $collapsed) = @_;
my $strand_flag = $self->my_config('strand') || 'b';
my $container = exists $self->{'container'}{'ref'} ? $self->{'container'}{'ref'} : $self->{'container'};
my $target = $self->get_parameter('single_Transcript');
my $target_gene = $self->get_parameter('single_Gene');
my $strand = $self->strand;
my $length = $container->length;
my $export;
foreach my $gene (@{$self->features}) { # For alternate splicing diagram only draw transcripts in gene
my $gene_id = $gene->can('stable_id') ? $gene->stable_id : undef;
next if $target_gene && $gene_id ne $target_gene;
my $gene_type = $gene->status . '_' . $gene->biotype;
my $gene_name = $gene->can('display_xref') && $gene->display_xref ? $gene->display_xref->display_id : undef;
if ($feature_type eq 'gene') {
$export .= $self->_render_text($gene, 'Gene', {
'headers' => [ 'gene_id', 'gene_name', 'gene_type' ],
'values' => [ $gene_id, $gene_name, $gene_type ]
});
} else {
my $exons = {};
foreach my $transcript (@{$gene->get_all_Transcripts}) {
next if $transcript->start > $length || $transcript->end < 1;
my $transcript_id = $transcript->stable_id;
next if $target && ($transcript_id ne $target); # For exon_structure diagram only given transcript
my $transcript_name =
$transcript->can('display_xref') && $transcript->display_xref ? $transcript->display_xref->display_id :
$transcript->can('analysis') && $transcript->analysis ? $transcript->analysis->logic_name :
undef;
foreach (sort { $a->start <=> $b->start } @{$transcript->get_all_Exons}) {
next if $_->start > $length || $_->end < 1;
if ($collapsed) {
my $stable_id = $_->stable_id;
next if $exons->{$stable_id};
$exons->{$stable_id} = 1;
}
$export .= $self->export_feature($_, $transcript_id, $transcript_name, $gene_id, $gene_name, $gene_type);
}
}
}
}
return $export;
}
1;