~ubuntu-branches/ubuntu/trusty/bioperl/trusty

« back to all changes in this revision

Viewing changes to Bio/Tree/TreeFunctionsI.pm

  • Committer: Package Import Robot
  • Author(s): Charles Plessy
  • Date: 2013-09-22 13:39:48 UTC
  • mfrom: (3.1.11 sid)
  • Revision ID: package-import@ubuntu.com-20130922133948-c6z62zegjyp7ztou
Tags: 1.6.922-1
* New upstream release.
* Replaces and Breaks grinder (<< 0.5.3-3~) because of overlaping contents.
  Closes: #722910
* Stop Replacing and Breaking bioperl ( << 1.6.9 ): not needed anymore. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
# POD documentation - main docs before the code
13
13
 
 
14
 
14
15
=head1 NAME
15
16
 
16
17
Bio::Tree::TreeFunctionsI - Decorated Interface implementing basic Tree exploration methods
87
88
 
88
89
# Let the code begin...
89
90
 
 
91
 
90
92
package Bio::Tree::TreeFunctionsI;
 
93
 
91
94
use strict;
92
 
 
93
95
use base qw(Bio::Tree::TreeI);
94
96
 
 
97
 
95
98
=head2 find_node
96
99
 
97
100
 Title   : find_node
106
109
=cut
107
110
 
108
111
sub find_node {
109
 
   my ($self,$type,$field) = @_;
 
112
   my ($self, $type, $field) = @_;
110
113
   if( ! defined $type ) { 
111
114
       $self->warn("Must request a either a string or field and string when searching");
112
115
   }
119
122
 
120
123
   if( ! defined $field ) { 
121
124
       # only 1 argument, default to searching by id
122
 
       $field= $type; 
123
 
       $type = 'id';
 
125
       $field = $type; 
 
126
       $type  = 'id';
124
127
   } else {   
125
128
       $type =~ s/^-//;
126
129
   }
131
134
   # leaf nodes.  Can't handle NHX tags right now
132
135
 
133
136
   my @nodes = grep { $_->can($type) && defined $_->$type() &&
134
 
                     $_->$type() eq $field } $self->get_nodes();
 
137
                      $_->$type() eq $field } $self->get_nodes();
135
138
 
136
139
   if ( wantarray) { 
137
140
       return @nodes;
138
141
   } else { 
139
142
       if( @nodes > 1 ) { 
140
 
           $self->warn("More than 1 node found but caller requested scalar, only returning first node");
 
143
           $self->warn("More than 1 node found but caller requested scalar, only returning first node");
141
144
       }
142
145
       return shift @nodes;
143
146
   }
144
147
}
145
148
 
 
149
 
146
150
=head2 remove_Node
147
151
 
148
152
 Title   : remove_Node
172
176
   }
173
177
}
174
178
 
 
179
 
175
180
=head2 get_lineage_nodes
176
181
 
177
182
 Title   : get_lineage_nodes
178
183
 Usage   : my @nodes = $tree->get_lineage_nodes($node);
179
 
 Function: Get the full lineage of a node (all its ancestors, in the order
180
 
           root->most recent ancestor)
 
184
 Function: Given a node or its ID, get its full lineage, i.e. all its ancestors,
 
185
           from the root to the most recent ancestor. Only use the node ID as
 
186
           input if the nodes have been added to the tree.
181
187
 Returns : list of nodes
182
 
 Args    : either Bio::Tree::NodeI or string of the node id
 
188
 Args    : either Bio::Tree::NodeI (or string of the node id)
183
189
 
184
190
=cut
185
191
 
