diff variant_effect_predictor/Bio/Graphics/Glyph/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/arrow.pm	Thu Apr 11 02:01:53 2013 -0400
@@ -0,0 +1,388 @@
+package Bio::Graphics::Glyph::arrow;
+# package to use for drawing an arrow
+
+use strict;
+use vars '@ISA';
+use Bio::Graphics::Glyph::generic;
+@ISA = 'Bio::Graphics::Glyph::generic';
+
+my %UNITS = (n => 1e-12,
+	     n => 1e-9,
+	     u => 1e-6,
+	     m => 0.001,
+	     c => 0.01,
+	     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;
+}
+
+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');  # 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;
+
+  my $trunc_left  = $x1 < $self->panel->left;
+  my $trunc_right = $x2 > $self->panel->right;
+
+  $x1 = $self->panel->left  if $trunc_left;
+  $x2 = $self->panel->right if $trunc_right;
+
+  $trunc_left = 0  if $self->no_trunc;
+  $trunc_right = 0 if $self->no_trunc;
+
+  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 && !$trunc_left;  # west arrow
+  $self->arrowhead($gd,$x2,$center,$a2,+1) if $ne && !$trunc_right; # east arrow
+  $gd->line($x1,$center-$a2,$x1,$center+$a2,$fg) if $base_w && !$trunc_left;  #west base
+  $gd->line($x2,$center-$a2,$x2,$center+$a2,$fg) if $base_e && !$trunc_right; #east 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 $relative_coords_offset = $self->option('relative_coords_offset');
+    $relative_coords_offset = 1 unless ($relative_coords_offset);
+
+    my $start    = $relative ? $relative_coords_offset : $self->feature->start-1;
+    my $stop     = $start + $self->feature->length - 1;
+
+    my $offset   = $relative ? ($self->feature->start - $relative_coords_offset) : 0;
+    my $reversed = exists $self->{flip} || ($relative && $self->feature->strand < 0);
+
+    my $unit_label   = $self->option('units') || '';
+    my $unit_divider = $self->option('unit_divider') || 1;
+
+    my $units      = $self->calculate_units($start/$unit_divider,$self->feature->length/$unit_divider);
+    my $divisor    = $UNITS{$units} || 1;
+
+    $divisor *= $unit_divider;
+
+    my $format     = min($self->feature->length,$self->panel->length)/$divisor > 10
+      ? "%d$units%s" : "%.6g$units%s";
+
+    my $scale  = $self->option('scale') || 1;  ## Does the user want to override the internal scale?
+
+    my $model  = sprintf("$format ",$stop/($divisor*$scale),$unit_label);
+    my $minlen = $width * length($model);
+
+    my ($major_interval,$minor_interval) = $self->panel->ticks(($stop-$start+1)/$unit_divider,$minlen);
+
+    my $left  = $sw ? $x1+$height : $x1;
+    my $right = $ne ? $x2-$height : $x2;
+
+    # adjust for portions of arrow that are outside panel
+    $start += $self->panel->start - $self->feature->start
+      if $self->feature->start < $self->panel->start;
+    $stop  -= $self->feature->end - $self->panel->end
+      if $self->feature->end   > $self->panel->end;
+
+    my $first_tick = $major_interval * int(0.5 + $start/$major_interval);
+    my $last_tick  = $major_interval * int(0.5 + $stop/$major_interval);
+
+    for (my $i = $first_tick; $i <= $last_tick; $i += $major_interval) {
+
+      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;
+      my $scaled = $label/$divisor;
+      $label = sprintf($format,$scaled,$unit_label);
+
+      my $middle = $tickpos - (length($label) * $width)/2;
+      next if $middle < $left or $middle > $right;
+
+      $gd->string($font,$middle,$center+$a2-1,$label,$font_color)
+        unless ($self->option('no_tick_label'));
+    }
+
+    if ($self->option('tick') >= 2) {
+
+      $first_tick = $minor_interval * int(0.5 + $start/$minor_interval);
+      $last_tick  = $minor_interval * int(0.5 + $stop/$minor_interval);
+
+      my $a4 = $self->height/4;
+      for (my $i = $first_tick; $i <= $last_tick; $i += $minor_interval) {
+	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;
+    ($ne,$sw) = ($sw,$ne) if $self->{flip};
+  }
+  return ($sw,$ne,0,0) unless $self->option('base');
+  return ($sw,$ne,
+	  (!$sw && $self->feature->start>= $self->panel->start),
+	  (!$ne && $self->feature->end  <= $self->panel->end));
+}
+
+sub no_trunc { 0; }
+
+sub calculate_units {
+  my $self   = shift;
+  my ($start,$length) = @_;
+  return 'G' if $length >= 1e9;
+  return 'M' if $length >= 1e6;
+  return 'k' if $length >= 1e3;
+  return ''  if $length >= 1;
+  return 'c' if $length >= 1e-2;
+  return 'm' if $length >= 1e-3;
+  return 'u' if $length >= 1e-6;
+  return 'n' if $length >= 1e-9;
+  return 'p';
+}
+
+sub min { $_[0]<$_[1] ? $_[0] : $_[1] }
+
+1;
+
+__END__
+
+=head1 NAME
+
+Ace::Graphics::Glyph::arrow - The "arrow" glyph
+
+=head1 SYNOPSIS
+
+  See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>.
+
+=head1 DESCRIPTION
+
+This glyph draws arrows.  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
+
+The following options are standard among all Glyphs.  See
+L<Bio::Graphics::Glyph> for a full explanation.
+
+  Option      Description                      Default
+  ------      -----------                      -------
+
+  -fgcolor      Foreground color	       black
+
+  -outlinecolor	Synonym for -fgcolor
+
+  -bgcolor      Background color               turquoise
+
+  -fillcolor    Synonym for -bgcolor
+
+  -linewidth    Line width                     1
+
+  -height       Height of glyph		       10
+
+  -font         Glyph font		       gdSmallFont
+
+  -connector    Connector type                 0 (false)
+
+  -connector_color
+                Connector color                black
+
+  -label        Whether to draw a label	       0 (false)
+
+  -description  Whether to draw a description  0 (false)
+
+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
+
+  -parallel   Whether to draw the arrow         1 (true)
+	      parallel to the sequence
+	      or perpendicular to it.
+
+  -northeast  Force a north or east             1 (true)
+	      arrowhead(depending 
+	      on orientation)
+
+  -east       synonym of above
+
+  -southwest  Force a south or west             1 (true)
+	      arrowhead(depending 
+	      on orientation)
+
+  -west       synonym of above
+
+  -double     force-doubleheaded arrow          0 (false)
+
+  -base       Draw a vertical base at the       0 (false)
+              non-arrowhead side
+
+  -scale      Reset the labels on the arrow     0 (false)
+              to reflect an externally 
+              established scale.
+
+  -arrowstyle "regular" to create a simple      regular
+              arrowhead.  "filled" to create
+              a thick filled arrowhead
+
+  -units      add units to the tick labels      none
+              e.g. bp
+
+  -unit_divider                                 1
+              divide tick labels by the
+              indicated amount prior to
+              displaying (use, for example
+              if you want to display in
+              cR units)
+
+Set -parallel to 0 (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
+
+Lincoln Stein E<lt>lstein@cshl.orgE<gt>.
+
+Copyright (c) 2001 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