Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Graphics/Glyph/arrow.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1f6dce3d34e0 |
---|---|
1 package Bio::Graphics::Glyph::arrow; | |
2 # package to use for drawing an arrow | |
3 | |
4 use strict; | |
5 use vars '@ISA'; | |
6 use Bio::Graphics::Glyph::generic; | |
7 @ISA = 'Bio::Graphics::Glyph::generic'; | |
8 | |
9 my %UNITS = (n => 1e-12, | |
10 n => 1e-9, | |
11 u => 1e-6, | |
12 m => 0.001, | |
13 c => 0.01, | |
14 k => 1000, | |
15 M => 1_000_000, | |
16 G => 1_000_000_000); | |
17 | |
18 sub pad_bottom { | |
19 my $self = shift; | |
20 my $val = $self->SUPER::pad_bottom(@_); | |
21 $val += $self->font->height if $self->option('tick'); | |
22 $val; | |
23 } | |
24 | |
25 # override draw method | |
26 sub draw { | |
27 my $self = shift; | |
28 my $parallel = $self->option('parallel'); | |
29 $parallel = 1 unless defined $parallel; | |
30 $self->draw_parallel(@_) if $parallel; | |
31 $self->draw_perpendicular(@_) unless $parallel; | |
32 } | |
33 | |
34 sub draw_perpendicular { | |
35 my $self = shift; | |
36 my $gd = shift; | |
37 my ($dx,$dy) = @_; | |
38 my ($x1,$y1,$x2,$y2) = $self->bounds(@_); | |
39 | |
40 my $ne = $self->option('northeast'); | |
41 my $sw = $self->option('southwest'); | |
42 $ne = $sw = 1 unless defined($ne) || defined($sw); | |
43 | |
44 # draw a perpendicular arrow at position indicated by $x1 | |
45 my $fg = $self->set_pen; | |
46 my $a2 = ($y2-$y1)/4; | |
47 | |
48 my @positions = $x1 == $x2 ? ($x1) : ($x1,$x2); | |
49 for my $x (@positions) { | |
50 if ($ne) { | |
51 $gd->line($x,$y1,$x,$y2,$fg); | |
52 $gd->line($x-$a2,$y1+$a2,$x,$y1,$fg); | |
53 $gd->line($x+$a2,$y1+$a2,$x,$y1,$fg); | |
54 } | |
55 if ($sw) { | |
56 $gd->line($x,$y1,$x,$y2,$fg); | |
57 $gd->line($x-$a2,$y2-$a2,$x,$y2,$fg); | |
58 $gd->line($x+$a2,$y2-$a2,$x,$y2,$fg); | |
59 } | |
60 } | |
61 | |
62 # add a label if requested | |
63 $self->draw_label($gd,$dx,$dy) if $self->option('label'); # this draws the label aligned to the left | |
64 } | |
65 | |
66 sub draw_parallel { | |
67 my $self = shift; | |
68 my $gd = shift; | |
69 my ($dx,$dy) = @_; | |
70 my ($x1,$y1,$x2,$y2) = $self->bounds(@_); | |
71 | |
72 my $fg = $self->set_pen; | |
73 my $a2 = ($self->height)/2; | |
74 my $center = $y1+$a2; | |
75 | |
76 my $trunc_left = $x1 < $self->panel->left; | |
77 my $trunc_right = $x2 > $self->panel->right; | |
78 | |
79 $x1 = $self->panel->left if $trunc_left; | |
80 $x2 = $self->panel->right if $trunc_right; | |
81 | |
82 $trunc_left = 0 if $self->no_trunc; | |
83 $trunc_right = 0 if $self->no_trunc; | |
84 | |
85 my ($sw,$ne,$base_w,$base_e) = $self->arrowheads; | |
86 $gd->line($x1,$center,$x2,$center,$fg); | |
87 $self->arrowhead($gd,$x1,$center,$a2,-1) if $sw && !$trunc_left; # west arrow | |
88 $self->arrowhead($gd,$x2,$center,$a2,+1) if $ne && !$trunc_right; # east arrow | |
89 $gd->line($x1,$center-$a2,$x1,$center+$a2,$fg) if $base_w && !$trunc_left; #west base | |
90 $gd->line($x2,$center-$a2,$x2,$center+$a2,$fg) if $base_e && !$trunc_right; #east base | |
91 | |
92 # turn on ticks | |
93 if ($self->option('tick')) { | |
94 local $^W = 0; # dumb uninitialized variable warning | |
95 my $font = $self->font; | |
96 my $width = $font->width; | |
97 my $font_color = $self->fontcolor; | |
98 my $height = $self->height; | |
99 | |
100 my $relative = $self->option('relative_coords'); | |
101 my $relative_coords_offset = $self->option('relative_coords_offset'); | |
102 $relative_coords_offset = 1 unless ($relative_coords_offset); | |
103 | |
104 my $start = $relative ? $relative_coords_offset : $self->feature->start-1; | |
105 my $stop = $start + $self->feature->length - 1; | |
106 | |
107 my $offset = $relative ? ($self->feature->start - $relative_coords_offset) : 0; | |
108 my $reversed = exists $self->{flip} || ($relative && $self->feature->strand < 0); | |
109 | |
110 my $unit_label = $self->option('units') || ''; | |
111 my $unit_divider = $self->option('unit_divider') || 1; | |
112 | |
113 my $units = $self->calculate_units($start/$unit_divider,$self->feature->length/$unit_divider); | |
114 my $divisor = $UNITS{$units} || 1; | |
115 | |
116 $divisor *= $unit_divider; | |
117 | |
118 my $format = min($self->feature->length,$self->panel->length)/$divisor > 10 | |
119 ? "%d$units%s" : "%.6g$units%s"; | |
120 | |
121 my $scale = $self->option('scale') || 1; ## Does the user want to override the internal scale? | |
122 | |
123 my $model = sprintf("$format ",$stop/($divisor*$scale),$unit_label); | |
124 my $minlen = $width * length($model); | |
125 | |
126 my ($major_interval,$minor_interval) = $self->panel->ticks(($stop-$start+1)/$unit_divider,$minlen); | |
127 | |
128 my $left = $sw ? $x1+$height : $x1; | |
129 my $right = $ne ? $x2-$height : $x2; | |
130 | |
131 # adjust for portions of arrow that are outside panel | |
132 $start += $self->panel->start - $self->feature->start | |
133 if $self->feature->start < $self->panel->start; | |
134 $stop -= $self->feature->end - $self->panel->end | |
135 if $self->feature->end > $self->panel->end; | |
136 | |
137 my $first_tick = $major_interval * int(0.5 + $start/$major_interval); | |
138 my $last_tick = $major_interval * int(0.5 + $stop/$major_interval); | |
139 | |
140 for (my $i = $first_tick; $i <= $last_tick; $i += $major_interval) { | |
141 | |
142 my $tickpos = $dx + ($reversed ? $self->map_pt($stop - $i + $offset) | |
143 : $self->map_pt($i + $offset)); | |
144 next if $tickpos < $left or $tickpos > $right; | |
145 | |
146 $gd->line($tickpos,$center-$a2,$tickpos,$center+$a2,$fg); | |
147 my $label = $scale ? $i / $scale : $i; | |
148 my $scaled = $label/$divisor; | |
149 $label = sprintf($format,$scaled,$unit_label); | |
150 | |
151 my $middle = $tickpos - (length($label) * $width)/2; | |
152 next if $middle < $left or $middle > $right; | |
153 | |
154 $gd->string($font,$middle,$center+$a2-1,$label,$font_color) | |
155 unless ($self->option('no_tick_label')); | |
156 } | |
157 | |
158 if ($self->option('tick') >= 2) { | |
159 | |
160 $first_tick = $minor_interval * int(0.5 + $start/$minor_interval); | |
161 $last_tick = $minor_interval * int(0.5 + $stop/$minor_interval); | |
162 | |
163 my $a4 = $self->height/4; | |
164 for (my $i = $first_tick; $i <= $last_tick; $i += $minor_interval) { | |
165 my $tickpos = $dx + ($reversed ? $self->map_pt($stop - $i + $offset) | |
166 : $self->map_pt($i + $offset)); | |
167 next if $tickpos < $left or $tickpos > $right; | |
168 | |
169 $gd->line($tickpos,$center-$a4,$tickpos,$center+$a4,$fg); | |
170 } | |
171 } | |
172 } | |
173 | |
174 # add a label if requested | |
175 $self->draw_label($gd,$dx,$dy) if $self->option('label'); | |
176 $self->draw_description($gd,$dx,$dy) if $self->option('description'); | |
177 } | |
178 | |
179 sub arrowheads { | |
180 my $self = shift; | |
181 my ($ne,$sw,$base_e,$base_w); | |
182 if ($self->option('double')) { | |
183 $ne = $sw = 1; | |
184 } else { | |
185 $ne = $self->option('northeast') || $self->option('east'); | |
186 $sw = $self->option('southwest') || $self->option('west'); | |
187 } | |
188 # otherwise use strandedness to define the arrow | |
189 unless (defined($ne) || defined($sw)) { | |
190 # turn on both if neither specified | |
191 $ne = 1 if $self->feature->strand > 0; | |
192 $sw = 1 if $self->feature->strand < 0; | |
193 ($ne,$sw) = ($sw,$ne) if $self->{flip}; | |
194 } | |
195 return ($sw,$ne,0,0) unless $self->option('base'); | |
196 return ($sw,$ne, | |
197 (!$sw && $self->feature->start>= $self->panel->start), | |
198 (!$ne && $self->feature->end <= $self->panel->end)); | |
199 } | |
200 | |
201 sub no_trunc { 0; } | |
202 | |
203 sub calculate_units { | |
204 my $self = shift; | |
205 my ($start,$length) = @_; | |
206 return 'G' if $length >= 1e9; | |
207 return 'M' if $length >= 1e6; | |
208 return 'k' if $length >= 1e3; | |
209 return '' if $length >= 1; | |
210 return 'c' if $length >= 1e-2; | |
211 return 'm' if $length >= 1e-3; | |
212 return 'u' if $length >= 1e-6; | |
213 return 'n' if $length >= 1e-9; | |
214 return 'p'; | |
215 } | |
216 | |
217 sub min { $_[0]<$_[1] ? $_[0] : $_[1] } | |
218 | |
219 1; | |
220 | |
221 __END__ | |
222 | |
223 =head1 NAME | |
224 | |
225 Ace::Graphics::Glyph::arrow - The "arrow" glyph | |
226 | |
227 =head1 SYNOPSIS | |
228 | |
229 See L<Ace::Graphics::Panel> and L<Ace::Graphics::Glyph>. | |
230 | |
231 =head1 DESCRIPTION | |
232 | |
233 This glyph draws arrows. Depending on options, the arrows can be | |
234 labeled, be oriented vertically or horizontally, or can contain major | |
235 and minor ticks suitable for use as a scale. | |
236 | |
237 =head2 OPTIONS | |
238 | |
239 The following options are standard among all Glyphs. See | |
240 L<Bio::Graphics::Glyph> for a full explanation. | |
241 | |
242 Option Description Default | |
243 ------ ----------- ------- | |
244 | |
245 -fgcolor Foreground color black | |
246 | |
247 -outlinecolor Synonym for -fgcolor | |
248 | |
249 -bgcolor Background color turquoise | |
250 | |
251 -fillcolor Synonym for -bgcolor | |
252 | |
253 -linewidth Line width 1 | |
254 | |
255 -height Height of glyph 10 | |
256 | |
257 -font Glyph font gdSmallFont | |
258 | |
259 -connector Connector type 0 (false) | |
260 | |
261 -connector_color | |
262 Connector color black | |
263 | |
264 -label Whether to draw a label 0 (false) | |
265 | |
266 -description Whether to draw a description 0 (false) | |
267 | |
268 In addition to the common options, the following glyph-specific | |
269 options are recognized: | |
270 | |
271 Option Description Default | |
272 ------ ----------- ------- | |
273 | |
274 -tick Whether to draw major 0 | |
275 and minor ticks. | |
276 0 = no ticks | |
277 1 = major ticks | |
278 2 = minor ticks | |
279 | |
280 -parallel Whether to draw the arrow 1 (true) | |
281 parallel to the sequence | |
282 or perpendicular to it. | |
283 | |
284 -northeast Force a north or east 1 (true) | |
285 arrowhead(depending | |
286 on orientation) | |
287 | |
288 -east synonym of above | |
289 | |
290 -southwest Force a south or west 1 (true) | |
291 arrowhead(depending | |
292 on orientation) | |
293 | |
294 -west synonym of above | |
295 | |
296 -double force-doubleheaded arrow 0 (false) | |
297 | |
298 -base Draw a vertical base at the 0 (false) | |
299 non-arrowhead side | |
300 | |
301 -scale Reset the labels on the arrow 0 (false) | |
302 to reflect an externally | |
303 established scale. | |
304 | |
305 -arrowstyle "regular" to create a simple regular | |
306 arrowhead. "filled" to create | |
307 a thick filled arrowhead | |
308 | |
309 -units add units to the tick labels none | |
310 e.g. bp | |
311 | |
312 -unit_divider 1 | |
313 divide tick labels by the | |
314 indicated amount prior to | |
315 displaying (use, for example | |
316 if you want to display in | |
317 cR units) | |
318 | |
319 Set -parallel to 0 (false) to display a point-like feature such as a | |
320 polymorphism, or to indicate an important location. If the feature | |
321 start == end, then the glyph will draw a single arrow at the | |
322 designated location: | |
323 | |
324 ^ | |
325 | | |
326 | |
327 Otherwise, there will be two arrows at the start and end: | |
328 | |
329 ^ ^ | |
330 | | | |
331 | |
332 Scale: Pass in a externally established scale to reset the labels on | |
333 the arrow. This is particularly useful for manually constructed | |
334 images where the founding parameters of the panel are not 1-based. | |
335 For example, a genetic map interval ranging from 0.1 - 0.3 can be | |
336 constructed by first multiplying every value by 100. Passing | |
337 | |
338 arrow(-scale=>100); | |
339 | |
340 will draw tick marks labelled appropriately to your external scale. | |
341 | |
342 =head1 BUGS | |
343 | |
344 Please report them. | |
345 | |
346 =head1 SEE ALSO | |
347 | |
348 L<Bio::Graphics::Panel>, | |
349 L<Bio::Graphics::Glyph>, | |
350 L<Bio::Graphics::Glyph::arrow>, | |
351 L<Bio::Graphics::Glyph::cds>, | |
352 L<Bio::Graphics::Glyph::crossbox>, | |
353 L<Bio::Graphics::Glyph::diamond>, | |
354 L<Bio::Graphics::Glyph::dna>, | |
355 L<Bio::Graphics::Glyph::dot>, | |
356 L<Bio::Graphics::Glyph::ellipse>, | |
357 L<Bio::Graphics::Glyph::extending_arrow>, | |
358 L<Bio::Graphics::Glyph::generic>, | |
359 L<Bio::Graphics::Glyph::graded_segments>, | |
360 L<Bio::Graphics::Glyph::heterogeneous_segments>, | |
361 L<Bio::Graphics::Glyph::line>, | |
362 L<Bio::Graphics::Glyph::pinsertion>, | |
363 L<Bio::Graphics::Glyph::primers>, | |
364 L<Bio::Graphics::Glyph::rndrect>, | |
365 L<Bio::Graphics::Glyph::segments>, | |
366 L<Bio::Graphics::Glyph::ruler_arrow>, | |
367 L<Bio::Graphics::Glyph::toomany>, | |
368 L<Bio::Graphics::Glyph::transcript>, | |
369 L<Bio::Graphics::Glyph::transcript2>, | |
370 L<Bio::Graphics::Glyph::translation>, | |
371 L<Bio::Graphics::Glyph::triangle>, | |
372 L<Bio::DB::GFF>, | |
373 L<Bio::SeqI>, | |
374 L<Bio::SeqFeatureI>, | |
375 L<Bio::Das>, | |
376 L<GD> | |
377 | |
378 =head1 AUTHOR | |
379 | |
380 Lincoln Stein E<lt>lstein@cshl.orgE<gt>. | |
381 | |
382 Copyright (c) 2001 Cold Spring Harbor Laboratory | |
383 | |
384 This library is free software; you can redistribute it and/or modify | |
385 it under the same terms as Perl itself. See DISCLAIMER.txt for | |
386 disclaimers of warranty. | |
387 | |
388 =cut |