1 """
2 BIANA: Biologic Interactions and Network Analysis
3 Copyright (C) 2009 Javier Garcia-Garcia, Emre Guney, Baldo Oliva
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 """
19
20 import sets
21 import sys
22 import ExternalEntity
23 import ExternalEntityAttribute
24
25
26 -class Ontology(ExternalEntity.ExternalEntity):
27 """
28 Class to represent a general ontology
29
30 The Ontology is an external entity itself. Each of its elemens is also an ExternalEntityObject
31
32 Each ontology as a "linkedAttribute", which is the primary attribute to represent the ontology (for example, taxID for taxonomy), and a "descriptionAttribute", which is an attribute that describes the external entity element
33 """
34
35 - def __init__(self, source_database, name, linkedAttribute, descriptionAttribute, id=None, levelAttribute=None ):
36 """
37 "source_database" is the source database id where this entity is described
38
39 "name" is the name for the ontology. It must be UNIQUE! There cannot be different ontologies with the same name
40
41 "linkedAttribute" is the attribute_identifier for the primary attribute of the ontology (for example, taxID for taxonomy ontology)
42
43 "descriptionAttribute" is the attribute_identifier for representing a human readable description of the element. This attribute is used when showing the ontolgy to users
44
45 "id" is the UNIQUE identifier in the database for this external entity (as the ontology is an External Entity)
46 """
47
48 self.name = name
49 self.trees = {}
50 self.hierarchy = {}
51 self.root_ids = sets.Set()
52 self.linked_attribute = linkedAttribute
53 self.level_attribute = levelAttribute
54 self.linked_attribute_values = {}
55 self._attrID2id = {}
56 self.description_attribute = descriptionAttribute
57 self.externalEntityObjs = {}
58 self.all_ids = sets.Set()
59
60 self.precalculated_descendants = {}
61
62 ExternalEntity.ExternalEntity.__init__(self, source_database = source_database, type="ontology", id=id)
63
64
65 - def add_element(self, ontologyElementID, isA=[], isPartOf=[], linkedAttributeValue=None):
66 """
67 Adds an element to the ontology.
68
69 "ontologyElementID": externalEntityID that identifies the externalEntityObject belonging to the ontology
70
71 "isA": list with the externalEntityIDs of the parents of this element
72
73 "isPartOf": list with the externalEntityIDs of the elements to which this element is part of
74
75 "linkedAttributeValue" is the value of the main attribute of the added external entity. Not mandatory.
76 """
77
78 self.all_ids.add(ontologyElementID)
79 self.linked_attribute_values[ontologyElementID] = linkedAttributeValue
80 self._attrID2id[linkedAttributeValue]=ontologyElementID
81 self.hierarchy.setdefault(ontologyElementID,[])
82
83 if( len(isA)==0 ):
84 self.root_ids.add(ontologyElementID)
85
86 self.trees[ontologyElementID] = (isA,isPartOf)
87
88 for current_parent in isA:
89 self.hierarchy.setdefault(current_parent,[]).append(ontologyElementID)
90
91
93 """
94 Sets the external entity objects corresponding to the elements of the ontology
95
96 "externalEntitiesDict": Dictionary with all the external entities. Key: externalEntityID. Value: externalEntity Object
97
98 Objects are only required for printing the ontology
99 """
100 self.externalEntityObjs = externalEntitiesDict
101
104
105
107 return self._attrID2id[attr_id]
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 return result
132
133
135 """
136 Gets all the descendants, using the "is_a" relation
137 """
138
139 if self.precalculated_descendants.has_key(ontologyElementID):
140 return self.precalculated_descendants[ontologyElementID]
141
142 result = sets.Set()
143
144
145 for current_descendant_id in self.hierarchy[ontologyElementID]:
146 if current_descendant_id == ontologyElementID:
147 sys.stderr.write("Ontology has a loop. An element %s [%s] is a child of itself?\n" %(current_descendant_id,self.linked_attribute_values[current_descendant_id]))
148 return result
149 else:
150 if current_descendant_id not in result:
151 result.add(current_descendant_id)
152 result.update(self.get_descendants(current_descendant_id))
153
154 else:
155 sys.stderr.write("Ontology has a loop, between %s [%s] and %s [%s]\n" %(current_descendant_id,
156 self.linked_attribute_values[current_descendant_id],
157 ontologyElementID,
158 self.linked_attribute_values[ontologyElementID]))
159
160 self.precalculated_descendants[ontologyElementID] = result
161
162 return result
163
164
166 """
167 Returns a list of tuples with the format: (linked_attr, descriptive_attr)
168 """
169
170 return [ ( self.linked_attribute_values[x],"|".join([ y.value for y in self.externalEntityObjs[x].get_attribute(self.description_attribute)]) ) for x in self.linked_attribute_values ]
171
173 """
174 Returns a list with the main attribute for all the elements in the ontology
175 """
176 return self.linked_attribute_values.values()
177
179 """
180 Returns a list with the external entity ids of all the elements in the ontology
181 """
182 return self.linked_attribute_values.keys()
183
185 """
186 Returns a boolean indicating if an external entity with this attribute is found in the ontology
187 """
188 return linkedAttributeID in self.linked_attribute_values
189
191 """
192 Returns a list with the parents of the element with this externalEntityID (using the relation is_a)
193 """
194 return self.trees[elementID][0]
195
197 """
198 Returns a list with the parents of the element with this externalEntityID (using the relation is_part_of)
199 """
200 return self.trees[elementID][1]
201
202
204 """
205 Prints recursively in stdout a tree representing the ontology, using the external entity id.
206
207 Only for testing purposes
208 """
209
210 for x in xrange(depth):
211 outmethod("\t")
212
213 outmethod("%s [%s]" %('|'.join([ x.value for x in self.externalEntityObjs[id].get_attribute(self.description_attribute) ]),self.linked_attribute_values[id]))
214 outmethod("\n")
215 depth = depth+1
216 for current_descendant_id in self.hierarchy[id]:
217 self._recursive_tree_print(current_descendant_id, outmethod, depth)
218
219
221 """
222 Prints recursively in stdout a tree representing the ontology, using the external entity id.
223
224 Only for testing purposes
225 """
226
227
228
229 for x in self.root_ids:
230 self._recursive_tree_print( id = x,
231 depth = 0,
232 outmethod = outmethod )
233
234
236
237 nodes_xml = [ "<node ontologyNodeID=\"%s\" id=\"%s\">" %(self.linked_attribute_values[id],
238 '|'.join([ x.value for x in self.externalEntityObjs[id].get_attribute(self.description_attribute) ])) ]
239
240 for current_descendant_id in self.hierarchy[id]:
241 nodes_xml.extend(self._recursive_tree_xml(current_descendant_id))
242
243 nodes_xml.append("</node>")
244 return nodes_xml
245
246
248 """
249 Returns a String with an XML representation of the ontology
250
251 To execute this method, is necessary to load in the ontology all the external Entity Objects
252 """
253
254 nodes_xml = ["<ontology name=\"%s\">" %self.name]
255
256 for x in self.root_ids:
257 nodes_xml.extend(self._recursive_tree_xml( id = x) )
258
259 nodes_xml.append("</ontology>")
260
261 return "\n".join(nodes_xml)
262
263
265 """
266 Helper function to reach leafs traversing the tree
267 """
268 if len(self.hierarchy[id]) == 0:
269
270 nodes = [ ", ".join([ x.value for x in self.externalEntityObjs[id].get_attribute(self.description_attribute) ]) ]
271 else:
272 nodes = []
273
274 for current_descendant_id in self.hierarchy[id]:
275 nodes.extend(self._traverse_tree_for_leafs(current_descendant_id))
276
277 return nodes
278
279
281 """
282 Returns a list of leafs in the ontology tree
283 To execute this method, is necessary to load in the ontology all the external Entity Objects
284 """
285 leaf_nodes = []
286
287 for x in self.root_ids:
288 leaf_nodes.extend(self._traverse_tree_for_leafs( id = x) )
289
290 return leaf_nodes
291