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