File Coverage

blib/lib/Bio/NEXUS/SpanBlock.pm
Criterion Covered Total %
statement 100 184 54.3
branch 9 40 22.5
condition 6 11 54.5
subroutine 20 25 80.0
pod 12 12 100.0
total 147 272 54.0


line stmt bran cond sub pod time code
1             ######################################################
2             # SpanBlock.pm
3             ######################################################
4             # Author: Chengzhi Liang, Thomas Hladish
5             # $Id: SpanBlock.pm,v 1.33 2007/09/21 23:09:09 rvos Exp $
6              
7             #################### START POD DOCUMENTATION ##################
8              
9             =head1 NAME
10              
11             Bio::NEXUS::SpanBlock - Represent SPAN block in a NEXUS file (contains meta data).
12              
13             =head1 SYNOPSIS
14              
15             if ( $type =~ /spanblock/i ) {
16             $block_object = new Bio::NEXUS::SpanBlock($type, $block, $verbose);
17             }
18              
19             =head1 DESCRIPTION
20              
21             This module representing a SPAN block in a NEXUS file for meta data.
22              
23             =head1 FEEDBACK
24              
25             All feedback (bugs, feature enhancements, etc.) are greatly appreciated.
26              
27             =head1 AUTHORS
28              
29             Chengzhi Liang (liangc@umbi.umd.edu)
30             Thomas Hladish (tjhladish at yahoo)
31              
32             =head1 CONTRIBUTORS
33              
34             =head1 METHODS
35              
36             =cut
37              
38             package Bio::NEXUS::SpanBlock;
39              
40 34     34   342 use strict;
  34         73  
  34         1649  
41             #use Data::Dumper; # XXX this is not used, might as well not import it!
42 34     34   197 use Bio::NEXUS::Functions;
  34         66  
  34         9023  
43 34     34   298 use Bio::NEXUS::Block;
  34         76  
  34         1000  
44             #use Carp;# XXX this is not used, might as well not import it!
45 34     34   186 use Bio::NEXUS::Util::Exceptions;
  34         74  
  34         1420  
46 34     34   197 use Bio::NEXUS::Util::Logger;
  34         71  
  34         1098  
47 34     34   196 use vars qw(@ISA $VERSION $AUTOLOAD);
  34         69  
  34         2150  
48 34     34   211 use Bio::NEXUS; $VERSION = $Bio::NEXUS::VERSION;
  34         82  
  34         132047  