186
192
sub get_lineage_nodes {
187
193
    my ($self, $input) = @_;
188
194
    my $node;
189
 
    unless (ref $input) {
 
195
 
 
196
    # Sanity checks
 
197
    if (ref $input) {
 
198
        if (not $input->isa('Bio::Tree::NodeI')) {
 
199
            $self->throw("Did not provide a valid Bio::Tree::NodeI object or ID string to get_lineage_nodes");
 
200
        }
 
201
        $node = $input;
 
202
    } else {
190
203
        $node = $self->find_node($input);
191
204
    }
192
 
    elsif (! $input->isa('Bio::Tree::NodeI')) {
193
 
        $self->warn("Did not provide either a valid Bio::Tree::NodeI object or id to get_lineage_nodes");
194
 
        return;
195
 
    }
196
 
    else { 
197
 
        $node = $input;
198
 
    }
199
205
 
200
 
    # when dealing with Bio::Taxon objects with databases, the root will always
 
206
    # When dealing with Bio::Taxon objects with databases, the root will always
201
207
    # be the database's root, ignoring this Tree's set root node; prefer the
202
208
    # Tree's idea of root.
203
209
    my $root = $self->get_root_node || '';
211
217
    return @lineage;
212
218
}
213
219
 
 
220
 
 
221
=head2 get_lineage_string
 
222
 
 
223
 Title   : get_lineage_string
 
224
 Usage   : my $lineage = $tree->get_lineage_string($node);
 
225
 Function: Get the string representation of the full lineage of a node, e.g.
 
226
           for the Enterobacteriales node, return
 
227
           Bacteria;Proteobacteria;Gammaproteobacteria;Enterobacteriales.
 
228
           This method uses get_lineage_nodes internally and therefore inherits
 
229
           of all of its caveats.
 
230
 Returns : string
 
231
 Args    : * either Bio::Tree::NodeI (or string of the node id)
 
232
           * an optional separator (default: ';')
 
233
 
 
234
=cut
 
235
 
 
236
sub get_lineage_string {
 
237
    my ($self, $input, $sep) = @_;
 
238
    $sep ||= ';';
 
239
    my $node;
 
240
    unless (ref $input) {
 
241
        $node = $self->find_node($input);
 
242
    }
 
243
    elsif (! $input->isa('Bio::Tree::NodeI')) {
 
244
        $self->warn("Did not provide either a valid Bio::Tree::NodeI object or id to get_lineage_nodes");
 
245
        return;
 
246
    }
 
247
    else {
 
248
        $node = $input;
 
249
    }
 
250
    my @nodes = ($self->get_lineage_nodes($node), $node);
 
251
    for my $i (0 .. scalar @nodes - 1) {
 
252
        my $node_name = $nodes[$i]->node_name || '';
 
253
        if ($node_name =~ m/$sep/) {
 
254
           $self->warn("Separator '$sep' is not safe to use because the node ".
 
255
               "called '$node_name' contains it. Consider using another separator".
 
256
               " or sanitizing the node name.");
 
257
        }
 
258
        $nodes[$i] = $node_name;
 
259
    }
 
260
    return join $sep, @nodes;
 
261
}
 
262
 
 
263
 
214
264
=head2 splice
215
265
 
216
266
 Title   : splice
272
322
                    push(@keep_nodes, $self->find_node($key => $value));
273
323
                }
274
324
            }
275
 
            elsif ($key =~ /preserve/) {
276
 
                $preserve_lengths = $value;
277
 
            }
 
325
            elsif ($key =~ /preserve/) {
 
326
                $preserve_lengths = $value;
 
327
            }
278
328
        }
279
329
 
280
330
        if ($remove_all) {
323
373
        # no ancestor of our own to remove us from the tree
324
374
        foreach my $desc (@descs) {
325
375
            $desc->ancestor($ancestor);
326
 
            $desc->branch_length($desc->branch_length + $node->branch_length) if $preserve_lengths;
 
376
            $desc->branch_length($desc->branch_length + $node->branch_length) if $preserve_lengths;
327
377
        }
328
378
        $node->ancestor(undef);
329
379
    }
335
385
    }
336
386
}
337
387
 
 
388
 
338
389
=head2 get_lca
339
390
 
340
391
 Title   : get_lca
369
420
    # be identical.
370
421
    my @paths;
371
422
    foreach my $node (@nodes) {
372
 
        unless(ref($node) && $node->isa('Bio::Tree::NodeI')) {
373
 
            $self->throw("Cannot process get_lca() with a non-NodeI object ($node)\n");
374
 
        }
 
423
        unless(ref($node) && $node->isa('Bio::Tree::NodeI')) {
 
424
            $self->throw("Cannot process get_lca() with a non-NodeI object ($node)\n");
 
425
        }
375
426
        my @path = ($self->get_lineage_nodes($node), $node);
376
427
        push(@paths, \@path);
377
428
    }
408
459
    return $lca;
409
460
}
410
461
 
 
462
 
411
463
=head2 merge_lineage
412
464
 
413
465
 Title   : merge_lineage
414
466
 Usage   : merge_lineage($node)
415
467
 Function: Merge a lineage of nodes with this tree.
