File Coverage

blib/lib/OBO/Parser/NCBIParser.pm
Criterion Covered Total %
statement 74 74 100.0
branch 13 18 72.2
condition 1 3 33.3
subroutine 10 10 100.0
pod 2 4 50.0
total 100 109 91.7


line stmt bran cond sub pod time code
1             # $Id: NCBIParser.pm 2015-02-12 Erick Antezana $
2             #
3             # Module : NCBIParser.pm
4             # Purpose : Parse NCBI files: names and nodes
5             # License : Copyright (c) 2006-2015 by ONTO-perl. All rights reserved.
6             #
7             # This program is free software; you can redistribute it and/or
8             # modify it under the same terms as Perl itself.
9             #
10             ###############################################################################
11             package OBO::Parser::NCBIParser;
12              
13 1     1   713 use OBO::Core::Term;
  1         3  
  1         27  
14 1     1   6 use OBO::Parser::OBOParser;
  1         2  
  1         21  
15 1     1   6 use OBO::Core::Ontology;
  1         3  
  1         20  
16              
17 1     1   5 use strict;
  1         1  
  1         22  
18 1     1   5 use warnings;
  1         2  
  1         24  
19 1     1   5 use Carp;
  1         3  
  1         774  
20              
21             $Carp::Verbose = 0;
22              
23             sub new {
24 1     1 0 11 my $class = shift;
25 1         17 my $self = {};
26 1         2 bless ( $self, $class );
27 1         3 return $self;
28             }
29              
30             =head2 parse
31              
32             Usage : $ncbi_parser->parse ( $ncbi_nodes_path )
33             Returns : ref to a hash { child_id => parent_id }
34             Args : nodes.dmp path ( string )
35            
36             Usage : $ncbi_parser->parse ( $ncbi_names_path, $name_type )
37             Returns : ref to a hash { ncbi_id => ncbi_name }
38             Args :
39             1. names.dmp path or nodes.dmp path, string
40             2. ncbi name type ( string, e.g. 'scientific name' ) if the first arg is names.dmp otherwise none
41             Function : parses the complete NCBI taxonomy
42            
43             =cut
44              
45             sub parse {
46             my (
47 2     2 1 418 $self,
48             $input_path,
49             $name_type # optional
50             ) = @_;
51            
52 2 50       6 croak "Not enough arguments! " if ( @_ < 1 );
53            
54 2   33     136 open my $IN, '<', $input_path || croak "Can't open file '$input_path': $! ";
55 2         53 my @in_lines = <$IN>;
56            
57 2         5 my %map;
58 2 100       6 if ( $name_type ) { # parsing names.dmp
59             # %map: ncbi_id => scientific_name
60 1         3 foreach my $line ( @in_lines ) {
61 22         57 my @fields = split /\t\|/, $line;
62 22 100       59 if ( $fields[3] eq "\t$name_type" ) {
63 10         11 my $key = $fields[0];
64 10         16 my $value = substr $fields[1], 1;
65 10         28 $map{$key} = $value;
66             }
67             }
68             } else { # parsing nodes.dmp
69             # %map: child_id => parent_id
70 1         3 foreach my $line ( @in_lines ) {
71 8         33 my @fields = split (/\t\|/, $line);
72 8         12 my $key = $fields[0];
73 8         11 my $value = substr $fields[1], 1;
74 8         30 $map{$key} = $value;
75             }
76             }
77 2         43 close ( $IN );
78 2         14 return \%map;
79             }
80              
81             =head2 work
82              
83             Usage : $NCBIParser->work ( $onto, $nodes, $names, $ncbi_ids )
84             Returns : map of added terms { NCBI ID => OBO::Core::Term object }
85             Args :
86             1. input ontology, OBO::Core::Ontology object
87             2. ref to a hash { child_id => parent_id }
88             3. ref to a hash { ncbi_id => scientific_name }
89             4. parental ontology term for the root of the taxonomy, OBO::Core::Term object
90             5. ref to a list of NCBI taxon ids ( \d+ )
91            
92             Function : adds NCBI taxonomy to the input ontology for the specified taxa
93            
94             =cut
95              
96             sub work {
97             my (
98 1     1 1 9 $self,
99             $ontology,
100             $nodes,
101             $names,
102             $parent,
103             $ncbi_ids,
104             ) = @_;
105            
106 1         3 my %selected_nodes = ( ); # taxon id => parent id
107 1         2 my %selected_names = ( ); # taxon id => taxon name
108              
109             # the hashes %selected_nodes and %selected_names are being populated:
110 1         2 foreach my $ncbi_id ( @{$ncbi_ids} ) {
  1         3  
111 1         4 getParentsRecursively ( $ncbi_id, $nodes, $names, \%selected_nodes, \%selected_names );
112             }
113 1         2 my %map; # NCBI_ID=>taxon_term
114             # the terms are created and added to the ontology and %map
115 1         4 foreach my $ncbi_id ( keys %selected_nodes ){
116 4         7 my $selected_name = $selected_names{$ncbi_id};
117 4         18 my $taxon = OBO::Core::Term->new ( );
118 4         16 $taxon->id ( "NCBI:$ncbi_id" );
119 4         13 $taxon->name ( $selected_name );
120 4         10 $ontology->add_term ( $taxon );
121 4         9 $map{$ncbi_id} = $taxon;
122             } # the end of foreach
123             # Connect children to parents by 'is_a' relationships but not if the child is root ( cyclic is_a )
124 1         4 foreach my $ncbi_id ( keys %selected_nodes ) {
125 4 50       11 my $child = $map{$ncbi_id} or croak "No term for '$ncbi_id' in the map: $! ";
126 4 50       14 my $parent = $map{$selected_nodes{$ncbi_id}} or croak "No term for '$selected_nodes{$ncbi_id}' in the map: $! ";
127 4 100       19 $ontology->create_rel ( $child, 'is_a', $parent ) if ( $ncbi_id != 1 );
128             }
129 1 50       5 my $root = $ontology->get_term_by_id ( 'NCBI:1' ) or croak "No term in the ontology for 'root': $!";
130 1         5 $ontology->create_rel ( $root, 'is_a', $parent );
131 1         5 return \%map;
132             }
133              
134             ########################################################################
135             #
136             # Subroutines
137             #
138             ########################################################################
139              
140             sub getParentsRecursively {
141            
142 4 50   4 0 12 caller eq __PACKAGE__ or croak;
143            
144 4         7 my ( $ncbi_id, $nodes, $names, $selected_nodes, $selected_names ) = @_;
145 4         7 my $child_id = $ncbi_id;
146 4         5 my $parent_id = ${$nodes}{$ncbi_id};
  4         35  
147 4         6 my $child_name = ${$names}{$ncbi_id};
  4         9  
148 4         5 my $parent_name = ${$names}{$ncbi_id};
  4         7  
149            
150 4         7 $selected_nodes->{$child_id} = $parent_id;
151 4         8 $selected_names->{$child_id} = $child_name;
152            
153 4 100       22 getParentsRecursively ( $parent_id, $nodes, $names, $selected_nodes, $selected_names ) if ( $child_id != 1 );
154             }
155              
156             1;
157              
158             __END__