File Coverage

GO/Model/Term.pm
Criterion Covered Total %
statement 143 338 42.3
branch 43 160 26.8
condition 7 36 19.4
subroutine 30 62 48.3
pod 31 49 63.2
total 254 645 39.3


line stmt bran cond sub pod time code
1             # $Id: Term.pm,v 1.24 2008/01/17 20:08:14 cmungall Exp $
2             #
3             # This GO module is maintained by Chris Mungall
4             #
5             # see also - http://www.geneontology.org
6             # - http://www.godatabase.org/dev
7             #
8             # You may distribute this module under the same terms as perl itself
9              
10              
11             package GO::Model::Term;
12              
13             =head1 NAME
14              
15             GO::Model::Term - a term or concept in an ontology
16              
17             =head1 SYNOPSIS
18              
19             # From a file
20             use GO::Parser;
21             my $parser = new GO::Parser({handler=>'obj'}); # create parser object
22             $parser->parse("gene_ontology.obo"); # parse file -> objects
23             my $graph = $parser->handler->graph; # get L object
24             my $term = $graph->get_term("GO:0001303"); # fetch a term by ID
25             printf "Term %s %s\n", $term->name, $term->acc;
26              
27             # From a GO Database (requires go-db-perl)
28             my apph = GO::AppHandle->connect(-dbname=>$dbname);
29             my $term = $apph->get_term({acc=>00003677});
30             printf "Term:%s (%s)\nDefinition:%s\nSynonyms:%s\n",
31             $term->name,
32             $term->public_acc,
33             $term->definition,
34             join(", ", @{$term->synonym_list});
35              
36             =head1 DESCRIPTION
37              
38             Represents an Ontology term; the same class is used for process,
39             compartment and function
40              
41             currently, a Term is not aware of its Relationships; to find out how a
42             term is related to other terms, use the a L object,
43             which will give you the GO::Model::Relationship objects; for example
44              
45             $rels = $graph->get_parent_relationships($term->acc);
46              
47             =head1 SEE ALSO
48              
49             L
50             L
51             L
52             L
53              
54             =head1 NOTES
55              
56             Like all the GO::Model::* classes, this uses accessor methods to get
57             or set the attributes. by using the accessor method without any
58             arguments gets the value of the attribute. if you pass in an argument,
59             then the attribuet will be set according to that argument.
60              
61             for single-valued attributes
62              
63             # this sets the value of the attribute
64             $my_object->attribute_name("my value");
65              
66             # this gets the value of the attribute
67             $my_value = $my_object->attribute_name();
68              
69             for lists:
70              
71             # this sets the values of the attribute
72             $my_object->attribute_name(\@my_values);
73              
74             # this gets the values of the attribute
75             $my_values = $my_object->attribute_name();
76              
77              
78             =cut
79              
80              
81 24     24   144 use Carp;
  24         43  
  24         1953  
82 24     24   159 use Exporter;
  24         46  
  24         1584  
83 24     24   12755 use GO::Utils qw(rearrange);
  24         64  
  24         3676  
84 24     24   19391 use GO::Model::Root;
  24         66  
  24         1358  
85 24     24   19392 use GO::Model::Association;
  24         73  
  24         1408  
86 24     24   16022 use GO::Model::Xref;
  24         69  
  24         3685  
87 24     24   15081 use GO::Model::GeneProduct;
  24         76  
  24         1377  
88 24     24   787 use strict;
  24         52  
  24         1287  
89 24     24   133 use vars qw(@ISA);
  24         50  
  24         1127  
90              
91 24     24   141 use base qw(GO::Model::Root Exporter);
  24         47  
  24         153489  