416
 
 Returns : n/a
 
468
 Returns : true for success, false (and a warning) otherwise
417
469
 Args    : Bio::Tree::TreeI with only one leaf, OR
418
470
           Bio::Tree::NodeI which has an ancestor
419
471
 
443
495
    my ($self, $thing) = @_;
444
496
    $self->throw("Must supply an object reference") unless ref($thing);
445
497
 
446
 
    my ($lineage_tree, $lineage_leaf);
 
498
    my $lineage_leaf;
447
499
    if ($thing->isa('Bio::Tree::TreeI')) {
448
500
        my @leaves = $thing->get_leaf_nodes;
449
501
        $self->throw("The supplied Tree can only have one leaf") unless @leaves == 1;
450
 
        $lineage_tree = $thing;
451
502
        $lineage_leaf = shift(@leaves);
452
503
    }
453
504
    elsif ($thing->isa('Bio::Tree::NodeI')) {
454
505
        $self->throw("The supplied Node must have an ancestor") unless $thing->ancestor;
455
 
        $lineage_tree = $self->new(-node => $thing);
456
506
        $lineage_leaf = $thing;
457
507
    }
458
508
 
459
 
    # see if any node in the supplied lineage is in our tree - that will be
460
 
    # our lca and we can merge at the node below
 
509
    # Find the lowest node in the supplied lineage that is in the tree
 
510
    # That will be our lca and we can merge at the node below
461
511
    my @lineage = ($lineage_leaf, reverse($self->get_lineage_nodes($lineage_leaf)));
462
512
    my $merged = 0;
463
 
    for my $i (0..$#lineage) {
464
 
        my $lca = $self->find_node(-internal_id => $lineage[$i]->internal_id) || next;
465
 
 
466
 
        if ($i == 0) {
467
 
            # the supplied thing to merge is already in the tree, nothing to do
468
 
            return;
 
513
    my $node;
 
514
    my $i = 0;
 
515
    while ($i <= $#lineage) {
 
516
        $node = $self->find_node(-internal_id => $lineage[$i]->internal_id);
 
517
        if (defined $node) {
 
518
            $merged = 1;
 
519
            last;
469
520
        }
470
 
        # $i is the lca, so the previous node is new to the tree and should
471
 
        # be merged on
472
 
        $lca->add_Descendent($lineage[$i-1]);
473
 
        $merged = 1;
474
 
        last;
475
 
    }
476
 
    $merged || ($self->warn("Couldn't merge the lineage of ".$lineage_leaf->id." with the rest of the tree!\n") && return);
 
521
        $i++;
 
522
    }
 
523
    if (not $merged) {
 
524
        $self->warn("Could not merge the lineage of ".$lineage_leaf->id." with the rest of the tree");
 
525
    }
 
526
 
 
527
    # Merge descendents, recursively
 
528
    while ($i > 0) {
 
529
        $node->add_Descendent($lineage[$i-1]);
 
530
        $node = $self->find_node(-internal_id => $lineage[$i-1]->internal_id);
 
531
        $i--;
 
532
    }
 
533
 
 
534
    return $merged;
477
535
}
478
536
 
 
537
 
479
538
=head2 contract_linear_paths
480
539
 
481
540
 Title   : contract_linear_paths
533
592
    }
534
593
}
535
594
 
 
595
 
536
596
=head2 is_binary
537
597
 
538
598
  Example    : is_binary(); is_binary($node);
546
606
 
547
607
=cut
548
608
 
549
 
sub is_binary;
550
 
 
551
609
sub is_binary {
552
610
    my $self = shift;
553
611
    my $node = shift || $self->get_root_node;
677
735
    }
678
736
}
679
737
 
 
738
 
680
739
=head2 simplify_to_leaves_string
681
740
 
682
741
 Title   : simplify_to_leaves_string
714
773
    return join(',', @data);
715
774
}
716
775
 
 
776
 
717
777
# alias
718
778
sub _clone { shift->clone(@_) }
719
779
 
 
780
 
720
781
# safe node clone that doesn't seg fault, but deliberately loses ancestors and
721
782
# descendents
722
783
sub _clone_node {
733
794
    return $clone;
734
795
}
735
796
 
 
797
 
736
798
# tree string generator for simplify_to_leaves_string, based on
737
799
# Bio::TreeIO::newick::_write_tree_Helper
738
800
sub _simplify_helper {
759
821
    return @data;
760
822
}
761
823
 
 
824
 