49              
50             @ISA = qw(Bio::NEXUS::Block);
51             my $logger = Bio::NEXUS::Util::Logger->new();
52              
53             =head2 new
54              
55             Title : new
56             Usage : block_object = new Bio::NEXUS::SpanBlock($block_type, $commands, $verbose);
57             Function: Creates a new Bio::NEXUS::SpanBlock object
58             Returns : Bio::NEXUS::SpanBlock object
59             Args : type (string), the commands/comments to parse (array ref), and a verbose flag (0 or 1; optional)
60              
61             =cut
62              
63             sub new {
64 1     1 1 3 my ( $class, $type, $commands, $verbose ) = @_;
65 1 50       6 unless ($type) { ( $type = lc $class ) =~ s/Bio::NEXUS::(.+)Block/$1/i; }
  0         0  
66              
67 1         5 my $self = { type => $type, };
68 1         4 bless $self, $class;
69 1 50 33     22 $self->_parse_block( $commands, $verbose )
70             if ( ( defined $commands ) and @$commands );
71 1         4 return $self;
72             }
73              
74             =head2 get_spandex
75              
76             Title : get_spandex
77             Usage : $hash_ref = $span_block->get_spandex(;
78             Function: Gets the SPANDEX command contents as hash_reference
79             Returns : hash reference of the SPANDEX command contents
80             Args : none
81              
82             =cut
83              
84             sub get_spandex {
85 1     1 1 2 my ($self) = @_;
86 1   50     11 return $self->{'spandex'} || {};
87             }
88              
89             =head2 add_spandex
90              
91             Title : add_spandex
92             Usage : $span_block->add_spandex(;
93             Function: Adds the SPANDEX command contents as hash_reference
94             Returns : none
95             Args : hash reference of the SPANDEX command contents
96              
97             =cut
98              
99             sub add_spandex {
100 1     1 1 3 my ( $self, $new_spandex ) = @_;
101 1         2 my %current_spandex = %{ $self->get_spandex() };
  1         4  
102 1         7 $self->{'spandex'} = { %current_spandex, %$new_spandex };
103 1         4 return;
104             }
105              
106             =begin comment
107              
108             Title : _parse_spandex
109             Usage : $block->_parse_spandex($buffer_string);
110             Function: parser that parses the spandex command adds it to the SpanBlock object
111             Returns : none
112             Args : the attributes and the value of the spandex command as array
113              
114             =end comment
115              
116             =cut
117              
118             sub _parse_spandex {
119 1     1   3 my ( $self, $buffer ) = @_;
120 1         6 my ( $key, $val ) = split /\s*=\s*/, $buffer;
121 1         10 $self->add_spandex( { $key, $val } );
122 1         4 return $key, $val;
123             }
124              
125             =begin comment
126              
127             Title : _parse_add
128             Usage : $span_block->_parse_add($content);
129             Function: parse the additional commands (_parse_block parses the standard commands) in the spanblock
130             Returns : hash of command and values
131             Args : a spanblock content as string
132              
133             =end comment
134              
135             =cut
136              
137             sub _parse_add {
138 2     2   6 my ( $self, $content ) = @_;
139 2         5 my %add;
140 2         11 $content =~ s/to\s*=\s*(\S+)//;
141 2         7 my $key = $1;
142 2         16 $content =~ s/attributes\s*=\s*\(([^\)]+)\)//;
143 2         13 my @attributes = split /\s*,\s*/, $1;
144 2         9 $add{$key}{'attributes'} = \@attributes;
145 2         24 $content =~ s/source\s*=\s*(\S+)//;
146 2         9 $add{$key}{'source'} = $1;
147 2         9 $content =~ s/data\s*=\s*//;
148 2         15 my @data = split ',', $content;
149              
150 2         5 for my $values (@data) {
151 21         71 $values =~ s/^\s*(.*?)\s*/$1/;
152 21 50       60 if ( $values =~ s/^\s*("|')([^"]+)("|')// ) {
153 0         0 my $keyvalue = $2;
154 0         0 $keyvalue =~ s/\s+/_/g;
155 0         0 $values = $keyvalue . $values;
156             }
157 21         71 my @values = split /\s+/, $values;
158 21         24 push @{ $add{$key}{'data'} }, \@values;
  21         59  
159             }
160 2         9 $self->add_add( \%add );
161 2         12 return \%add;
162             }
163              
164             =head2 get_add
165              
166             Title : get_add
167             Usage : $hash_ref = $span_block->get_add();
168             Function: gets ADD command content to the span block
169             Returns : hash reference of ADD command's attributes and values
170             Args : none
171              
172             =cut
173              
174             sub get_add {
175 2     2 1 4 my ($self) = @_;
176 2   100     46 return $self->{'add'} || {};
177             }
178              
179             =head2 add_add
180              
181             Title : add_add
182             Usage : $span_block->add_add($hash_ref);
183             Function: Adds ADD command contents to the span block
184             Returns : none
185             Args : hash reference of ADD command's attributes and values
186              
187             =cut
188              
189             sub add_add {
190 2     2 1 4 my ( $self, $new_add ) = @_;
191 2         4 my %current_add = %{ $self->get_add() };
  2         7  
192 2         9 $self->{'add'} = { %current_add, %$new_add };
193 2         5 return;
194             }
195              
196             =begin comment
197              
198             Title : _parse_method
199             Usage : $span_block->_parse_method($content);
200             Function: parse the methods in the spanblock
201             Returns : hash reference of name and values
202             Args : a spanblock content as string
203              
204             =end comment
205              
206             =cut
207              
208             sub _parse_method {
209 5     5   7 my ( $self, $content ) = @_;
210 5         6 my %method;
211 5         16 $content =~ s/^\s*(\S+)//;
212 5         9 my $name = $1;
213 5 100       15 if ( $content =~ /parameters/ ) {
214 1         7 $content =~ s/parameters\s*=\s*\(([^\)]+)\)//gi;
215 1         3 my $parameters = $1;
216 1         4 $method{$name}{'parameters'} = $parameters;
217             }
218              
219 5 100       32 $method{$name} =
220 5         6 { %{ $method{$name} || {} }, %{ $self->_parse_pair($content) } };
  5         9  
221 5         18 $self->add_method( \%method );
222 5         14 return \%method;
223             }
224              
225             =head2 get_method
226              
227             Title : get_method
228             Usage : $hash_ref = $span_block->get_method();
229             Function: gets METHOD command content to the span block
230             Returns : hash reference of METHOD command's attributes and values
231             Args : none
232              
233             =cut
234              
235             sub get_method {
236 5     5 1 4 my ($self) = @_;
237 5   100     28 return $self->{'method'} || {};
238             }
239              
240             =head2 add_method
241              
242             Title : add_method
243             Usage : $span_block->add_method($string);
244             Function: Adds METHOD command content to the span block
245             Returns : none
246             Args : hash reference of METHOD command's attributes and values
247              
248             =cut
249              
250             sub add_method {
251 5     5 1 8 my ( $self, $new_method ) = @_;
252 5         4 my %current_method = %{ $self->get_method() };
  5         9  
253 5         17 $self->{'method'} = { %current_method, %$new_method };
254 5         13 return;
255             }
256              
257             =begin comment
258              
259             Title : _parse_pair
260             Usage : $data_hash = $span_block->_parse_pair($string);
261             Function: parse the pairs in the string to hash reference
262             Returns : hash reference of name and values
263             Args : string as 'a=b c=d'
264              
265             =end comment
266              
267             =cut
268              
269             # This method seems obsolete to me. should use _parse_nexus_words instead (TH, 8/06)
270             sub _parse_pair {
271              
272             # a=b c=d ..
273 5     5   7 my ( $self, $string ) = @_;
274 5         16 $string =~ s/^\s*(.+)/$1/;
275 5         15 $string =~ s/(.*\S)\s*$/$1/;
276 5         14 $string =~ s/=/ /g;
277              
278 5         17 my %hash = split /\s+/, $string;
279 5         26 return \%hash;
280             }
281              
282             =head2 get_attributes
283              
284             Title : get_attributes
285             Usage : $attr_array_ref = $span_block->get_attributes($name);
286             Function: get the attributes of a particular identifier name
287             Returns : array reference of attributes.
288             Args : identifier name
289              
290             =cut
291              
292             sub get_attributes {
293 0     0 1 0 my ( $self, $name ) = @_;
294 0         0 return $self->{'add'}{$name}{'attributes'};
295             }
296              
297             =head2 get_data
298              
299             Title : get_data
300             Usage : $data_array_ref = $span_block->get_data($name);
301             Function: get the data of a particular identifier
302             Returns : array reference of data
303             Args : identifier name
304              
305             =cut
306              
307             sub get_data {
308 1     1 1 7 my ( $self, $name ) = @_;
309 1         4 return $self->{'add'}{$name}{'data'};
310             }
311              
312             =head2 rename_otus
313              
314             Title : rename_otus
315             Usage : $block->rename_otus($names);
316             Function: rename all OTUs
317             Returns : none
318             Args : hash of OTU names
319              
320             =cut
321              
322             sub rename_otus {
323 0     0 1 0 my ( $self, $translation ) = @_;
324 0         0 for my $values ( @{ $self->{'add'}{'taxlabels'}{'data'} } ) {
  0         0  
325 0         0 ${$values}[0] = $$translation{ ${$values}[0] }
  0         0  
  0         0  
326 0 0       0 if $$translation{ ${$values}[0] };
327             }
328             }
329              
330             =head2 add_otu_clone
331              
332             Title : add_otu_clone
333             Usage : ...
334             Function: ...
335             Returns : ...
336             Args : ...
337              
338             =cut
339              
340             sub add_otu_clone {
341 1     1 1 3 my ( $self, $original_otu_name, $copy_otu_name ) = @_;
342             #print "Warning: Bio::NEXUS::SpanBlock::add_otu_clone() method not fully implemented\n";
343            
344 1         3 foreach my $set ( @{ $self->{'add'}{'taxlabels'}{'data'} } ) {
  1         5  
345 20         16 foreach my $item ( @{ $set } ) {
  20         32  
346 58 100       130 if ($item eq $original_otu_name) {
347             #print "found the otu in some set\n";
348 1         4 unshift (@$set, $copy_otu_name);
349 1         3 last;
350             }
351             }
352             }
353             }
354              
355             =head2 equals
356              
357             Name : equals
358             Usage : $span->equals($another);
359             Function: compare if two Bio::NEXUS::SpanBlock objects are equal
360             Returns : boolean
361             Args : a Bio::NEXUS::SpanBlock object
362              
363             =cut
364              
365             sub equals {
366 0     0 1   my ( $self, $block ) = @_;
367              
368 0 0         if ( !Bio::NEXUS::Block::equals( $self, $block ) ) { return 0; }
  0            
369 0           my @keys1 = sort keys %{ $self->{'add'} };
  0            
370 0           my @keys2 = sort keys %{ $block->{'add'} };
  0            
371 0 0         if ( scalar @keys1 != scalar @keys2 ) { return 0; }
  0            
372 0           for ( my $i = 0; $i < @keys1; $i++ ) {
373 0 0         if ( $keys1[$i] ne $keys2[$i] ) {
374 0           return 0;
375             }
376             }
377 0           @keys1 = sort keys %{ $self->{'method'} };
  0            
378 0           @keys2 = sort keys %{ $block->{'method'} };
  0            
379 0 0         if ( scalar @keys1 != scalar @keys2 ) { return 0; }
  0            
380 0           for ( my $i = 0; $i < @keys1; $i++ ) {
381 0 0         if ( $keys1[$i] ne $keys2[$i] ) {
382 0           return 0;
383             }
384             }
385              
386 0           return 1;
387             }
388              
389             =begin comment
390              
391             Name : _write
392             Usage : $block->_write($filename);
393             Function: Writes NEXUS block from stored data
394             Returns : none
395             Args : none
396              
397             =end comment
398              
399             =cut
400              
401             sub _write {
402 0     0     my ( $self, $fh, $verbose ) = @_;
403 0   0       $fh ||= \*STDOUT;
404              
405 0           Bio::NEXUS::Block::_write( $self, $fh );
406              
407 0 0         for my $key ( keys %{ $self->{'spandex'} || {} } ) {
  0            
408 0           print $fh "\tSPANDEX $key=", $key = $self->{'spandex'}{$key}, ";\n";
409             }
410              
411 0 0         for my $key ( keys %{ $self->{'add'} || {} } ) {
  0            
412 0           print $fh "\tADD to=", $key;
413 0           print $fh " attributes=(";
414 0           print $fh ( join ',', @{ $self->{'add'}{$key}{'attributes'} } );
  0            
415 0           print $fh ')';
416 0           print $fh " source=", $self->{'add'}{$key}{'source'};
417 0           print $fh " data=\n";
418 0           for my $values ( @{ $self->{'add'}{$key}{'data'} } ) {
  0            
419 0           print $fh "\t";
420 0           for my $value (@$values) {
421 0           print $fh "\t", _nexus_formatted($value);
422             }
423 0           print $fh ",\n";
424             }
425 0           print $fh "\t\t;\n";
426             }
427 0           for my $key ( keys %{ $self->{'method'} } ) {
  0            
428 0           print $fh "\tMETHOD $key";
429 0           print $fh " program=", $self->{'method'}{$key}{'program'};
430              
431 0           for my $key1 ( keys %{ $self->{'method'}{$key} } ) {
  0            
432 0 0         if ( !$self->{'method'}{$key}{$key1} ) { next; }
  0            
433 0 0         if ( $key1 =~ /program/i ) { next; }
  0            
434 0 0         if ( $key1 =~ /parameters/i ) {
435 0           print $fh " $key1=(", $self->{'method'}{$key}{$key1}, ')';
436             }
437             else {
438 0           print $fh " $key1=", $self->{'method'}{$key}{$key1};
439             }
440             }
441 0           print $fh ";\n";
442             }
443 0 0         for my $comm ( @{ $self->{'unknown'} || [] } ) {
  0            
444 0           print $fh "\t$comm;\n";
445             }
446              
447 0           print $fh "END;\n";
448             }
449              
450             sub AUTOLOAD {
451 0 0   0     return if $AUTOLOAD =~ /DESTROY$/;
452 0           my $package_name = __PACKAGE__ . '::';
453              
454             # The following methods are deprecated and are temporarily supported
455             # via a warning and a redirection
456 0           my %synonym_for = (
457              
458             # "${package_name}parse" => "${package_name}_parse_tree", # example
459             );
460              
461 0 0         if ( defined $synonym_for{$AUTOLOAD} ) {
462 0           $logger->warn("$AUTOLOAD() is deprecated; use $synonym_for{$AUTOLOAD}() instead");
463 0           goto &{ $synonym_for{$AUTOLOAD} };
  0            
464             }
465             else {
466 0           Bio::NEXUS::Util::Exceptions::UnknownMethod->throw(
467             'error' => "ERROR: Unknown method $AUTOLOAD called"
468             );
469             }
470 0           return;
471             }
472              
473             1;