File Coverage

blib/lib/GOBO/ClassExpression.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             GOBO::ClassExpression
4              
5             =head1 SYNOPSIS
6              
7             my $xp = GOBO::ClassExpression->parse_idexpr('GO:0005737^part_of(CL:0000023)');
8              
9             =head1 DESCRIPTION
10              
11             A class expression is an GOBO::ClassNode whose members are identified
12             by a boolean or relational expression. For example, the class 'nuclei
13             of cardiac cells' is expressed as the intersection (an
14             GOBO::ClassExpression::Intersection) between the set 'nucleus' (an
15             GOBO::TermNode) and the set of all things that stand in the part_of
16             relation to 'class node' (a GOBO::ClassExpression::RelationalExpression).
17              
18             Simple ontologies do not include class expressions. They can often be
19             ignored for many purposes.
20              
21             An GOBO::TermNode can be formally and logically defined by stating
22             equivalence to a GOBO::ClassExpression
23              
24             [Term]
25             id: GO:new
26             name: oocyte cytoplasm
27             intersection_of: GO:0005737 ! cytoplasm
28             intersection_of: part_of CL:0000023 ! oocyte
29              
30             This can also be thought of as necessary and sufficient conditions for
31             membership of a class.
32              
33             On parsing the above using GOBO::Parsers::OBOParer, the following should hold
34              
35             $t->label eq 'oocyte cytoplasm';
36             $t->logical_definition->isa('GOBO::ClassExpression');
37              
38             =head2 Example files
39              
40             The xp version of SO includes intersection-based class expressions.
41             See http://sequenceontology.org
42              
43             The extended version of GO will soon include these for regulation terms. See also
44              
45             http://wiki.geneontology.org/index.php/Category:Cross_Products
46              
47             =head2 Mapping to OWL
48              
49             The notion of ClassExpression here is largely borrowed from OWL and
50             Description Logics. See
51              
52             http://www.w3.org/TR/2008/WD-owl2-syntax-20081202/#Class_Expressions
53              
54             Note that not everything in OWL is expressable in OBO format or the
55             GOBO model.
56              
57             Conversely, this model and OBO format can express things not in OWL,
58             such as relation expressions involving intersection and union.
59              
60             =head2 Mapping to the GO Database schema
61              
62             Currently the GO database is not able to store the full range of class
63             expressions. It can only store logical definitions to
64             GOBO::ClassExpression::Intersection objects. See the POD docs for this
65             class for details.
66              
67             =head2 Mapping to the Chado schema
68              
69             Currently the GO database is not able to store the full range of class
70             expressions. It can only store logical definitions to
71             GOBO::ClassExpression::Intersection objects. See the POD docs for this
72             class for details.
73              
74             =cut
75              
76             package GOBO::ClassExpression;
77 1     1   7564 use Moose;
  0            
  0            
78             use strict;
79             extends 'GOBO::ClassNode';
80             use GOBO::ClassExpression::RelationalExpression;
81             use GOBO::ClassExpression::Intersection;
82             use GOBO::ClassExpression::Union;
83              
84             # abstract class - no accessors
85              
86             # utility methods follow...
87              
88             =head2 ID Expressions
89              
90             A class expression can be expressed as an ID expression. See:
91              
92             http://www.geneontology.org/GO.format.obo-1_3.shtml#S.1.6
93              
94             For example:
95             GO:0005737^part_of(CL:0000023)
96              
97             The set of all cytoplasm (GO:0005737) instances that are part_of some oocyte (CL:0000023)
98              
99              
100             =head3 parse_idexpr
101              
102             Generates a GOBO::ClassExpression based on an ID expression string
103              
104             Usage - $xp = GOBO::ClassExpression->parse_idexpr('GO:0005737^part_of(CL:0000023)');
105              
106             The grammar for ID expressions is:
107              
108             GOBO::ClassExpression = GOBO::BooleanExpression | GOBO::RelationalExpression | GOBO::TermNode
109             GOBO::BooleanExpression = GOBO::Intersection | GOBO::Union
110             GOBO::Intersection = GOBO::ClassExpression '^' GOBO::ClassExpression
111             GOBO::Union = GOBO::ClassExpression '|' GOBO::ClassExpression
112             GOBO::RelationalExpression = GOBO::RelationNode '(' GOBO::ClassExpression ')'
113              
114              
115             =cut
116              
117             sub parse_idexpr {
118             my $self = shift;
119             my $g = shift;
120             my $expr = shift;
121             return unless $expr;
122             #print STDERR "Parsing: $expr\n";
123             my @toks = split(/([\(\)\^\|])/,$expr);
124             @toks = grep {$_} @toks;
125             my $x = _parse_idexpr_toks($g,\@toks);
126             $x->normalize if $x->can('normalize');
127             return $x;
128             }
129              
130             sub _parse_idexpr_toks {
131             my $g = shift;
132             my $toks = shift;
133             #printf STDERR "Parsing tokens: %s\n", join(',',@$toks);
134             if (!@$toks) {
135             return;
136             }
137             my $tok = shift @$toks;
138             while (@$toks && !$tok) {
139             # process null tokens
140             $tok = shift @$toks;
141             }
142             #print STDERR "tok: $tok;; rest=@$toks\n";
143              
144             # RETURN: atom
145             if (!@$toks) {
146             #printf STDERR "atom: $tok\n";
147             #return $tok;
148             return $g->noderef($tok);
149             }
150             my $this;
151             if ($toks->[0] eq '(') {
152             # relational expression
153             shift @$toks;
154             #printf STDERR "parsing relational expr from @$toks\n";
155             my $filler = _parse_idexpr_toks($g,$toks);
156             $this = new GOBO::ClassExpression::RelationalExpression(relation=>$tok,target=>$filler);
157             #printf STDERR "relexpr $tok $filler ==> $this ;; remaining = @$toks\n";
158             }
159             else {
160             #printf STDERR "atom: $tok\n";
161             $this = $g->noderef($tok);
162             }
163              
164             if (@$toks) {
165             my $combo;
166             my $op = shift @$toks;
167             #printf STDERR "op: '$op';; rest=@$toks\n";
168              
169             if ($op eq ')') {
170             # TODO: check balance
171             #printf STDERR "end-brace: $this\n";
172             return $this;
173             }
174              
175             my $next = _parse_idexpr_toks($g,$toks);
176             if ($op eq '^') {
177             #printf STDERR "intersection: $this $next\n";
178             $combo = new GOBO::ClassExpression::Intersection(arguments=>[$this,$next]);
179             }
180             elsif ($op eq '|') {
181             #printf STDERR "union: $this $next\n";
182             $combo = new GOBO::ClassExpression::Union(arguments=>[$this,$next]);
183             }
184             else {
185             }
186             return $combo; # TODO -- DNF
187             }
188             #printf STDERR "return: $this\n";
189             return $this;
190             }
191              
192             =head2 normalize
193              
194             A or (B or C) ==> A or B or C
195             A and (B and C) ==> A and B and C
196              
197              
198             =cut
199              
200             sub normalize {
201             my $self = shift;
202             return;
203             }
204              
205             1;
206