762
825
=head2 distance
763
826
 
764
827
 Title   : distance
774
837
    my ($self,@args) = @_;
775
838
    my ($nodes) = $self->_rearrange([qw(NODES)],@args);
776
839
    if( ! defined $nodes ) {
777
 
        $self->warn("Must supply two nodes or -nodes parameter to distance() method");
778
 
        return;
 
840
        $self->warn("Must supply two nodes or -nodes parameter to distance() method");
 
841
        return;
779
842
    }
780
843
    elsif (ref($nodes) eq 'ARRAY') {
781
 
        1;
 
844
        1;
782
845
    }
783
846
    elsif ( @args == 2) { # assume these are nodes...
784
 
            $nodes = \@args;
 
847
            $nodes = \@args;
785
848
    }
786
849
    else {
787
 
        $self->warn("Must supply two nodes or -nodes parameter to distance() method");
788
 
        return;
 
850
        $self->warn("Must supply two nodes or -nodes parameter to distance() method");
 
851
        return;
789
852
    }
790
853
    $self->throw("Must provide 2 nodes") unless @{$nodes} == 2;
791
854
 
815
878
    return $cumul_dist;
816
879
}
817
880
 
 
881
 
818
882
=head2 is_monophyletic
819
883
 
820
884
 Title   : is_monophyletic
821
885
 Usage   : if( $tree->is_monophyletic(-nodes => \@nodes, 
822
 
                                      -outgroup => $outgroup)
 
886
                                      -outgroup => $outgroup)
823
887
 Function: Will do a test of monophyly for the nodes specified
824
888
           in comparison to a chosen outgroup
825
889
 Returns : boolean
826
890
 Args    : -nodes    => arrayref of nodes to test
827
891
           -outgroup => outgroup to serve as a reference
828
892
 
829
 
 
830
893
=cut
831
894
 
832
895
sub is_monophyletic{
859
922
   return 1;
860
923
}
861
924
 
 
925
 
862
926
=head2 is_paraphyletic
863
927
 
864
928
 Title   : is_paraphyletic
865
929
 Usage   : if( $tree->is_paraphyletic(-nodes =>\@nodes,
866
 
                                      -outgroup => $node) ){ }
 
930
                                      -outgroup => $node) ){ }
867
931
 Function: Tests whether or not a given set of nodes are paraphyletic
868
932
           (representing the full clade) given an outgroup
869
933
 Returns : [-1,0,1] , -1 if the group is not monophyletic
914
978
       $og_ancestor = $og_ancestor->ancestor;
915
979
   }
916
980
   my $tree = Bio::Tree::Tree->new(-root     => $clade_root,
917
 
                                  -nodelete => 1);
 
981
                                   -nodelete => 1);
918
982
 
919
983
   foreach my $n ( $tree->get_nodes() ) { 
920
984
       next unless $n->is_Leaf();
944
1008
        return 0;
945
1009
    }
946
1010
 
947
 
        my $old_root = $self->get_root_node;
948
 
        if( $new_root == $old_root ) {
949
 
            $self->warn("Node requested for reroot is already the root node!");
950
 
            return 0;
951
 
        }
952
 
        my $anc = $new_root->ancestor;
953
 
        unless( $anc ) {
954
 
            # this is already the root
955
 
            $self->warn("Node requested for reroot is already the root node!");            return 0;
956
 
        }
957
 
        my $tmp_node = $new_root->create_node_on_branch(-position=>0,-force=>1);
 
1011
    my $old_root = $self->get_root_node;
 
1012
    if( $new_root == $old_root ) {
 
1013
        $self->warn("Node requested for reroot is already the root node!");
 
1014
        return 0;
 
1015
    }
 
1016
    my $anc = $new_root->ancestor;
 
1017
    unless( $anc ) {
 
1018
        # this is already the root
 
1019
        $self->warn("Node requested for reroot is already the root node!");
 
1020
        return 0;
 
1021
    }
 
1022
    my $tmp_node = $new_root->create_node_on_branch(-position=>0,-force=>1);
958
1023
    # reverse the ancestor & children pointers
959
1024
    my $former_anc = $tmp_node->ancestor;
960
1025
    my @path_from_oldroot = ($self->get_lineage_nodes($tmp_node), $tmp_node);
964
1029
        $current->remove_Descendent($next);
