File Coverage

lib/Bio/Graphics/Glyph/Factory.pm
Criterion Covered Total %
statement 12 110 10.9
branch 0 48 0.0
condition 0 27 0.0
subroutine 4 23 17.3
pod 17 19 89.4
total 33 227 14.5


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Bio::Graphics::Glyph::Factory - Factory for Bio::Graphics::Glyph objects
4              
5             =head1 SYNOPSIS
6              
7             See L<Bio::Graphics::Panel>.
8              
9             =head1 DESCRIPTION
10              
11             This class is used internally by Bio::Graphics to generate new Glyph
12             objects by combining a list of features with the user's desired
13             configuration. It is intended to be used internally by Bio::Graphics.
14              
15             =head1 FEEDBACK
16              
17             =head2 Mailing Lists
18              
19             User feedback is an integral part of the evolution of this and other
20             Bioperl modules. Send your comments and suggestions preferably to one
21             of the Bioperl mailing lists. Your participation is much appreciated.
22              
23             bioperl-l@bioperl.org - General discussion
24             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
25              
26             =head2 Reporting Bugs
27              
28             Report bugs to the Bioperl bug tracking system to help us keep track
29             the bugs and their resolution. Bug reports can be submitted via the
30             web:
31              
32             http://bugzilla.open-bio.org/
33              
34             =head1 AUTHOR - Lincoln Stein
35              
36             Email - lstein@cshl.org
37              
38             =head1 SEE ALSO
39              
40             L<Bio::Graphics::Panel>
41              
42             =head1 APPENDIX
43              
44             The rest of the documentation details each of the object
45             methods. Internal methods are usually preceded with an "_"
46             (underscore).
47              
48             =cut
49              
50             package Bio::Graphics::Glyph::Factory;
51              
52 1     1   6 use strict;
  1         2  
  1         37  
53 1     1   5 use Carp qw(:DEFAULT cluck);
  1         2  
  1         211  
54 1     1   7 use Bio::Root::Version;
  1         2  
  1         9  
55 1     1   80 use base qw(Bio::Root::Root);
  1         1  
  1         1426  
