diff variant_effect_predictor/Bio/Graphics/Glyph/ruler_arrow.pm @ 0:1f6dce3d34e0

Uploaded
author mahtabm
date Thu, 11 Apr 2013 02:01:53 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/variant_effect_predictor/Bio/Graphics/Glyph/ruler_arrow.pm	Thu Apr 11 02:01:53 2013 -0400
@@ -0,0 +1,351 @@
+package Bio::Graphics::Glyph::ruler_arrow;
+# package to use for drawing an arrow as ruler (5' and 3' are marked as label)
+
+use strict;
+use vars '@ISA';
+use Bio::Graphics::Glyph::generic;
+@ISA = 'Bio::Graphics::Glyph::generic';
+
+my %UNITS = (K => 1000,
+	     M => 1_000_000,
+	     G => 1_000_000_000);
+
+sub pad_bottom {
+  my $self = shift;
+  my $val = $self->SUPER::pad_bottom(@_);
+  $val += $self->font->height if $self->option('tick');
+  $val;
+}
+
+# override draw method
+sub draw {
+  my $self = shift;
+  my $parallel = $self->option('parallel');
+  $parallel = 1 unless defined $parallel;
+  $self->draw_parallel(@_) if $parallel;
+  $self->draw_perpendicular(@_) unless $parallel;
+  $self->draw_label(@_) if ($self->option('label'));
+}
+
+sub draw_perpendicular {
+  my $self = shift;
+  my $gd = shift;
+  my ($dx,$dy) = @_;
+  my ($x1,$y1,$x2,$y2) = $self->bounds(@_);
+
+  my $ne = $self->option('northeast');
+  my $sw = $self->option('southwest');
+  $ne = $sw = 1 unless defined($ne) || defined($sw);
+
+  # draw a perpendicular arrow at position indicated by $x1
+  my $fg = $self->set_pen;
+  my $a2 = ($y2-$y1)/4;
+
+  my @positions = $x1 == $x2 ? ($x1) : ($x1,$x2);
+  for my $x (@positions) {
+    if ($ne) {
+      $gd->line($x,$y1,$x,$y2,$fg);
+      $gd->line($x-$a2,$y1+$a2,$x,$y1,$fg);
+      $gd->line($x+$a2,$y1+$a2,$x,$y1,$fg);
+    }
+    if ($sw) {
+      $gd->line($x,$y1,$x,$y2,$fg);
+      $gd->line($x-$a2,$y2-$a2,$x,$y2,$fg);
+      $gd->line($x+$a2,$y2-$a2,$x,$y2,$fg);
+    }
+  }
+
+  # add a label if requested
+#  $self->draw_label($gd,$dx,$dy) if ($self->option('label') && !$self->option('ruler'));
+  # this draws the label aligned to the left
+}
+
+sub draw_parallel {
+  my $self = shift;
+  my $gd = shift;
+  my ($dx,$dy) = @_;
+  my ($x1,$y1,$x2,$y2) = $self->bounds(@_);
+
+  my $fg = $self->set_pen;
+  my $a2 = ($self->height)/2;
+  my $center = $y1+$a2;
+
+  $x1 = $self->panel->left  if $x1 < $self->panel->left;
+  $x2 = $self->panel->right if $x2 > $self->panel->right;
+
+  my ($sw,$ne,$base_w,$base_e) = $self->arrowheads;
+  $gd->line($x1,$center,$x2,$center,$fg);
+  $self->arrowhead($gd,$x1,$center,$a2,-1) if $sw; # west arrow
+  $self->arrowhead($gd,$x2,$center,$a2,+1) if $ne; # east arrow
+  $gd->line($x2,$center-$a2,$x2,$center+$a2,$fg) if $base_e; #east base
+  $gd->line($x1,$center-$a2,$x1,$center+$a2,$fg) if $base_w; #west base
+
+  # turn on ticks
+  if ($self->option('tick')) {
+      local $^W = 0;  # dumb uninitialized variable warning
+    my $font = $self->font;
+    my $width      = $font->width;
+    my $font_color = $self->fontcolor;
+    my $height   = $self->height;
+
+    my $relative = $self->option('relative_coords');
+    my $start    = $relative ? 1 : $self->feature->start;
+    my $stop     = $start + $self->feature->length  - 1;
+
+    my $offset   = $relative ? $self->feature->start-1 : 0;
+    my $reversed = $self->feature->strand < 0;
+
+    my $units = $self->option('units') || '';
+    my $divisor = $UNITS{$units} || 1 if $units;
+
+    my ($major_ticks,$minor_ticks) = $self->panel->ticks($start,$stop,$font,$divisor);
+
+    ## Does the user want to override the internal scale?
+    my $scale = $self->option('scale');
+
+    my $left  = $sw ? $x1+$height : $x1;
+    my $right = $ne ? $x2-$height : $x2;
+
+    my $format = ($major_ticks->[1]-$major_ticks->[0])/($divisor||1) < 1 ? "%.1f$units" : "%d$units";
+
+    for my $i (@$major_ticks) {
+      my $tickpos = $dx + ($reversed ? $self->map_pt($stop - $i + $offset)
+	                             : $self->map_pt($i + $offset));
+      next if $tickpos < $left or $tickpos > $right;
+      $gd->line($tickpos,$center-$a2,$tickpos,$center+$a2,$fg);
+      my $label = $scale ? $i / $scale : $i;
+      if ($units) {
+	my $scaled = $label/$divisor;
+	$label = sprintf($format,$scaled);
+      }
+      my $middle = $tickpos - (length($label) * $width)/2;
+      $gd->string($font,$middle,$center+$a2-1,$label,$font_color)
+        unless ($self->option('no_tick_label'));
+    }
+
+    if ($self->option('tick') >= 2) {
+      my $a4 = $self->height/4;
+      for my $i (@$minor_ticks) {
+	my $tickpos = $dx + ($reversed ? $self->map_pt($stop - $i + $offset)
+	                               : $self->map_pt($i + $offset));
+	next if $tickpos < $left or $tickpos > $right;
+	$gd->line($tickpos,$center-$a4,$tickpos,$center+$a4,$fg);
+      }
+    }
+  }
+
+  # add a label if requested
+#  $self->draw_label($gd,$dx,$dy)       if ($self->option('label');
+#  $self->draw_description($gd,$dx,$dy) if $self->option('description');
+}
+
+sub arrowheads {
+  my $self = shift;
+  my ($ne,$sw,$base_e,$base_w);
+  if ($self->option('double')) {
+    $ne = $sw = 1;
+  } else {
+    $ne   = $self->option('northeast') || $self->option('east');
+    $sw   = $self->option('southwest') || $self->option('west');
+  }
+  # otherwise use strandedness to define the arrow
+  unless (defined($ne) || defined($sw)) {
+    # turn on both if neither specified
+    $ne = 1 if $self->feature->strand > 0;
+    $sw = 1 if $self->feature->strand < 0;
+  }
+  return ($sw,$ne,0,0) unless $self->option('base');
+  return ($sw,$ne,!$sw,!$ne);
+}
+
+sub draw_label {
+  my $self = shift;
+  my ($gd,$left,$top) = @_;
+
+  my $label5 = "5'";
+  my $label3 = "3'";
+  my $relative = $self->option('relative_coords');
+  my $start    = $relative ? 1 : $self->feature->start;
+  my $stop     = $start + $self->feature->length  - 1;
+
+  my $offset   = $relative ? $self->feature->start-1 : 0;
+  my $reversed = $self->feature->strand < 0;
+
+  my $units = $self->option('units') || '';
+  my $divisor = $UNITS{$units} || 1 if $units;
+
+  my ($major_ticks,$minor_ticks) = $self->panel->ticks($start,$stop,$self->font,$divisor);
+  my $tick_scale = " ($major_ticks bp/";
+  $tick_scale .= ($self->option('tick') >= 2)?"major tick)":"tick)";
+
+  my $top_left_label = $label5;
+  $top_left_label .= $tick_scale if ($self->option('no_tick_label') && $self->option('tick'));
+  #-1 direction mean lower end is 3' (minus strand on top)
+  ($label5, $label3) = ($label3, $label5) if ($self->option('direction') == -1);
+  my $x = $self->left + $left;
+  $x = $self->panel->left + 1 if $x <= $self->panel->left;
+  my $font = $self->option('labelfont') || $self->font;
+  $gd->string($font,
+              $x,
+              $self->top + $top,
+              $top_left_label,
+              $self->fontcolor);
+  my $x1 = $left + $self->panel->right - $font->width*length($label3);
+  $gd->string($font,
+              $x1,
+              $self->top + $top,
+              $label3,
+              $self->fontcolor);
+  if ($self->option('both')) {#minus strand as well
+      $gd->string($font,
+                  $x,
+                  $self->bottom - $self->pad_bottom + $top,
+                  $label3,
+                  $self->fontcolor);
+      my $x1 = $left + $self->panel->right - $font->width*length($label5);
+      $gd->string($font,
+                  $x1,
+                  $self->bottom - $self->pad_bottom + $top,
+                  $label5,
+                  $self->fontcolor);
+  }
+}
+
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Bio::Graphics::Glyph::arrow - The "ruler_arrow" glyph
+
+=head1 SYNOPSIS
+
+  See L<Bio::Graphics::Panel> and L<Bio::Graphics::Glyph>.
+
+=head1 DESCRIPTION
+
+This glyph draws arrows.  Label, if requested, will be 5' and 3' at both ends
+and tick scale is printed if no_tick_label option is set and tick option set.
+Depending on options, the arrows can be labeled, be oriented vertically 
+or horizontally, or can contain major and minor ticks suitable for use as a scale.
+
+=head2 OPTIONS
+
+In addition to the common options, the following glyph-specific
+options are recognized:
+
+  Option      Description               Default
+  ------      -----------               -------
+
+  -tick       Whether to draw major         0
+              and minor ticks.
+	      0 = no ticks
+	      1 = major ticks
+	      2 = minor ticks
+  -label      5' at start, 3' at end        0
+              above arrow
+  -both       5', 3' above,                 0
+              and 3', 5' below arrow
+  -direction  0 = ruler is plus strand      0
+              -1 = ruler is minus strand
+
+  -parallel   Whether to draw the arrow     true
+	      parallel to the sequence
+	      or perpendicular to it.
+
+  -northeast  Force a north or east         true
+	      arrowhead(depending 
+	      on orientation)
+
+  -east       synonym of above
+
+  -southwest  Force a south or west         true
+	      arrowhead(depending 
+	      on orientation)
+
+  -west       synonym of above
+
+  -double     force-doubleheaded arrow
+
+  -base       Draw a vertical base at the   false
+              non-arrowhead side
+
+  -scale      Reset the labels on the arrow false
+              to reflect an externally 
+              established scale.
+
+Set -parallel to false to display a point-like feature such as a
+polymorphism, or to indicate an important location.  If the feature
+start == end, then the glyph will draw a single arrow at the
+designated location:
+
+       ^
+       |
+
+Otherwise, there will be two arrows at the start and end:
+
+       ^              ^
+       |              |
+
+Scale: Pass in a externally established scale to reset the labels on
+the arrow.  This is particularly useful for manually constructed
+images where the founding parameters of the panel are not 1-based.
+For example, a genetic map interval ranging from 0.1 - 0.3 can be
+constructed by first multiplying every value by 100. Passing
+
+  arrow(-scale=>100);
+
+will draw tick marks labelled appropriately to your external scale.
+
+=head1 BUGS
+
+Please report them.
+
+=head1 SEE ALSO
+
+
+L<Bio::Graphics::Panel>,
+L<Bio::Graphics::Glyph>,
+L<Bio::Graphics::Glyph::arrow>,
+L<Bio::Graphics::Glyph::cds>,
+L<Bio::Graphics::Glyph::crossbox>,
+L<Bio::Graphics::Glyph::diamond>,
+L<Bio::Graphics::Glyph::dna>,
+L<Bio::Graphics::Glyph::dot>,
+L<Bio::Graphics::Glyph::ellipse>,
+L<Bio::Graphics::Glyph::extending_arrow>,
+L<Bio::Graphics::Glyph::generic>,
+L<Bio::Graphics::Glyph::graded_segments>,
+L<Bio::Graphics::Glyph::heterogeneous_segments>,
+L<Bio::Graphics::Glyph::line>,
+L<Bio::Graphics::Glyph::pinsertion>,
+L<Bio::Graphics::Glyph::primers>,
+L<Bio::Graphics::Glyph::rndrect>,
+L<Bio::Graphics::Glyph::segments>,
+L<Bio::Graphics::Glyph::ruler_arrow>,
+L<Bio::Graphics::Glyph::toomany>,
+L<Bio::Graphics::Glyph::transcript>,
+L<Bio::Graphics::Glyph::transcript2>,
+L<Bio::Graphics::Glyph::translation>,
+L<Bio::Graphics::Glyph::triangle>,
+L<Bio::DB::GFF>,
+L<Bio::SeqI>,
+L<Bio::SeqFeatureI>,
+L<Bio::Das>,
+L<GD>
+
+=head1 AUTHOR
+
+Shengqiang Shu E<lt>sshu@bdgp.lbl.govE<gt>
+Lincoln Stein E<lt>lstein@cshl.orgE<gt>.
+
+Copyright (c) 2001 BDGP, Cold Spring Harbor Laboratory
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.  See DISCLAIMER.txt for
+disclaimers of warranty.
+
+=cut