965
1030
        $current->branch_length($next->branch_length);
966
1031
        $current->bootstrap($next->bootstrap) if defined $next->bootstrap;
967
 
        $next->remove_tag('B');
 
1032
        $next->remove_tag('B');
968
1033
        $next->add_Descendent($current);
969
1034
    }
970
1035
 
980
1045
    return 1;
981
1046
}
982
1047
 
 
1048
 
983
1049
=head2 reroot_at_midpoint
984
1050
 
985
1051
 Title   : reroot_at_midpoint
1004
1070
 
1005
1071
    my $midpt = $node->create_node_on_branch(-FRACTION=>0.5);
1006
1072
    if (defined $id) {
1007
 
        $self->warn("ID argument is not a scalar") if (ref $id);
1008
 
        $midpt->id($id) if defined($id) && !ref($id);
 
1073
        $self->warn("ID argument is not a scalar") if (ref $id);
 
1074
        $midpt->id($id) if defined($id) && !ref($id);
1009
1075
    }
1010
1076
    $self->reroot($midpt);
1011
1077
    return $midpt;
1012
1078
}
1013
1079
 
 
1080
 
1014
1081
=head2 findnode_by_id
1015
1082
 
1016
1083
 Title   : findnode_by_id
1023
1090
 
1024
1091
=cut
1025
1092
 
1026
 
 
1027
1093
sub findnode_by_id {
1028
1094
    my $tree = shift;
1029
1095
    $tree->deprecated("use of findnode_by_id() is deprecated; ".
1030
 
                      "use find_node() instead");
 
1096
                      "use find_node() instead");
1031
1097
    my $id = shift;
1032
1098
    my $rootnode = $tree->get_root_node;
1033
1099
    if ( ($rootnode->id) and ($rootnode->id eq $id) ) {
1041
1107
    }
1042
1108
}
1043
1109
 
 
1110
 
1044
1111
=head2 move_id_to_bootstrap
1045
1112
 
1046
1113
 Title   : move_id_to_bootstrap
1049
1116
 Returns : undef
1050
1117
 Args    : undef
1051
1118
 
1052
 
 
1053
1119
=cut
1054
1120
 
1055
1121
sub move_id_to_bootstrap{
1056
1122
   my ($tree) = shift;
1057
1123
   for my $node ( grep { ! $_->is_Leaf } $tree->get_nodes ) {
1058
 
       $node->bootstrap($node->id || '');
 
1124
       $node->bootstrap(defined $node->id ? $node->id : '');
1059
1125
       $node->id('');
1060
1126
   }
1061
1127
}
1063
1129
 
1064
1130
=head2 add_trait
1065
1131
 
1066
 
  Example    : $key = $tree->add_trait($trait_file, 3);
1067
 
  Description: Add traits to a Bio::Tree:Tree nodes
1068
 
               of a tree from a file.
1069
 
  Returns    : trait name
1070
 
  Exceptions : log an error if a node has no value in the file
1071
 
  Args       : name of trait file (scalar string), 
1072
 
               index of trait file column (scalar int)
1073
 
  Caller     : main()
1074
 
 
1075
 
The trait file is a tab-delimited text file and needs to have a header
1076
 
line giving names to traits. The first column contains the leaf node
1077
 
ids. Subsequent columns contain different trait value sets. Columns
1078
 
numbering starts from 0. The default trait column is the second
1079
 
(1). The returned hashref has one special key, my_trait_name, that
1080
 
holds the trait name. Single or double quotes are removed.
 
1132
 Title   : add_trait
 
1133
 Usage   : my $key = $tree->add_trait($trait_file, 3);
 
1134
 Function: Add traits to the leaf nodes of a Bio::Tree:Tree from a file.
 
1135
           The trait file is a tab-delimited text file and needs to have a
 
1136
           header line giving names to traits. The first column contains the
 
1137
           leaf node ids. Subsequent columns contain different trait value sets.
 
1138
           Single or double quotes are removed from the trait values. Traits
 
1139
           are added to leaf nodes as a tag named $key using the add_tag_value()
 
1140
           method. This means that you can retrieve the trait values using the
 
1141
           get_tag_values() method (see the documentation for Bio::Tree::Node).
 
1142
 Returns : Trait name (a scalar) on success, undef on failure (for example, if
 
1143
           the column index requested was too large).
 
1144
 Args    : * Name of trait file (scalar string).
 
