Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Graphics/Glyph/segments.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::segments; | |
2 #$Id: segments.pm,v 1.21.2.1 2003/07/05 00:32:04 lstein Exp $ | |
3 | |
4 use strict; | |
5 use Bio::Location::Simple; | |
6 use Bio::Graphics::Glyph::generic; | |
7 use Bio::Graphics::Glyph::segmented_keyglyph; | |
8 use vars '@ISA'; | |
9 | |
10 use constant RAGGED_START_FUZZ => 25; # will show ragged ends of alignments | |
11 # up to this many bp. | |
12 use constant DEBUG => 0; | |
13 | |
14 @ISA = qw( Bio::Graphics::Glyph::segmented_keyglyph | |
15 Bio::Graphics::Glyph::generic | |
16 ); | |
17 | |
18 my %complement = (g=>'c',a=>'t',t=>'a',c=>'g',n=>'n', | |
19 G=>'C',A=>'T',T=>'A',C=>'G',N=>'N'); | |
20 | |
21 sub pad_left { | |
22 my $self = shift; | |
23 return $self->SUPER::pad_left unless $self->option('draw_target') && $self->option('ragged_start') && $self->dna_fits; | |
24 return $self->SUPER::pad_left unless $self->level > 0; | |
25 my $target = eval {$self->feature->hit} or return $self->SUPER::pad_left; | |
26 return $self->SUPER::pad_left unless $target->start<$target->end && $target->start < RAGGED_START_FUZZ; | |
27 return ($target->start-1) * $self->scale; | |
28 } | |
29 | |
30 sub pad_right { | |
31 my $self = shift; | |
32 return $self->SUPER::pad_right unless $self->level > 0; | |
33 return $self->SUPER::pad_right unless $self->option('draw_target') && $self->option('ragged_start') && $self->dna_fits; | |
34 my $target = eval {$self->feature->hit} or return $self->SUPER::pad_right; | |
35 return $self->SUPER::pad_right unless $target->end < $target->start && $target->start < RAGGED_START_FUZZ; | |
36 return ($target->end-1) * $self->scale; | |
37 } | |
38 | |
39 # group sets connector to 'solid' | |
40 sub connector { | |
41 my $self = shift; | |
42 return $self->SUPER::connector(@_) if $self->all_callbacks; | |
43 return ($self->SUPER::connector(@_) || 'solid'); | |
44 } | |
45 | |
46 # never allow our components to bump | |
47 sub bump { | |
48 my $self = shift; | |
49 return $self->SUPER::bump(@_) if $self->all_callbacks; | |
50 return 0; | |
51 } | |
52 | |
53 sub fontcolor { | |
54 my $self = shift; | |
55 return $self->SUPER::fontcolor unless $self->option('draw_target') || $self->option('draw_dna'); | |
56 return $self->SUPER::fontcolor unless $self->dna_fits; | |
57 return $self->bgcolor; | |
58 } | |
59 | |
60 sub draw_component { | |
61 my $self = shift; | |
62 my ($draw_dna,$draw_target) = ($self->option('draw_dna'),$self->option('draw_target')); | |
63 return $self->SUPER::draw_component(@_) | |
64 unless $draw_dna || $draw_target; | |
65 return $self->SUPER::draw_component(@_) unless $self->dna_fits; | |
66 | |
67 my $dna = $draw_target ? eval {$self->feature->hit->seq} | |
68 : eval {$self->feature->seq}; | |
69 return $self->SUPER::draw_component(@_) unless length $dna > 0; # safety | |
70 | |
71 my $show_mismatch = $draw_target && $self->option('show_mismatch'); | |
72 my $genomic = eval {$self->feature->seq} if $show_mismatch; | |
73 | |
74 my $gd = shift; | |
75 my ($x1,$y1,$x2,$y2) = $self->bounds(@_); | |
76 | |
77 # adjust for nonaligned left end (for ESTs...) The size given here is roughly sufficient | |
78 # to show a polyA end or a C. elegans trans-spliced leader. | |
79 my $offset = 0; | |
80 eval { # protect against data structures that don't implement the target() method. | |
81 if ($draw_target && $self->option('ragged_start')){ | |
82 my $target = $self->feature->hit; | |
83 if ($target->start < $target->end && $target->start < RAGGED_START_FUZZ | |
84 && $self->{partno} == 0) { | |
85 $offset = $target->start - 1; | |
86 if ($offset > 0) { | |
87 $dna = $target->subseq(1-$offset,0)->seq . $dna; | |
88 $genomic = $self->feature->subseq(1-$offset,0)->seq . $genomic; | |
89 $x1 -= $offset * $self->scale; | |
90 } | |
91 } | |
92 elsif ($target->end < $target->start && | |
93 $target->end < RAGGED_START_FUZZ && $self->{partno} == $self->{total_parts}) { | |
94 $offset = $target->end - 1; | |
95 if ($offset > 0) { | |
96 $dna .= $target->factory->get_dna($target,$offset,1); | |
97 $genomic = $self->feature->subseq(-$offset,0)->seq . $genomic; | |
98 $x2 += $offset * $self->scale; | |
99 $offset = 0; | |
100 } | |
101 } | |
102 } | |
103 }; | |
104 | |
105 $self->draw_dna($gd,$offset,lc $dna,lc $genomic,$x1,$y1,$x2,$y2); | |
106 } | |
107 | |
108 sub draw_dna { | |
109 my $self = shift; | |
110 | |
111 my ($gd,$start_offset,$dna,$genomic,$x1,$y1,$x2,$y2) = @_; | |
112 my $pixels_per_base = $self->scale; | |
113 my $feature = $self->feature; | |
114 my $target = $feature->target; | |
115 my $strand = $feature->strand; | |
116 | |
117 my @segs; | |
118 | |
119 my $complement = $strand < 0; | |
120 | |
121 if ($self->{flip}) { | |
122 $dna = $self->reversec($dna); | |
123 $genomic = $self->reversec($genomic); | |
124 $strand *= -1; | |
125 } | |
126 | |
127 warn "strand = $strand, complement = $complement" if DEBUG; | |
128 | |
129 if ($genomic && length($genomic) != length($dna) && eval { require Bio::Graphics::Browser::Realign}) { | |
130 warn "$genomic\n$dna\n" if DEBUG; | |
131 warn "strand = $strand" if DEBUG; | |
132 @segs = Bio::Graphics::Browser::Realign::align_segs($genomic,$dna); | |
133 for my $seg (@segs) { | |
134 my $src = substr($genomic,$seg->[0],$seg->[1]-$seg->[0]+1); | |
135 my $tgt = substr($dna, $seg->[2],$seg->[3]-$seg->[2]+1); | |
136 warn "@$seg\n$src\n$tgt" if DEBUG; | |
137 } | |
138 } else { | |
139 @segs = [0,length($genomic)-1,0,length($dna)-1]; | |
140 } | |
141 | |
142 my $color = $self->fgcolor; | |
143 my $font = $self->font; | |
144 my $lineheight = $font->height; | |
145 my $fontwidth = $font->width; | |
146 $y1 -= $lineheight/2 - 3; | |
147 my $pink = $self->factory->translate_color('lightpink'); | |
148 my $panel_end = $self->panel->right; | |
149 | |
150 my $start = $self->map_no_trunc($self->feature->start- $start_offset); | |
151 my $end = $self->map_no_trunc($self->feature->end - $start_offset); | |
152 | |
153 my ($last,$tlast); | |
154 for my $seg (@segs) { | |
155 | |
156 # fill in misaligned bits with dashes and bases | |
157 if (defined $last) { | |
158 my $delta = $seg->[0] - $last - 1; | |
159 my $tdelta = $seg->[2] - $tlast - 1; | |
160 warn "src gap [$last,$seg->[0]], tgt gap [$tlast,$seg->[2]], delta = $delta, tdelta = $tdelta\n" if DEBUG; | |
161 | |
162 my $gaps = $delta - $tdelta; | |
163 my @fill_in = split '',substr($dna,$tlast+1,$tdelta) if $tdelta > 0; | |
164 unshift @fill_in,('-')x$gaps if $gaps > 0; | |
165 | |
166 warn "gaps = $gaps, fill_in = @fill_in\n" if DEBUG; | |
167 | |
168 my $distance = $pixels_per_base * ($delta+1); | |
169 my $pixels_per_target = $gaps >= 0 ? $pixels_per_base : $distance/(@fill_in+1); | |
170 | |
171 warn "pixels_per_base = $pixels_per_base, pixels_per_target=$pixels_per_target\n" if DEBUG; | |
172 my $offset = $self->{flip} ? $end + ($last-1)*$pixels_per_base : $start + $last*$pixels_per_base; | |
173 | |
174 for (my $i=0; $i<@fill_in; $i++) { | |
175 | |
176 my $x = $self->{flip} ? int($offset + ($i+1)*$pixels_per_target + 0.5) | |
177 : int($offset + ($i+1)*$pixels_per_target + 0.5); | |
178 | |
179 $self->filled_box($gd,$x,$y1+3,$x+$fontwidth,$y1+$lineheight-3,$pink,$pink) unless $gaps; | |
180 $gd->char($font,$x,$y1,$complement? $complement{$fill_in[$i]} : $fill_in[$i],$color); | |
181 } | |
182 } | |
183 | |
184 my @genomic = split '',substr($genomic,$seg->[0],$seg->[1]-$seg->[0]+1); | |
185 my @bases = split '',substr($dna, $seg->[2],$seg->[3]-$seg->[2]+1); | |
186 for (my $i = 0; $i<@bases; $i++) { | |
187 my $x = $self->{flip} ? int($end + ($seg->[0] + $i - 1)*$pixels_per_base + 0.5) | |
188 : int($start + ($seg->[0] + $i) *$pixels_per_base + 0.5); | |
189 next if $x+1 < $x1; | |
190 last if $x+1 > $x2; | |
191 if ($genomic[$i] && lc($bases[$i]) ne lc($complement ? $complement{$genomic[@genomic - $i - 1]} : $genomic[$i])) { | |
192 $self->filled_box($gd,$x,$y1+3,$x+$fontwidth,$y1+$lineheight-3,$pink,$pink); | |
193 } | |
194 $gd->char($font,$x,$y1,$complement ? $complement{$bases[$i]} || $bases[$i] : $bases[$i],$color); | |
195 } | |
196 $last = $seg->[1]; | |
197 $tlast = $seg->[3]; | |
198 } | |
199 | |
200 } | |
201 | |
202 # Override _subseq() method to make it appear that a top-level feature that | |
203 # has no subfeatures appears as a feature that has a single subfeature. | |
204 # Otherwise at high mags gaps will be drawn as components rather than | |
205 # as connectors. Because of differing representations of split features | |
206 # in Bio::DB::GFF::Feature and Bio::SeqFeature::Generic, there is | |
207 # some breakage of encapsulation here. | |
208 sub _subseq { | |
209 my $self = shift; | |
210 my $feature = shift; | |
211 my @subseq = $self->SUPER::_subseq($feature); | |
212 return @subseq if @subseq; | |
213 if ($self->level == 0 && !@subseq && !eval{$feature->compound}) { | |
214 my($start,$end) = ($feature->start,$feature->end); | |
215 ($start,$end) = ($end,$start) if $start > $end; # to keep Bio::Location::Simple from bitching | |
216 # return Bio::Location::Simple->new(-start=>$start,-end=>$end); | |
217 return $self->feature; | |
218 } else { | |
219 return; | |
220 } | |
221 } | |
222 | |
223 1; | |
224 | |
225 __END__ | |
226 | |
227 =head1 NAME | |
228 | |
229 Bio::Graphics::Glyph::segments - The "segments" glyph | |
230 | |
231 =head1 SYNOPSIS | |
232 | |
233 See L<Bio::Graphics::Panel> and L<Bio::Graphics::Glyph>. | |
234 | |
235 =head1 DESCRIPTION | |
236 | |
237 This glyph is used for drawing features that consist of discontinuous | |
238 segments. Unlike "graded_segments" or "alignment", the segments are a | |
239 uniform color and not dependent on the score of the segment. | |
240 | |
241 =head2 OPTIONS | |
242 | |
243 The following options are standard among all Glyphs. See | |
244 L<Bio::Graphics::Glyph> for a full explanation. | |
245 | |
246 Option Description Default | |
247 ------ ----------- ------- | |
248 | |
249 -fgcolor Foreground color black | |
250 | |
251 -outlinecolor Synonym for -fgcolor | |
252 | |
253 -bgcolor Background color turquoise | |
254 | |
255 -fillcolor Synonym for -bgcolor | |
256 | |
257 -linewidth Line width 1 | |
258 | |
259 -height Height of glyph 10 | |
260 | |
261 -font Glyph font gdSmallFont | |
262 | |
263 -connector Connector type 0 (false) | |
264 | |
265 -connector_color | |
266 Connector color black | |
267 | |
268 -label Whether to draw a label 0 (false) | |
269 | |
270 -description Whether to draw a description 0 (false) | |
271 | |
272 -strand_arrow Whether to indicate 0 (false) | |
273 strandedness | |
274 | |
275 -draw_dna If true, draw the dna residues 0 (false) | |
276 when magnification level | |
277 allows. | |
278 | |
279 -draw_target If true, draw the dna residues 0 (false) | |
280 of the TARGET sequence when | |
281 magnification level allows. | |
282 SEE NOTE. | |
283 | |
284 -ragged_start When combined with -draw_target, 0 (false) | |
285 draw a few bases beyond the end | |
286 of the alignment. SEE NOTE. | |
287 | |
288 -show_mismatch When combined with -draw_target, 0 (false) | |
289 highlights mismatched bases in | |
290 pink. SEE NOTE. | |
291 | |
292 The -draw_target and -ragged_start options only work with seqfeatures | |
293 that implement the hit() method (Bio::SeqFeature::SimilarityPair). | |
294 The -ragged_start option is mostly useful for looking for polyAs and | |
295 cloning sites at the beginning of ESTs and cDNAs. Currently there is | |
296 no way of activating ragged ends. The length of the ragged starts is | |
297 hard-coded at 25 bp, and the color of mismatches is hard-coded as | |
298 light pink. | |
299 | |
300 =head1 BUGS | |
301 | |
302 Please report them. | |
303 | |
304 =head1 SEE ALSO | |
305 | |
306 | |
307 L<Bio::Graphics::Panel>, | |
308 L<Bio::Graphics::Glyph>, | |
309 L<Bio::Graphics::Glyph::arrow>, | |
310 L<Bio::Graphics::Glyph::cds>, | |
311 L<Bio::Graphics::Glyph::crossbox>, | |
312 L<Bio::Graphics::Glyph::diamond>, | |
313 L<Bio::Graphics::Glyph::dna>, | |
314 L<Bio::Graphics::Glyph::dot>, | |
315 L<Bio::Graphics::Glyph::ellipse>, | |
316 L<Bio::Graphics::Glyph::extending_arrow>, | |
317 L<Bio::Graphics::Glyph::generic>, | |
318 L<Bio::Graphics::Glyph::graded_segments>, | |
319 L<Bio::Graphics::Glyph::heterogeneous_segments>, | |
320 L<Bio::Graphics::Glyph::line>, | |
321 L<Bio::Graphics::Glyph::pinsertion>, | |
322 L<Bio::Graphics::Glyph::primers>, | |
323 L<Bio::Graphics::Glyph::rndrect>, | |
324 L<Bio::Graphics::Glyph::segments>, | |
325 L<Bio::Graphics::Glyph::ruler_arrow>, | |
326 L<Bio::Graphics::Glyph::toomany>, | |
327 L<Bio::Graphics::Glyph::transcript>, | |
328 L<Bio::Graphics::Glyph::transcript2>, | |
329 L<Bio::Graphics::Glyph::translation>, | |
330 L<Bio::Graphics::Glyph::triangle>, | |
331 L<Bio::DB::GFF>, | |
332 L<Bio::SeqI>, | |
333 L<Bio::SeqFeatureI>, | |
334 L<Bio::Das>, | |
335 L<GD> | |
336 | |
337 =head1 AUTHOR | |
338 | |
339 Lincoln Stein E<lt>lstein@cshl.orgE<gt> | |
340 | |
341 Copyright (c) 2001 Cold Spring Harbor Laboratory | |
342 | |
343 This library is free software; you can redistribute it and/or modify | |
344 it under the same terms as Perl itself. See DISCLAIMER.txt for | |
345 disclaimers of warranty. | |
346 | |
347 =cut |