92              
93             our %code_to_namespace =
94             ('F'=>'molecular_function',
95             'P'=>'biological_process',
96             'C'=>'cellular_component');
97              
98 4732     4732   39268 sub _valid_params { return qw(id name description term_type
99             is_obsolete is_relationship_type public_acc acc definition
100             synonym_list association_list selected_association_list
101             association_hash n_associations dbxref_list property_list subset_list
102             equivalent_to_union_of_term_list
103             disjoint_from_term_list
104             consider_list
105             replaced_by_list
106             is_instance
107             stag is_anonymous is_cyclic is_transitive is_symmetric is_anti_symmetric is_reflexive
108             inverse_of transitive_over domain range logical_definition); }
109              
110             =head2 acc
111              
112             Usage - print $term->acc()
113             Alias - public_acc
114             Returns -
115             Args -
116              
117             accessor: gets/sets GO ID/accession [as an integer]
118              
119             throws: exception if you try to pass in a non-integer
120              
121             if you want to use IDs in the format GO:0000nnn, then use the method
122             public_acc()
123              
124             =cut
125              
126             sub acc {
127 7220     7220 1 14068 my $self = shift;
128 7220 100       15879 if (@_) {
129 1415         1724 my $acc = shift;
130 1415         3303 $self->{acc} = $acc;
131             }
132 7220         29721 return $self->{acc};
133             }
134              
135             *public_acc = \&acc;
136              
137             =head2 name
138              
139             Usage - print $term->name;
140             Returns -
141             Args -
142              
143             accessor: gets/sets "name" attribute
144              
145             =cut
146              
147             sub name {
148 3540     3540 1 5453 my $self = shift;
149 3540 100       8673 $self->{name} = shift if @_;
150 3540         5443 my $name = $self->{name};
151 3540         51215 return $name;
152             }
153              
154             sub description {
155 0     0 0 0 my $self = shift;
156 0         0 warn('deprecated');
157 0         0 $self->name(@_);
158             }
159              
160              
161             =head2 subset_list
162              
163             Usage - foreach (@{$term->subset_list || []}) { printf " $_\n" }
164             Returns - list of strings
165             Args - list of strings [optional]
166              
167             List of subset Accs for a term
168              
169             Subsets are also known as GO Slims
170              
171             =cut
172              
173             =head2 in_subset
174              
175             Usage - if ($term->in_subset('goslim_prok');
176             Returns - bool
177             Args - subset-name str
178              
179             Tests if the term belongs to a subset
180              
181             =cut
182              
183             sub in_subset {
184 0     0 1 0 my $self = shift;
185 0         0 my $subset = shift;
186 0 0       0 return 1 if grep {$_ eq $subset} @{$self->subset_list || []};
  0 0       0  
  0         0  
187 0         0 return 0;
188             }
189              
190             =head2 definition
191              
192             Usage - print $term->definition;
193             Returns -
194             Args -
195              
196             accessor: gets/sets "definition" attribute
197              
198             =cut
199              
200             sub definition {
201 41     41 1 69 my $self = shift;
202 41 50       178 $self->{definition} = shift if @_;
203 41         246 return $self->{definition};
204             }
205              
206             =head2 primary_xref
207              
208             Title : primary_xref
209             Usage :
210             Function:
211             Example :
212             Returns : GO::Model::Xref
213             Args :
214              
215             The same as acc(), except the ID is returned as a L
216             rather than a string
217              
218             =cut
219              
220             sub primary_xref{
221 0     0 1 0 my ($self,@args) = @_;
222              
223 0         0 my ($dbname, $acc) = split(/\:/, $self->acc);
224 0         0 return GO::Model::Xref->new({xref_key=>$acc,
225             xref_dbname=>$dbname});
226             }
227              
228              
229             =head2 comment
230              
231             Title : comment
232             Usage : $obj->comment($newval)
233             Function:
234             Example :
235             Returns : value of comment (a scalar)
236             Args : on set, new value (a scalar or undef, optional)
237              
238              
239             =cut
240              
241             sub comment{
242 8     8 1 17 my $self = shift;
243              
244 8 50       53 return $self->{'comment'} = shift if @_;
245 0         0 return $self->{'comment'};
246             }
247              
248             =head2 definition_dbxref_list
249              
250             Title : definition_dbxref_list
251             Usage : $obj->definition_dbxref(\@xrefs)
252             Function:
253             Example :
254             Returns : definition_dbxref_list hashlist (of GO::Model::Xref)
255             Args : on set, new values (GO::Model::Xref hashlist)
256              
257             L
258              
259             =cut
260              
261             sub definition_dbxref_list{
262 196     196 1 440 my $self = shift;
263              
264 196 100       467 return $self->{'definition_dbxref_list'} = shift if @_;
265 160         6981 return $self->{'definition_dbxref_list'};
266             }
267              
268              
269             =head2 add_definition_dbxref
270              
271             - Usage : $term->add_definition_dbxref($xref);
272             - Args : GO::Term::Xref
273            
274             L
275              
276             =cut
277              
278             sub add_definition_dbxref {
279 53     53 1 81 my $self = shift;
280              
281 53         100 foreach my $dbxref (@_) {
282 53 50       126 if (!ref($dbxref)) {
283 0         0 my ($db, @rest) = split(/:/, $dbxref);
284 0 0       0 confess "$dbxref not a dbxref" unless @rest;
285 0         0 my $acc = join(":", @rest);
286 0         0 $dbxref = $self->apph->create_xref_obj({xref_key=>$acc,
287             xref_dbname=>$db});
288             }
289 53 50       212 UNIVERSAL::isa($dbxref, "GO::Model::Xref") or confess($dbxref." not a xref");
290 53 100       340 $self->definition_dbxref_list([]) unless $self->definition_dbxref_list;
291 53         75 push(@{$self->definition_dbxref_list}, $dbxref);
  53         104  
292              
293             }
294 53         139 $self->definition_dbxref_list;
295             }
296              
297              
298             sub lisp_acc {
299 0     0 0 0 my $self = shift;
300             return
301 0         0 sprintf "Go%07d", $self->acc;
302             }
303              
304              
305              
306             =head2 has_synonym
307              
308             Usage - if ($term->has_synonym("autotrophy") {...}
309             Returns - bool
310             Args - string
311              
312             =cut
313              
314             sub has_synonym {
315 0     0 1 0 my $self = shift;
316 0         0 my $str = shift;
317 0 0       0 my @syns = @{$self->synonym_list || []};
  0         0  
318 0 0       0 if (grep {$_ eq $str} @syns) {
  0         0  
319 0         0 return 1;
320             }
321 0         0 return 0;
322             }
323              
324              
325             =head2 add_synonym
326              
327             Usage - $term->add_synonym("calcineurin");
328             Usage - $term->add_synonym(@synonym_strings);
329             Returns -
330             Args -
331              
332             Adds a synonym; loses type information (the synonym type in blank)
333              
334             =cut
335              
336             sub add_synonym {
337 2     2 1 4 my $self = shift;
338 2         8 $self->add_synonym_by_type('', $_) foreach @_;
339             }
340              
341             =head2 synonym_list
342              
343             Usage - my $syn_l = $term->synonym_list;
344             Usage - $term->synonym_list([$syn1, $syn2]);
345             Returns - arrayref
346             Args - arrayref [optional]
347              
348             accessor: gets/set list of synonyms [array reference]
349              
350             each synonym is represented as a string - this method loses synonym
351             typing information. If used as a setter, will set the type for each
352             synonym to null
353              
354             =cut
355              
356             sub synonym_list {
357 11     11 1 27 my $self = shift;
358 11 100       29 if (@_) {
359 2         4 my $syns = shift;
360 2         7 $self->synonyms_by_type_idx({});
361 2         10 $self->add_synonym(@$syns);
362             }
363 11         30 my $sbt = $self->synonyms_by_type_idx;
364 5 50       34 my @syns =
365 11         35 map { @{$sbt->{$_} || []} } keys %$sbt;
  5         8  
366 11         47 return \@syns;
367             }
368              
369             sub synonym_type_list {
370              
371 0 0   0 0 0 return [keys %{shift->{_synonyms_by_type_idx} || {}}];
  0         0  
372             }
373              
374             # private: lookup table indexed by type, value is syn string arrayref
375             sub synonyms_by_type_idx {
376 158     158 0 196 my $self = shift;
377 158 100       338 if (@_) {
378 2         5 $self->{_synonyms_by_type_idx} = shift;
379             }
380             else {
381 156 100       564 $self->{_synonyms_by_type_idx} = {} unless
382             $self->{_synonyms_by_type_idx};
383             }
384 158         994 return $self->{_synonyms_by_type_idx};
385             }
386              
387              
388             =head2 add_synonym_by_type
389              
390             Usage - $term->add_synonym_by_type('exact', $syn);
391             Returns -
392             Args -
393              
394             =cut
395              
396             sub add_synonym_by_type {
397 145     145 1 858 my $self = shift;
398 145   100     548 my $type = shift || '';
399 145         205 my $syn = shift;
400 145         166 push(@{$self->synonyms_by_type_idx->{$type}}, $syn);
  145         380  
401             }
402              
403              
404             =head2 synonyms_by_type
405              
406             Usage - $synstrs = $term->synonyms_by_type('exact');
407             Usage - $term->synonyms_by_type('exact', \@exact_syns);
408             Returns - arrayref of strings
409             Args - type string, arrayref of strings [optional]
410              
411             in getter mode, gets a list of synonyms of a particular type
412              
413             in setter mode, sets a list of synonyms for a particular type
414              
415             =cut
416              
417             sub synonyms_by_type {
418 0     0 1 0 my $self = shift;
419 0         0 my $type = shift;
420 0 0       0 if (@_) {
421 0         0 $self->synonyms_by_type_idx->{$type} = shift;
422             }
423 0   0     0 return $self->synonyms_by_type_idx->{$type} || [];
424             }
425              
426             =head2 alt_id_list
427              
428             Usage - my $syn_l = $term->alt_id_list;
429             Usage - $term->alt_id_list([$syn1, $syn2]);
430             Returns - arrayref
431             Args - arrayref [optional]
432              
433             accessor: gets/set list of synonyms [array reference]
434              
435             =cut
436              
437             sub alt_id_list {
438 0     0 1 0 my $self = shift;
439 0 0       0 if (@_) {
440 0         0 $self->add_alt_id(@_);
441             }
442 0         0 $self->synonyms_by_type('alt_id');
443             }
444              
445              
446             =head2 add_alt_id
447              
448             Usage - $term->add_alt_id('GO:0000001');
449             Returns -
450             Args - id string, or list of id strings
451              
452             =cut
453              
454             sub add_alt_id {
455 15     15 1 26 my $self = shift;
456 15         99 my @alt_ids = @_;
457 15         106 $self->add_synonym_by_type('alt_id',$_) foreach @_;
458             }
459             *add_secondaryid = \&add_alt_id;
460              
461              
462             =head2 namespace (INHERITED)
463              
464             Usage - print $term->namespace(); # getting the type
465             Usage - $term->namespace("molecular_function"); # setting the type
466             Alias - type
467             Alias - term_type
468             Alias - category
469             Alias - ontology
470             Returns - string representing type
471             Args - string represnting type [optional]
472              
473             The OBO namespace for the L or
474             L
475              
476             This method is inherited from the superclass
477              
478             =cut
479              
480             # DEFINED IN SUPERCLASS
481             # documentation repeated here to make things easier to find
482              
483             =head2 set_namespace_by_code
484              
485             Usage - $term->set_namespace_by_code("P");
486             Returns -
487             Args - String: M, P or C
488              
489             Currently the mapping is hardcoded
490              
491             ('F'=>'molecular_function',
492             'P'=>'biological_process',
493             'C'=>'cellular_component');
494              
495             =cut
496              
497             sub set_namespace_by_code {
498 173     173 1 242 my $self = shift;
499 173         249 my $code = shift;
500 173         413 my $ns = $code_to_namespace{$code};
501 173 50       379 if (!$ns) {
502 0         0 $self->throw("Unknown code: $code");
503             }
504 173         701 $self->namespace($ns);
505 173         488 return $code;
506             }
507              
508             =head2 get_code_from_namespace
509              
510             Usage - $code = $term->get_code_from_namespace;
511             Returns - String: M, P or F
512             Args - String (if omitted will use current namespace)
513              
514             Returns the code for the current namespace (or any given namespace if supplied)
515              
516             =cut
517              
518             sub get_code_from_namespace {
519 140     140 1 3304 my $self = shift;
520 140   100     657 my $ns = shift || $self->namespace || '';
521 140         1031 my %m = reverse %code_to_namespace; # assumes 1-1 bijective mapping
522 140         416 my $code = $m{$ns};
523             # if (!$code) {
524             # $self->throw("Unknown namespace: $ns");
525             # }
526 140         549 return $code;
527             }
528              
529              
530              
531              
532             # DEPCRECATED
533             sub add_obsolete {
534 0     0 0 0 my $self = shift;
535 0 0       0 if (@_) {
536 0         0 my $obs = shift;
537 0         0 $self->{obsolete_h}->{$obs->acc} = $obs;
538             }
539 0         0 return $self->obsolete_list;
540             }
541              
542             # deprecated
543             sub obsolete_list {
544 0     0 0 0 my $self = shift;
545 0         0 while (shift @_) {
546 0         0 $self->add_obsolete ($_);
547             }
548 0         0 my @obs = values %{$self->{obsolete_h}};
  0         0  
549 0         0 return \@obs;
550             }
551              
552              
553             =head2 add_dbxref
554              
555             - Usage : $term->add_dbxref($xref);
556             - Args : GO::Term::Xref
557              
558             L
559              
560             =cut
561              
562             sub add_dbxref {
563 755     755 1 1080 my $self = shift;
564              
565 755         1429 foreach my $dbxref (@_) {
566 755 50       1674 if (!ref($dbxref)) {
567 0         0 my ($db, @rest) = split(/:/, $dbxref);
568 0 0       0 confess "$dbxref not a dbxref" unless @rest;
569 0         0 my $acc = join(":", @rest);
570 0         0 $dbxref = $self->apph->create_xref_obj({xref_key=>$acc,
571             xref_dbname=>$db});
572             }
573 755 50       2403 UNIVERSAL::isa($dbxref, "GO::Model::Xref") or confess($dbxref." not a xref");
574 755 50       3965 $self->dbxref_list([]) unless $self->dbxref_list;
575 755         3719 push(@{$self->dbxref_list}, $dbxref);
  755         3408  
576              
577             }
578 755         3663 $self->dbxref_list;
579             }
580             *add_xref = \&add_dbxref;
581              
582              
583             =head2 dbxref_list
584              
585             - Usage : $term->dbxref_list($xref);
586             - Args : optional listref of GO::Term::Xref
587             - Returns : listref of GO::Term::Xref
588            
589              
590             accessor: gets/sets list of dbxref [array reference]
591              
592             =cut
593              
594             # autodefined
595              
596             =head2 is_obsolete
597              
598             accessor: gets/set obsolete flag [boolean
599              
600             =cut
601              
602             sub is_obsolete {
603 0     0 1 0 my $self = shift;
604 0 0       0 $self->{is_obsolete} = shift if @_;
605 0 0       0 return $self->{is_obsolete} ? 1:0;
606             }
607              
608             =head2 is_root
609              
610             accessor: gets/set is_root flag [boolean]
611              
612             =cut
613              
614             sub is_root {
615 12     12 1 38 my $self = shift;
616 12 50       58 $self->{is_root} = shift if @_;
617 12 50       84 return $self->{is_root} ? 1:0;
618             }
619              
620             =head1 TERM ASSOCIATION METHODS
621              
622             =head2 association_list
623              
624             Usage - $assoc_l = $term->association_list
625             Returns - arrayref of GO::Model::Association
626             Args - arrayref of GO::Model::Association [optional]
627              
628             accessor: gets/set list of associations [array reference]
629              
630             if this is undefined, the datasource will be queried
631             for the associations
632              
633             =cut
634              
635             sub association_list {
636 1154     1154 1 5133 my $self = shift;
637 1154         10336 my ($al, $sort_by) =
638             rearrange([qw(associations sort_by)], @_);
639 1154 50       4439 if ($al) {
640 0 0       0 if (!ref($al) eq "ARRAY") {
641 0         0 confess("$al is not an array ref");
642             }
643 0         0 $self->{"association_list"} = $al;
644 0 0       0 foreach my $assoc (@{$self->{"association_list"} || []}) {
  0         0  
645 0         0 my $gene = $assoc->gene_product;
646 0         0 $self->{association_hash}->{$gene->acc} = $assoc;
647             }
648             }
649 1154 100       4097 if (!defined($self->{"association_list"})) {
650 829 50       2337 if (!defined($self->apph)) {
651             # print $self->dump;
652             }
653             else {
654 829         2608 $self->{"association_list"} =
655             $self->apph->get_direct_associations($self);
656 829 50       1118 foreach my $assoc (@{$self->{"association_list"} || []}) {
  829         6679  
657 0         0 my $gene = $assoc->gene_product;
658 0 0       0 if (!$gene) {
659 0         0 confess("no gene for assoc $assoc");
660             }
661 0 0       0 if (!$self->{association_hash}->{$gene->acc}) {
662 0         0 $self->{association_hash}->{$gene->acc} = [];
663             }
664 0         0 push(@{$self->{association_hash}->{$gene->acc}}, $assoc);
  0         0  
665             }
666             }
667             }
668 1154 0 0     3692 if ($sort_by &&
      33        
669             (!$self->{"association_list_sort_by"} ||
670             $self->{"association_list_sort_by"} ne $sort_by)) {
671 0 0       0 my @sortlist = ref($sort_by) ? @$sort_by : ($sort_by);
672 0         0 my @al =
673             sort {
674 0 0       0 my $as1 = $a;
675 0         0 my $as2 = $b;
676 0         0 my $i=0;
677 0         0 my $cmp;
678 0   0     0 while (!defined($cmp) &&
679             $i < @sortlist) {
680 0         0 my $sortk = $sortlist[$i];
681 0         0 $i++;
682 0 0       0 if ($sortk eq "gene_product") {
    0          
683 0         0 $cmp =
684             $as1->gene_product->symbol cmp
685             $as2->gene_product->symbol;
686             }
687             elsif ($sortk eq "ev_code") {
688 0         0 confess("cant sort on evcode yet");
689             }
690             else {
691 0         0 confess("dont know $sortk");
692             }
693             }
694 0         0 $cmp;
695 0         0 } @{$self->{association_list} || []};
696 0         0 $self->{"association_list"} = \@al;
697 0         0 $self->{"association_list_sort_by"} = $sort_by;
698             }
699 1154         26682 return $self->{"association_list"};
700             }
701              
702             =head2 selected_association_list
703              
704             Usage - $assoc_l = $term->selected_association_list
705             Returns - arrayref of GO::Model::Association
706             Args - arrayref of GO::Model::Association [optional]
707              
708             accessor: gets list of SELECTED associations [array reference]
709              
710             [this method is only of use if you are using it in conjunction with
711             L in the go-db-perl distro]
712              
713             this in not the total list of all associations associated with a term;
714             if the term was created via a query on products, this will include
715             those associations
716              
717             L
718              
719             =cut
720              
721             # done by AUTOLOAD
722              
723              
724              
725             =head2 add_association
726              
727             Usage - $term->add_association($assoc);
728             Returns -
729             Args - GO::Model::Association
730              
731             L
732              
733             =cut
734              
735             sub add_association {
736 173     173 1 247 my $self = shift;
737 173 100       509 if (!$self->{"association_list"}) {
738 79         272 $self->{"association_list"} = [];
739             }
740 173         248 my $assoc = shift;
741 173 50       952 if (ref($assoc) ne "GO::Model::Association") {
742             # it's a hashref - create obj from hashref
743 0         0 my $assoc2 = $self->apph->create_association_obj($assoc);
744 0         0 $assoc = $assoc2;
745             }
746 173         187 push(@{$self->{"association_list"}}, ($assoc));
  173         1002  
747 173         518 my $gene = $assoc->gene_product;
748 173 100       709 if (!$self->{association_hash}->{$gene->acc}) {
749 131         532 $self->{association_hash}->{$gene->acc} = [];
750             }
751 173         497 push(@{$self->{association_hash}->{$gene->acc}}, $assoc);
  173         484  
752 173         1112 return $self->{"association_list"};
753             }
754              
755              
756             =head2 add_selected_association
757              
758             Usage -
759             Returns -
760             Args -
761              
762             L
763              
764             =cut
765              
766             sub add_selected_association {
767 0     0 1 0 my $self = shift;
768 0         0 my $assoc = shift;
769 0 0       0 $assoc->isa("GO::Model::Association") || confess;
770 0 0       0 if (!$self->{"selected_association_list"}) {
771 0         0 $self->{"selected_association_list"} = [];
772             }
773 0         0 push(@{$self->{"selected_association_list"}}, $assoc);
  0         0  
774             }
775              
776             =head2 association_hash
777              
778             returns associations as listref of unique GeneProduct objects
779              
780             L
781              
782             =cut
783              
784             sub association_hash {
785 0     0 1 0 my $self = shift;
786 0 0       0 if (!defined($self->{"association_list"})) {
787 0         0 $self->association_list;
788             }
789 0 0       0 $self->{"association_hash"} = shift if @_;
790 0         0 return $self->{"association_hash"};
791             }
792              
793             =head2 get_all_associations
794              
795             Usage - my $al = $term->get_all_associations
796             Returns - GO::Model::Association list
797             Args -
798              
799             returns all associations for the term and the terms beneath it in the GO DAG
800              
801             same as $apph->get_all_associations($term)
802              
803             L
804              
805             =cut
806              
807             sub get_all_associations {
808 0     0 1 0 my $self = shift;
809 0         0 $self->apph->get_all_associations($self);
810             }
811              
812             =head2 n_associations
813              
814             Usage - my $n = $term->n_associations
815             Returns -
816             Args -
817              
818             =cut
819              
820             sub n_associations {
821 0     0 1 0 my $self = shift;
822 0 0       0 if (!@{$self->{"association_list"} || []}) {
  0 0       0  
823              
824             # association count can be get/set even if the actual
825             # list is not present
826 0 0       0 $self->{n_associations} = shift if @_;
827             }
828 0 0 0     0 if (!defined($self->{n_associations}) &&
829             $self->{association_list}) {
830              
831             # we have already loaded the
832             # association list
833 0 0       0 $self->{n_associations} =
834 0         0 scalar(@{$self->association_list || []});
835             }
836 0 0       0 if (!defined($self->{n_associations})) {
837 0         0 $self->{n_associations} =
838             $self->apph->get_association_count($self);
839             }
840 0         0 return $self->{n_associations};
841             }
842              
843              
844             =head2 product_list
845              
846             Usage - $prods = $term->product_list
847             Returns - L listref
848             Args -
849              
850             Returns a reference to an array of gene products that are attached
851             directly to this term.
852              
853             (if the products have not been fetched, this method will call
854             $term->association_list, cache the results, and use the associations
855             to build the product list. succeeding calls of product_list to this
856             term will hence be faster)
857              
858             See L
859              
860             =cut
861              
862             sub product_list {
863 0     0 1 0 my $self = shift;
864 0         0 my $assocs = $self->association_list;
865 0         0 my @prods = ();
866 0         0 my %ph = ();
867 0         0 foreach my $assoc (@$assocs) {
868 0         0 my $gp = $assoc->gene_product;
869 0 0       0 if (!$ph{$gp->id}) {
870 0         0 push(@prods, $gp);
871 0         0 $ph{$gp->id} = 1;
872             }
873             }
874 0         0 return [@prods];
875             }
876              
877              
878             =head2 deep_product_list
879              
880             Usage -
881             Returns - GO::Model::GeneProduct listref
882             Args -
883              
884             finds all products attached to this term and all terms below in the
885             graph
886              
887             L
888              
889             =cut
890              
891             sub deep_product_list {
892 0     0 1 0 my $self = shift;
893 0         0 my $prods =
894             $self->apph->get_products({deep=>1, term=>$self});
895 0         0 return $prods;
896             }
897              
898             =head2 n_deep_products
899              
900             Usage - my $count = $term->n_deep_products;
901             Returns - int
902             Args - filter (hashref) - or string "recount"
903              
904             gets the count for the *dsitinct* number of GO::Model::GeneProduct
905             entries annotated at OR BELOW this level. if you have set the filters
906             in GO::AppHandle then these filters will be used in determining the
907             count.
908              
909             Remember, if you did not explicitly set the filters, then the
910             default filter will be used, which is [!IEA] (i.e. curated
911             associations only, see www.geneontology.org for a discussion of
912             evidence codes).
913              
914             Note: currently only the speciesdb filter is respected. It turns out
915             to be very expensive to do the set arithmetic for distinct recursive
916             gene counts with different evidence combinations. Because each product
917             belongs to one speciesdb only, the speciesdb counts are mutually
918             exclusive, which makes this easier.
919              
920             # get the number of gene products that have been annotated
921             # as transcription factors in worm and fly discounting
922             # uncurated automatic annotations
923             $apph->filters({evcodes=>["!IEA"], speciesdbs=>["SGD", "FB"]});
924             $term = $apph->get_term({name=>"transcription factor"});
925             print $term->n_deep_products;
926              
927             The count will be cached, so if you alter the filter parameters be sure
928             to get a recount like this:
929              
930             my $count = $term->n_deep_products("recount");
931              
932             TODO: make the recount automatic if the filter is changed
933              
934             PERFORMANCE NOTE 1: When you ask the AppHandle to give you a list of
935             GO::Model::Term objects, it may decide to populate this attribute when
936             building the terms in a fast and efficient way. Therefore you should
937             avoid setting the filters *after* you have created the objects
938             otherwise it will have to refetch all these values slowing things
939             down.
940              
941             PERFORMANCE NOTE 2: If you are using the SQL GO::AppHandle
942             implementation, then this call will probably involve a query to the
943             *gene_produc_count* table. If you populated the database you are using
944             yourself, make sure this table is filled otherwise this will be an
945             expensive query.
946              
947             L
948              
949             =cut
950              
951             sub n_deep_products {
952 0     0 1 0 my $self = shift;
953 0 0       0 $self->{n_deep_products} = shift if @_;
954 0 0 0     0 if (!defined($self->{n_deep_products}) ||
955             $self->{n_deep_products} eq "recount") {
956 0         0 $self->{n_deep_products} =
957             $self->apph->get_deep_product_count({term=>$self});
958             }
959             else {
960             }
961 0         0 return $self->{n_deep_products};
962             }
963              
964             # EXPERIMENTAL
965             sub n_deep_products_grouped_by_taxid {
966 0     0 0 0 my $self = shift;
967 0 0       0 $self->{n_deep_products_grouped_by_taxid} = shift if @_;
968 0 0 0     0 if (!defined($self->{n_deep_products_grouped_by_taxid}) ||
969             $self->{n_deep_products_grouped_by_taxid} eq "recount") {
970 0         0 $self->{n_deep_products_grouped_by_taxid} =
971             $self->apph->get_deep_product_count({term=>$self,group_by=>'taxid'});
972             }
973             else {
974             }
975 0         0 return $self->{n_deep_products_grouped_by_taxid};
976             }
977              
978              
979             =head2 n_products
980              
981             Usage - as n_deep_products
982             Returns -
983             Args -
984              
985             see docs for n_deep_products
986              
987             gets a count of products AT THIS LEVEL ONLY
988              
989             L
990              
991             =cut
992              
993             sub n_products {
994 0     0 1 0 my $self = shift;
995 0 0       0 $self->{n_products} = shift if @_;
996 0 0 0     0 if (!defined($self->{n_products}) ||
997             $self->{n_products} eq "recount") {
998 0         0 $self->{n_products} =
999             $self->apph->get_product_count({term=>$self});
1000             }
1001 0         0 return $self->{n_products};
1002             }
1003              
1004             sub n_unique_associations {
1005 0     0 0 0 my $self = shift;
1006 0 0       0 return scalar(keys %{$self->association_hash || {}});
  0         0  
1007             }
1008              
1009             sub get_child_terms {
1010 0     0 0 0 my $self = shift;
1011 0         0 return $self->apph->get_child_terms($self, @_);
1012             }
1013              
1014             sub get_parent_terms {
1015 0     0 0 0 my $self = shift;
1016 0         0 return $self->apph->get_parent_terms($self, @_);
1017             }
1018              
1019             =head2 loadtime
1020              
1021             Title : loadtime
1022             Usage :
1023             Function:
1024             Example :
1025             Returns : time term was loaded into datasource
1026             Args : none
1027              
1028              
1029             =cut
1030              
1031             sub loadtime{
1032 0     0 1 0 my ($self) = @_;
1033 0         0 return $self->apph->get_term_loadtime($self->acc);
1034             }
1035              
1036              
1037             sub show {
1038 0     0 0 0 my $self = shift;
1039 0         0 print $self->as_str;
1040             }
1041              
1042             sub as_str {
1043 0     0 0 0 my $self = shift;
1044 0         0 sprintf("%s (%s)", $self->name, $self->public_acc);
1045             }
1046             # --- EXPERIMENTAL METHOD ---
1047             # not yet public
1048             sub namerule {
1049 0     0 0 0 my $self = shift;
1050 0 0       0 $self->{_namerule} = shift if @_;
1051 0         0 return $self->{_namerule};
1052             }
1053              
1054             sub defrule {
1055 0     0 0 0 my $self = shift;
1056 0 0       0 $self->{_defrule} = shift if @_;
1057 0         0 return $self->{_defrule};
1058             }
1059              
1060             # --- EXPERIMENTAL METHOD ---
1061             # not yet public
1062             sub stag {
1063 0     0 0 0 my $self = shift;
1064 0 0       0 $self->{_stag} = shift if @_;
1065 0 0       0 if (!$self->{_stag}) {
1066 0         0 require "Data/Stag.pm";
1067 0         0 $self->{_stag} = Data::Stag->new(stag=>[]);
1068             }
1069 0         0 return $self->{_stag};
1070             }
1071              
1072              
1073              
1074             # pseudo-private method
1075             # available to query classes;
1076             # a template is a specification from a client to a query server
1077             # showing how much data should be transferred across.
1078             # the template is an instance of the object that is being returned;
1079             # there are a few premade templates available; eg shallow
1080             sub get_template {
1081 0     0 0 0 my $class = shift;
1082 0   0     0 my $template = shift || {};
1083 0 0       0 if ($template eq "shallow") {
1084             # shallow template, just get term attributes, no other
1085             # structs
1086 0         0 $template = GO::Model::Term->new({"name"=>"",
1087             "acc"=>-1,
1088             "definition"=>"",
1089             "n_associations"=>0,
1090             "synonym_list"=>[],
1091             "dbxref_list"=>undef});
1092             }
1093 0 0       0 if ($template =~ /no.*assoc/) {
1094             # everything bar associations
1095 0         0 $template = GO::Model::Term->new({"name"=>"",
1096             "acc"=>-1,
1097             "definition"=>1,
1098             "n_associations"=>0,
1099             "synonym_list"=>[]});
1100 0         0 $template->{dbxref_h} = 1;
1101             }
1102 0 0       0 if ($template eq "all") {
1103             # everything
1104 0         0 $template = GO::Model::Term->new({"name"=>"",
1105             "acc"=>-1,
1106             "definition"=>1,
1107             "association_list"=>[],
1108             "synonym_list"=>[]});
1109 0         0 $template->{dbxref_h} = 1;
1110             }
1111 0         0 return $template;
1112             }
1113              
1114             sub to_text {
1115 5     5 0 9 my $self = shift;
1116 5         28 my ($prefix, $escape, $obs_l, $suppress) =
1117             rearrange([qw(prefix escape obs suppress)], @_);
1118 5 50       13 my @syns = @{$self->synonym_list || [] };
  5         15  
1119 5 50       8 my @xrefs = @{$self->dbxref_list || [] };
  5         31  
1120 5 50       22 if ($suppress) {
1121 0 0       0 if (!ref($suppress)) {
1122 0         0 $suppress = {$suppress => 1};
1123             }
1124             @xrefs =
1125 0         0 grep {!$suppress->{$_->xref_dbname}} @xrefs;
  0         0  
1126             }
1127             else {
1128 0         0 @xrefs =
1129 5         12 grep {$_->xref_dbname eq 'EC'} @xrefs;
1130             }
1131             my $sub =
1132 5     0   21 sub { @_ };
  0         0  
1133 5 50       17 if ($escape) {
1134 11         26 $sub =
1135 5     11   17 sub {map{s/\,/\\\,/g;$_}@_};
  11         30  
  11         43  
1136             }
1137 0         0 my $text =
1138             sprintf("%s%s ; %s%s%s%s",
1139             &$sub($prefix || ""),
1140             &$sub($self->name),
1141             $self->public_acc,
1142             (($obs_l && @$obs_l) ?
1143 0   0     0 join ("", map {", ".$_->public_acc } @$obs_l )
1144             : ''
1145             ),
1146             ((@xrefs) ?
1147 1         7 join("", map {&$sub(" ; ".($_->as_str || ''))} @xrefs )
1148             : ''
1149             ),
1150             ((@syns) ?
1151 5 50 50     28 join("", map {&$sub(" ; synonym:$_")} @syns ):""
    50 33        
    100          
1152             ),
1153             );
1154 5         29 return $text;
1155             }
1156              
1157             sub to_ptuples {
1158 0     0 0   my $self = shift;
1159 0           my ($th, $include, $sort) =
1160             rearrange([qw(tuples include sort)], @_);
1161 0           my @s = ();
1162 0           push(@s,
1163             ["term",
1164             $self->acc,
1165             $self->name,
1166             ]);
1167 0 0         foreach my $x (@{$self->dbxref_list || []}) {
  0            
1168 0           push(@s, $x->to_ptuples(-tuples=>$th));
1169 0           push(@s, ["term_dbxref",
1170             $self->acc,
1171             $x->as_str]);
1172             }
1173 0           @s;
1174             }
1175              
1176             1;