1145
           * Index of trait file column (scalar int). Note that numbering starts
 
1146
             at 0. Default: 1 (second column).
 
1147
           * Ignore missing values. Typically, if a leaf node has no value in
 
1148
             the trait file, an exception is thrown. If you set this option to
 
1149
             1, then no trait will be given to the node (no exception thrown).
1081
1150
 
1082
1151
=cut
1083
1152
 
1084
1153
sub _read_trait_file {
1085
 
    my $self = shift;
1086
 
    my $file = shift;
1087
 
    my $column = shift || 1;
 
1154
    my ($self, $file, $column) = @_;
 
1155
    $column ||= 1;
1088
1156
 
1089
 
    my $traits;
1090
 
    open my $TRAIT, "<", $file or $self->("Can't find file $file: $!\n");
 
1157
    my $trait_name;
 
1158
    my $trait_values;
 
1159
    open my $TRAIT, '<', $file or $self->throw("Could not open file $file: $!\n");
1091
1160
 
1092
1161
    my $first_line = 1;
1093
1162
    while (<$TRAIT>) {
1094
 
        if ($first_line) {
1095
 
            $first_line = 0;
1096
 
            s/['"]//g;
1097
 
            my @line = split;
1098
 
            $traits->{'my_trait_name'} = $line[$column];
1099
 
            next;
1100
 
        }
1101
 
        s/['"]//g;
1102
 
        my @line = split;
1103
 
        last unless $line[0];
1104
 
        $traits->{$line[0]} = $line[$column];
 
1163
        chomp;
 
1164
        s/['"]//g;
 
1165
        my @line = split /\t/;
 
1166
        if ($first_line) {
 
1167
            $first_line = 0;
 
1168
            $trait_name = $line[$column];
 
1169
            next;
 
1170
        }
 
1171
 
 
1172
        my $id = $line[0];
 
1173
        last if (not defined $id) or ($id eq '');
 
1174
 
 
1175
        # Skip empty trait values
 
1176
        my $value = $line[$column];
 
1177
        next if (not defined $value) or ($value eq '');
 
1178
 
 
1179
        $trait_values->{$id} = $value;
1105
1180
    }
1106
 
    return $traits;
 
1181
 
 
1182
    close $TRAIT;
 
1183
    return $trait_name, $trait_values;
1107
1184
}
1108
1185
 
1109
1186
sub add_trait {
1110
 
    my $self = shift;
1111
 
    my $file = shift;
1112
 
    my $column = shift;
1113
 
 
1114
 
    my $traits = $self->_read_trait_file($file, $column); # filename, trait column
1115
 
    my $key = $traits->{'my_trait_name'};
1116
 
    #use YAML; print Dump $traits; exit;
1117
 
    foreach my $node ($self->get_leaf_nodes) {
1118
 
        # strip quotes from the node id
1119
 
        $node->id($1) if $node->id =~ /^['"]+(.*)['"]+$/;
1120
 
        eval {
1121
 
            $node->verbose(2);
1122
 
            $node->add_tag_value($key, $traits->{ $node->id } );
1123
 
        };
1124
 
        $self->throw("ERROR: No trait for node [".
1125
 
                     $node->id. "/".  $node->internal_id. "]")
1126
 
            if $@;
 
1187
    my ($self, $file, $column, $ignore) = @_;
 
1188
    $ignore = 0 if not defined $ignore;
 
1189
 
 
1190
    my ($trait_name, $trait_values) = $self->_read_trait_file($file, $column);
 
1191
 
 
1192
    if (defined $trait_name) {
 
1193
 
 
1194
        for my $node ($self->get_leaf_nodes) {
 
1195
 
 
1196
            # strip quotes from the node id
 
1197
            $node->id($1) if $node->id =~ /^['"]+(.*)['"]+$/;
 
1198
 
 
1199
            if ( not exists $trait_values->{$node->id} ) {
 
1200
                if ($ignore) {
 
1201
                    next;
 
1202
                } else {
 
1203
                    $self->throw("No trait for node [".$node->id."/".$node->internal_id."]");
 
1204
                }
 
1205
            }
 
1206
 
 
1207
            $node->add_tag_value($trait_name, $trait_values->{ $node->id } );
 
1208
 
 
1209
        }
1127
1210
    }
1128
 
    return $key;
 
1211
    return $trait_name;
1129
1212
}
1130
1213
 
1131
1214