56             #use Memoize 'memoize';
57             #memoize('option');
58              
59             my %LOADED_GLYPHS = ();
60             my %GENERIC_OPTIONS = (
61             bgcolor => 'turquoise',
62             fgcolor => 'black',
63             fontcolor => 'black',
64             font2color => 'blue',
65             height => 8,
66             font => 'gdSmallFont', # This must be a string not method call
67             bump => +1, # bump by default (perhaps a mistake?)
68             );
69              
70             =head2 new
71              
72             Title : new
73             Usage : $f = Bio::Graphics::Glyph::Factory->new(
74             -stylesheet => $stylesheet,
75             -glyph_map => $glyph_map,
76             -options => $options);
77             Function : create a new Bio::Graphics::Glyph::Factory object
78             Returns : the new object
79             Args : $stylesheet is a Bio::Das::Stylesheet object that can
80             convert Bio::Das feature objects into glyph names and
81             associated options.
82             $glyph_map is a hash that maps primary tags to glyph names.
83             $options is a hash that maps option names to their values.
84             Status : Internal to Bio::Graphics
85              
86             =cut
87              
88             sub new {
89 0     0 1   my $class = shift;
90 0           my $panel = shift;
91 0           my %args = @_;
92 0           my $stylesheet = $args{-stylesheet}; # optional, for Bio::Das compatibility
93 0           my $map = $args{-map}; # map type name to glyph name
94 0           my $options = $args{-options}; # map type name to glyph options
95 0           return bless {
96             stylesheet => $stylesheet,
97             glyph_map => $map,
98             options => $options,
99             panel => $panel,
100             },$class;
101             }
102              
103             =head2 clone
104              
105             Title : clone
106             Usage : $f2 = $f->clone
107             Function : Deep copy of a factory object
108             Returns : a deep copy of the factory object
109             Args : None
110             Status : Internal to Bio::Graphics
111              
112             =cut
113              
114             sub clone {
115 0     0 1   my $self = shift;
116 0           my %new = %$self;
117 0           my $new = bless \%new,ref($self);
118 0           $new;
119             }
120              
121             =head2 stylesheet
122              
123             Title : stylesheet
124             Usage : $stylesheet = $f->stylesheet
125             Function : accessor for stylesheet
126             Returns : a Bio::Das::Stylesheet object
127             Args : None
128             Status : Internal to Bio::Graphics
129              
130             =cut
131              
132             sub stylesheet {
133 0     0 1   my $self = shift;
134 0           my $d = $self->{stylesheet};
135 0 0         $self->{stylesheet} = shift if @_;
136 0           $d;
137             }
138              
139             =head2 glyph_map
140              
141             Title : glyph_map
142             Usage : $map = $f->glyph_map
143             Function : accessor for the glyph map
144             Returns : a hash mapping primary tags to glyphs
145             Args : None
146             Status : Internal to Bio::Graphics
147              
148             =cut
149              
150 0     0 1   sub glyph_map { shift->{glyph_map} }
151              
152             =head2 option_map
153              
154             Title : option_map
155             Usage : $map = $f->option_map
156             Function : accessor for the option map
157             Returns : a hash mapping option names to values
158             Args : None
159             Status : Internal to Bio::Graphics
160              
161             =cut
162              
163 0     0 1   sub option_map { shift->{options} }
164              
165             =head2 global_opts
166              
167             Title : global_opts
168             Usage : $map = $f->global_opts
169             Function : accessor for global options
170             Returns : a hash mapping option names to values
171             Args : None
172             Status : Internal to Bio::Graphics
173              
174             This returns a set of defaults for option values.
175              
176             =cut
177              
178 0     0 1   sub global_opts{ shift->{global_opts} }
179              
180             =head2 panel
181              
182             Title : panel
183             Usage : $panel = $f->panel
184             Function : accessor for Bio::Graphics::Panel
185             Returns : a Bio::Graphics::Panel
186             Args : None
187             Status : Internal to Bio::Graphics
188              
189             This returns the panel with which the factory is associated.
190              
191             =cut
192              
193 0     0 1   sub panel { shift->{panel} }
194              
195             =head2 scale
196              
197             Title : scale
198             Usage : $scale = $f->scale
199             Function : accessor for the scale
200             Returns : a floating point number
201             Args : None
202             Status : Internal to Bio::Graphics
203              
204             This returns the scale, in pixels/bp for glyphs constructed by this
205             factory.
206              
207             =cut
208              
209 0     0 1   sub scale { shift->{panel}->scale }
210              
211             =head2 font
212              
213             Title : font
214             Usage : $font = $f->font
215             Function : accessor for the font
216             Returns : a font name
217             Args : None
218             Status : Internal to Bio::Graphics
219              
220             This returns a GD font name.
221              
222             =cut
223              
224             sub font {
225 0     0 1   my $self = shift;
226 0           my $glyph = shift;
227 0 0         $self->option($glyph,'font') || $self->{font};
228             }
229              
230             =head2 map_pt
231              
232             Title : map_pt
233             Usage : @pixel_positions = $f->map_pt(@bp_positions)
234             Function : map bp positions to pixel positions
235             Returns : a list of pixel positions
236             Args : a list of bp positions
237             Status : Internal to Bio::Graphics
238              
239             The real work is done by the panel, but factory subclasses can
240             override if desired.
241              
242             =cut
243              
244             sub map_pt {
245 0     0 1   my $self = shift;
246 0           my @result = $self->panel->map_pt(@_);
247 0 0         return wantarray ? @result : $result[0];
248             }
249              
250             =head2 map_no_trunc
251              
252             Title : map_no_trunc
253             Usage : @pixel_positions = $f->map_no_trunc(@bp_positions)
254             Function : map bp positions to pixel positions
255             Returns : a list of pixel positions
256             Args : a list of bp positions
257             Status : Internal to Bio::Graphics
258              
259             Same as map_pt(), but it will NOT clip pixel positions to be within
260             the drawing frame.
261              
262             =cut
263              
264             sub map_no_trunc {
265 0     0 1   my $self = shift;
266 0           my @result = $self->panel->map_no_trunc(@_);
267 0 0         return wantarray ? @result : $result[0];
268             }
269              
270             =head2 translate_color
271              
272             Title : translate_color
273             Usage : $index = $f->translate_color($color_name)
274             Function : translate symbolic color names into GD indexes
275             Returns : an integer
276             Args : a color name in format "green" or "#00FF00"
277             Status : Internal to Bio::Graphics
278              
279             The real work is done by the panel, but factory subclasses can
280             override if desired.
281              
282             =cut
283              
284             sub translate_color {
285 0     0 1   my $self = shift;
286 0           my $color_name = shift;
287 0           $self->panel->translate_color($color_name);
288             }
289              
290             =head2 transparent_color
291              
292             Title : transparent_color
293             Usage : $index = $f->transparent_color($opacity,$color_name)
294             Function : translate symbolic color names into GD indexes, with
295             an opacity value taken into account
296             Returns : an integer
297             Args : an opacity value from 0-1.0, plus a color name in format "green" or "#00FF00"
298             Status : Internal to Bio::Graphics
299              
300             The real work is done by the panel, but factory subclasses can
301             override if desired.
302              
303             =cut
304              
305             sub transparent_color {
306 0     0 1   my $self = shift;
307 0           $self->panel->transparent_color(@_);
308             }
309              
310             =head2 make_glyph
311              
312             Title : make_glyph
313             Usage : @glyphs = $f->glyph($level,[$type,]$feature1,$feature2...)
314             Function : transform features into glyphs.
315             Returns : a list of Bio::Graphics::Glyph objects
316             Args : a feature "level", followed by a list of FeatureI objects.
317             Status : Internal to Bio::Graphics
318              
319             The level is used to track the level of nesting of features that have
320             subfeatures. The option $type argument can be used to force the glyph type
321              
322             =cut
323              
324             # create a glyph
325             sub make_glyph {
326 0     0 1   my $self = shift;
327 0           my $level = shift;
328 0 0         my $forced_type = shift unless ref($_[0]);
329              
330 0           my @result;
331 0           my $panel = $self->panel;
332 0           my $flip = $panel->flip;
333              
334 0           for my $f (@_) {
335 0   0       my $type = $forced_type || $self->feature_to_glyph($f);
336              
337 0           my $glyphclass = 'Bio::Graphics::Glyph';
338 0   0       $type ||= 'generic';
339 0           $glyphclass .= "\:\:\L$type";
340              
341 0 0         unless ($LOADED_GLYPHS{$glyphclass}++) {
342 0 0         $self->throw("The requested glyph class, ``$type'' is not available: $@")
343             unless (eval "require $glyphclass");
344             }
345              
346 0           my $glyph = $glyphclass->new(-feature => $f,
347             -factory => $self,
348             -flip => $flip,
349             -level => $level);
350              
351 0           push @result,$glyph;
352              
353             }
354 0 0         return wantarray ? @result : $result[0];
355             }
356              
357              
358             =head2 feature_to_glyph
359              
360             Title : feature_to_glyph
361             Usage : $glyph_name = $f->feature_to_glyph($feature)
362             Function : choose the glyph name given a feature
363             Returns : a glyph name
364             Args : a Bio::Seq::FeatureI object
365             Status : Internal to Bio::Graphics
366              
367             =cut
368              
369             sub feature_to_glyph {
370 0     0 1   my $self = shift;
371 0           my $feature = shift;
372              
373 0           my $val;
374              
375 0 0 0       if ($self->{stylesheet} && $feature->type !~ /track|group/) {
376 0           $val = scalar $self->{stylesheet}->glyph($feature);
377 0   0       return $val || 'generic';
378             }
379              
380 0           my $map = $self->glyph_map;
381 0 0         if ($map) {
382 0 0         if (ref($map) eq 'CODE') {
383 0           $val = eval {$map->($feature)};
  0            
384 0 0         warn $@ if $@;
385             }
386             else {
387 0           $val = $map->{$feature->primary_tag};
388             }
389             }
390              
391 0   0       return $val || 'generic';
392             }
393              
394              
395             =head2 set_option
396              
397             Title : set_option
398             Usage : $f->set_option($option_name=>$option_value)
399             Function : set or change an option
400             Returns : nothing
401             Args : a name/value pair
402             Status : Internal to Bio::Graphics
403              
404             =cut
405              
406             sub set_option {
407 0     0 1   my $self = shift;
408 0           my ($option_name,$option_value) = @_;
409 0           $self->{overriding_options}{lc $option_name} = $option_value;
410             }
411              
412             # options:
413             # the overriding_options hash has precedence
414             # ...followed by the option_map
415             # ...followed by the stylesheet
416             # ...followed by generic options
417             sub option {
418 0     0 0   my $self = shift;
419 0           my ($glyph,$option_name,$partno,$total_parts) = @_;
420 0 0         return unless defined $option_name;
421 0           $option_name = lc $option_name; # canonicalize
422              
423 0 0 0       return $self->{overriding_options}{$option_name}
424             if exists $self->{overriding_options} && exists $self->{overriding_options}{$option_name};
425              
426 0 0 0       if (exists $self->{stylesheet} && (my $ss = $self->{stylesheet})) {
427 0           my(undef,%options) = $ss->glyph($glyph->feature);
428 0           my $value = $options{$option_name};
429 0 0         if (defined $value) { # some cleanup on DAS glyphs
430 0           $value =~ s/yes/1/i;
431 0           $value =~ s/no/0/i;
432             }
433 0 0         return $value if defined $value;
434             }
435              
436 0 0 0       if (exists $self->{options} && (my $map = $self->{options})) {
437 0 0 0       if (exists $map->{$option_name} && defined(my $value = $map->{$option_name})) {
438 0           my $feature = $glyph->feature;
439              
440 0 0         return $value unless ref $value eq 'CODE';
441 0           my $val = eval { $value->($feature,$option_name,$partno,$total_parts,$glyph)};
  0            
442 0 0         warn "Error returned while evaluating value of '$option_name' option for glyph $glyph, feature $feature: ",$@,"\n"
443             if $@;
444 0 0 0       return defined $val && $val eq '*default*' ? $GENERIC_OPTIONS{$option_name} : $val;
445             }
446             }
447              
448 0           return $GENERIC_OPTIONS{$option_name};
449             }
450              
451             sub get_option {
452 0     0 0   my $self = shift;
453 0           my $option_name = shift;
454 0 0         my $map = $self->{options} or return;
455 0           $map->{$option_name};
456             }
457              
458              
459             =head2 options
460              
461             Title : options
462             Usage : @option_names = $f->options
463             Function : return all configured option names
464             Returns : a list of option names
465             Args : none
466             Status : Internal to Bio::Graphics
467              
468             =cut
469              
470             # return names of all the options in the option hashes
471             sub options {
472 0     0 1   my $self = shift;
473 0           my %options;
474 0 0         if (my $map = $self->option_map) {
475 0           $options{lc($_)}++ foreach keys %$map;
476             }
477 0           $options{lc($_)}++ foreach keys %GENERIC_OPTIONS;
478 0           return keys %options;
479             }
480              
481             1;