├── README.md
├── object_onto.owl
└── owlready2_crash.ipynb
/README.md:
--------------------------------------------------------------------------------
1 | # onto_python
2 | An Introductory Jupyter Notebook to Manipulate Ontologies with Owlready2
3 |
4 | ## Requirements
5 | - owlready2
6 | - graphviz
7 |
8 | ## Additional Note
9 | Nothing for now.
10 |
--------------------------------------------------------------------------------
/object_onto.owl:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
--------------------------------------------------------------------------------
/owlready2_crash.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Owlready2 Crash Notebook\n",
8 | "Owlready2 is a Python package to construct and manipulate ontology under Python syntax, while Protege is a Java software to construct and manipulate ontologies with various plugins.\n",
9 | "\n",
10 | "This is a notebook to manipulate owl files pre-constructed in Protege, and to utilize some APIs from Owlready2 for information retrieval."
11 | ]
12 | },
13 | {
14 | "cell_type": "code",
15 | "execution_count": 1,
16 | "metadata": {},
17 | "outputs": [],
18 | "source": [
19 | "# All necessary imports\n",
20 | "import os\n",
21 | "import difflib\n",
22 | "import graphviz\n",
23 | "import owlready2 as owl"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "## Part 1: Load a local *.owl file\n",
31 | "Owlready2 natively supports RDF/XML format ontology file. \n",
32 | "\n",
33 | "Refer to \"https://pythonhosted.org/Owlready2/onto.html\" for more details in ontology manipulation with Owlready2."
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 2,
39 | "metadata": {},
40 | "outputs": [
41 | {
42 | "name": "stdout",
43 | "output_type": "stream",
44 | "text": [
45 | "Loaded owl file at: file:///mnt/c/Users/Zone/Desktop/Workspace/onto_python/object_onto.owl\n"
46 | ]
47 | }
48 | ],
49 | "source": [
50 | "# Here, we load a local ontology file, created earlier in Protege.\n",
51 | "# A prefix of \"file://\" is needed.\n",
52 | "onto_path = 'file://' + os.path.abspath('object_onto.owl')\n",
53 | "onto = owl.get_ontology(onto_path).load()\n",
54 | "print('Loaded owl file at:', onto_path)"
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "metadata": {},
60 | "source": [
61 | "## Part 2: Invoke a reasoner\n",
62 | "Reasoners are useful when checking the consistency of an ontology or deducing logical facts. Owlready2 includes a modified version of the HermiT reasoner.\n",
63 | "\n",
64 | "Refer to \"https://pythonhosted.org/Owlready2/reasoning.html\" for more details in reasoning."
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": 3,
70 | "metadata": {},
71 | "outputs": [
72 | {
73 | "name": "stderr",
74 | "output_type": "stream",
75 | "text": [
76 | "* Owlready2 * Running HermiT...\n",
77 | " java -Xmx2000M -cp /usr/local/lib/python3.6/dist-packages/owlready2/hermit:/usr/local/lib/python3.6/dist-packages/owlready2/hermit/HermiT.jar org.semanticweb.HermiT.cli.CommandLine -c -O -D -I file:////tmp/tmp8udl3gcv\n",
78 | "* Owlready2 * HermiT took 0.6661009788513184 seconds\n",
79 | "* Owlready * Reparenting object_onto.hasMaterial: {object_onto.topClassProperty, owl.FunctionalProperty, owl.ObjectProperty} => {object_onto.topClassProperty, owl.FunctionalProperty}\n",
80 | "* Owlready * Reparenting object_onto.canWithstandTemperature: {object_onto.topClassProperty, owl.ObjectProperty} => {object_onto.topClassProperty}\n",
81 | "* Owlready * Reparenting object_onto.canGrasp: {object_onto.topActionRelation, owl.ObjectProperty} => {object_onto.topActionRelation}\n",
82 | "* Owlready * (NB: only changes on entities loaded in Python are shown, other changes are done but not listed)\n"
83 | ]
84 | }
85 | ],
86 | "source": [
87 | "# Invoke reasoner\n",
88 | "# NOTE: New facts will be appended into the current onto\n",
89 | "owl.sync_reasoner()"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {},
95 | "source": [
96 | "## Part 3: Some basic APIs exploration\n",
97 | "Some APIs that are useful to retrieve information in classes, object properties, etc."
98 | ]
99 | },
100 | {
101 | "cell_type": "markdown",
102 | "metadata": {},
103 | "source": [
104 | "Reference: https://pythonhosted.org/Owlready/class.html"
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "execution_count": 4,
110 | "metadata": {
111 | "scrolled": false
112 | },
113 | "outputs": [
114 | {
115 | "name": "stdout",
116 | "output_type": "stream",
117 | "text": [
118 | "All classes\n",
119 | "--------------------\n",
120 | "object_onto.Operator\n",
121 | "object_onto.Container\n",
122 | "object_onto.MaterialPartition\n",
123 | "object_onto.TemperatureValuePartition\n",
124 | "object_onto.Bottle\n",
125 | "object_onto.Cold\n",
126 | "object_onto.DomainThing\n",
127 | "object_onto.Partition\n",
128 | "object_onto.Glass\n",
129 | "object_onto.Hot\n",
130 | "object_onto.Mild\n",
131 | "object_onto.Plastic\n",
132 | "object_onto.GlassBottle\n",
133 | "object_onto.Human\n",
134 | "object_onto.PlasticBottle\n",
135 | "\n",
136 | "object_onto.PlasticBottle\n",
137 | "{'namespace': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': 324, '_name': 'PlasticBottle', 'is_a': [object_onto.Bottle, object_onto.isGraspableBy.some(object_onto.Human)], '_equivalent_to': None, '__module__': 'owlready2.entity', '__doc__': None}\n",
138 | "\n",
139 | "name(string): PlasticBottle\n",
140 | "module_type: owlready2.entity\n",
141 | "equivalent_to: [object_onto.Bottle & object_onto.hasMaterial.some(object_onto.Plastic)]\n",
142 | "is_a: [object_onto.Bottle, object_onto.isGraspableBy.some(object_onto.Human)]\n"
143 | ]
144 | }
145 | ],
146 | "source": [
147 | "# Manipulation over Classes\n",
148 | "# --------------------\n",
149 | "# Retrieve all classes inside onto\n",
150 | "classes = list(onto.classes())\n",
151 | "print('All classes\\n'+'-'*20)\n",
152 | "for x in classes: \n",
153 | " print(x)\n",
154 | "print()\n",
155 | " \n",
156 | "# Get a random class in collection\n",
157 | "# Access dict to retrieve more info\n",
158 | "cls = classes[-1]\n",
159 | "print(cls)\n",
160 | "print(cls.__dict__)\n",
161 | "print()\n",
162 | "\n",
163 | "# Some useful APIs here\n",
164 | "print('name(string):', cls.name)\n",
165 | "print('module_type:', cls.__module__)\n",
166 | "print('equivalent_to:', cls.equivalent_to)\n",
167 | "print('is_a:', cls.is_a)"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 5,
173 | "metadata": {},
174 | "outputs": [
175 | {
176 | "name": "stdout",
177 | "output_type": "stream",
178 | "text": [
179 | "\n",
180 | "All object properties\n",
181 | "--------------------\n",
182 | "object_onto.canGrasp\n",
183 | "object_onto.topActionRelation\n",
184 | "object_onto.isGraspableBy\n",
185 | "object_onto.canWithstandTemperature\n",
186 | "object_onto.topClassProperty\n",
187 | "object_onto.hasMaterial\n",
188 | "\n",
189 | "object_onto.hasMaterial\n",
190 | "{'namespace': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'is_a': [owl.FunctionalProperty, object_onto.topClassProperty], 'storid': 312, '_name': 'hasMaterial', '_equivalent_to': [], '__module__': 'owlready2.entity', '__doc__': None, '_domain': None, '_range': None, '_property_chain': None, '_inverse_property': None, '_python_name': 'hasMaterial', '_class_property_type': [], '_class_property_some': True, '_class_property_only': False, '_class_property_relation': False, '_inverse_storid': 0}\n",
191 | "\n",
192 | "name(string): hasMaterial\n",
193 | "module_type: owlready2.entity\n",
194 | "is_a: [owl.FunctionalProperty, object_onto.topClassProperty]\n",
195 | "\n",
196 | "class_property_some: True\n",
197 | "class_property_only: False\n",
198 | "class_property_relation: False\n"
199 | ]
200 | }
201 | ],
202 | "source": [
203 | "# Retrieve all object properties\n",
204 | "properties = list(onto.object_properties())\n",
205 | "print('\\nAll object properties\\n'+'-'*20)\n",
206 | "for x in properties: \n",
207 | " print(x)\n",
208 | "print()\n",
209 | " \n",
210 | "rel = properties[-1]\n",
211 | "print(rel)\n",
212 | "print(rel.__dict__)\n",
213 | "print()\n",
214 | "\n",
215 | "# Some useful APIs here\n",
216 | "print('name(string):', rel.name)\n",
217 | "print('module_type:', rel.__module__)\n",
218 | "print('is_a:', rel.is_a)\n",
219 | "print()\n",
220 | "\n",
221 | "\"\"\"\n",
222 | "The .class_property_type attribute of Properties allows to indicate how to handle class properties:\n",
223 | " “some”: handle class properties as existential restrictions (i.e. SOME restrictions and VALUES restrictions).\n",
224 | " “only”: handle class properties as universal restrictions (i.e. ONLY restrictions).\n",
225 | " “relation”: handle class properties as relations (i.e. simple RDF triple, as in Linked Data).\n",
226 | "\"\"\"\n",
227 | "print('class_property_some:', rel._class_property_some)\n",
228 | "print('class_property_only:', rel._class_property_only)\n",
229 | "print('class_property_relation:', rel._class_property_relation)"
230 | ]
231 | },
232 | {
233 | "cell_type": "code",
234 | "execution_count": 6,
235 | "metadata": {},
236 | "outputs": [
237 | {
238 | "name": "stdout",
239 | "output_type": "stream",
240 | "text": [
241 | "\n",
242 | "All disjoints\n",
243 | "--------------------\n",
244 | "AllDisjoint([object_onto.Cold, object_onto.Hot, object_onto.Mild])\n",
245 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': -26, '_list_bnode': -27, 'entities': [object_onto.Cold, object_onto.Hot, object_onto.Mild]}\n",
246 | "\n",
247 | "AllDisjoint([object_onto.Container, object_onto.Operator])\n",
248 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': (307, 88, 306), 'entities': [object_onto.Container, object_onto.Operator]}\n",
249 | "\n",
250 | "AllDisjoint([object_onto.DomainThing, object_onto.Partition])\n",
251 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': (316, 88, 317), 'entities': [object_onto.DomainThing, object_onto.Partition]}\n",
252 | "\n",
253 | "AllDisjoint([object_onto.Glass, object_onto.Plastic])\n",
254 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': (318, 88, 321), 'entities': [object_onto.Glass, object_onto.Plastic]}\n",
255 | "\n",
256 | "AllDisjoint([object_onto.GlassBottle, object_onto.PlasticBottle])\n",
257 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': (322, 88, 324), 'entities': [object_onto.GlassBottle, object_onto.PlasticBottle]}\n",
258 | "\n",
259 | "AllDisjoint([object_onto.MaterialPartition, object_onto.TemperatureValuePartition])\n",
260 | "{'ontology': get_ontology(\"http://www.semanticweb.org/zone/ontologies/2019/11/object_onto#\"), 'storid': (310, 88, 311), 'entities': [object_onto.MaterialPartition, object_onto.TemperatureValuePartition]}\n",
261 | "\n"
262 | ]
263 | }
264 | ],
265 | "source": [
266 | "# Retrieve all disjoint sets\n",
267 | "disjoints = list(onto.disjoints())\n",
268 | "print('\\nAll disjoints\\n'+'-'*20)\n",
269 | "for x in disjoints: \n",
270 | " # NOTE: Retreive all disjoint individual entity objects, stored in the dict\n",
271 | " print(x)\n",
272 | " print(x.__dict__)\n",
273 | " print()"
274 | ]
275 | },
276 | {
277 | "cell_type": "markdown",
278 | "metadata": {},
279 | "source": [
280 | "## Part 4: Higher-level API exploration\n",
281 | "Some helper functions to retrieve useful info given an entity to search for. This is a mimic of ontograf plugin feature from Protege."
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": 7,
287 | "metadata": {},
288 | "outputs": [],
289 | "source": [
290 | "# Default type2str from owlready2\n",
291 | "type2str_restriction = owl.class_construct._restriction_type_2_label\n",
292 | "\n",
293 | "def _process_entity(entity, job_name, orig_entity, graph):\n",
294 | " \"\"\"Helper: Append entity for the specified job.\n",
295 | " \"\"\"\n",
296 | " edge = (orig_entity, job_name, entity)\n",
297 | " if edge not in graph:\n",
298 | " graph.append(edge)\n",
299 | " return graph\n",
300 | "\n",
301 | "def _process_restriction(restriction, entity, graph):\n",
302 | " \"\"\"Helper: Append restriction.\n",
303 | " \"\"\"\n",
304 | " assert restriction.__module__ == 'owlready2.class_construct'\n",
305 | " \n",
306 | " # Grab object_property --type--> value\n",
307 | " object_property, value = restriction.property, restriction.value\n",
308 | " restriction_type = type2str_restriction[restriction.type]\n",
309 | " \n",
310 | " # Separate logical or for 'only'\n",
311 | " if restriction_type == 'only':\n",
312 | " for or_value in value.Classes:\n",
313 | " edge = (entity, '{},{}'.format(object_property.name, restriction_type), or_value)\n",
314 | " if edge not in graph:\n",
315 | " graph.append(edge)\n",
316 | " \n",
317 | " # No more processing for 'some'\n",
318 | " else:\n",
319 | " edge = (entity, '{},{}'.format(object_property.name, restriction_type), value)\n",
320 | " if edge not in graph:\n",
321 | " graph.append(edge)\n",
322 | " \n",
323 | " return graph\n",
324 | "\n",
325 | "def _process_subclasses(entity, graph):\n",
326 | " \"\"\"Helper: Append subclasses.\n",
327 | " \"\"\"\n",
328 | " # Safely grab all subclasses\n",
329 | " try:\n",
330 | " subclses = list(entity.subclasses())\n",
331 | " except:\n",
332 | " subclses = []\n",
333 | "\n",
334 | " for subcls in subclses:\n",
335 | " if (entity, 'has_subclass', subcls) not in graph:\n",
336 | " graph.append((entity, 'has_subclass', subcls))\n",
337 | " if (subcls, 'subclass_of', entity) not in graph:\n",
338 | " graph.append((subcls, 'subclass_of', entity))\n",
339 | "\n",
340 | " return graph\n",
341 | "\n",
342 | "def _populate_subclass_rel(graph):\n",
343 | " \"\"\"Helper: Ensure 'subclass_of' and 'has_subclass' always appear in pairs.\n",
344 | " \"\"\"\n",
345 | " for edge in graph:\n",
346 | " if edge[1] == 'subclass_of' and (edge[2], 'has_subclass', edge[0]) not in graph:\n",
347 | " graph.append((edge[2], 'has_subclass', edge[0]))\n",
348 | " elif edge[1] == 'has_subclass' and (edge[2], 'subclass_of', edge[0]) not in graph:\n",
349 | " graph.append((edge[2], 'subclass_of', edge[0]))\n",
350 | " return graph\n",
351 | "\n",
352 | "def _process_instances(entity, graph):\n",
353 | " \"\"\"Helper: Append individuals.\n",
354 | " \"\"\"\n",
355 | " # Safely grab all individuals\n",
356 | " try:\n",
357 | " instances = entity.instances()\n",
358 | " except:\n",
359 | " instances = []\n",
360 | "\n",
361 | " for instance in instances:\n",
362 | " if instance.is_a[0] == entity:\n",
363 | " if (entity, 'has_individual', instance) not in graph:\n",
364 | " graph.append((entity, 'has_individual', instance))\n",
365 | "\n",
366 | " return graph\n",
367 | "\n",
368 | "def generate_knowledge_graph(entity):\n",
369 | " \"\"\"Helper function to grab entity-relation from onto and \n",
370 | " return as knowledge graph.\n",
371 | " \"\"\"\n",
372 | " graph = []\n",
373 | "\n",
374 | " # Part 1: Append subclasses\n",
375 | " graph = _process_subclasses(entity, graph)\n",
376 | "\n",
377 | " # Part 2: Collect equivalent_to\n",
378 | " try:\n",
379 | " equivalent_to_list = entity.INDIRECT_equivalent_to # NOTE: Weird bug here, have to use INDIRECT\n",
380 | " except:\n",
381 | " equivalent_to_list = []\n",
382 | " for et in equivalent_to_list:\n",
383 | " # equivalent_to AND objects:\n",
384 | " if et.__module__ == 'owlready2.class_construct':\n",
385 | " for x in et.Classes:\n",
386 | " # For class restriction, retrieve relevant infos inside\n",
387 | " if x.__module__ == 'owlready2.class_construct':\n",
388 | " graph = _process_restriction(x, entity, graph)\n",
389 | " \n",
390 | " # Part 3: Look into is_a\n",
391 | " is_a_list = entity.is_a\n",
392 | " for x in is_a_list:\n",
393 | " # Entity: is_a indicates subclasses\n",
394 | " if x.__module__ == 'owlready2.entity':\n",
395 | " graph = _process_entity(x, 'subclass_of', entity, graph)\n",
396 | " \n",
397 | " # Restriction\n",
398 | " elif x.__module__ == 'owlready2.class_construct':\n",
399 | " graph = _process_restriction(x, entity, graph)\n",
400 | " \n",
401 | " # Part 4: Look into instances\n",
402 | " graph = _process_instances(entity, graph)\n",
403 | " \n",
404 | " # Part 5: Some additional filters\n",
405 | " graph = _populate_subclass_rel(graph)\n",
406 | " \n",
407 | " return graph\n",
408 | "\n",
409 | "def _filter_graph(graph, onto):\n",
410 | " \"\"\"Helper: filter graph from some ill-logical entries.\n",
411 | " \"\"\"\n",
412 | " filtered_graph = []\n",
413 | " # Grab all individuals\n",
414 | " individuals = list(onto.individuals())\n",
415 | "\n",
416 | " for edge in graph:\n",
417 | " passed = True\n",
418 | " # Ill-logical individuals\n",
419 | " if edge[0] in individuals:\n",
420 | " passed = False\n",
421 | " if passed:\n",
422 | " filtered_graph.append(edge)\n",
423 | " return filtered_graph\n",
424 | "\n",
425 | "def keyword_search_onto(keyword, onto):\n",
426 | " \"\"\"Search and index key entity from onto given keyword.\n",
427 | " \"\"\"\n",
428 | " classes = list(onto.classes())\n",
429 | " classes_str = [x.name for x in classes]\n",
430 | " all_res = difflib.get_close_matches(keyword, classes_str)\n",
431 | " # Only grab the most probable search keyword\n",
432 | " if len(all_res) > 0:\n",
433 | " res = all_res[0]\n",
434 | " return classes[classes_str.index(res)]\n",
435 | " else:\n",
436 | " return None\n",
437 | "\n",
438 | "def _to_string(graph):\n",
439 | " \"\"\"Helper: Convert everything collected inside graph list into\n",
440 | " string.\n",
441 | " \"\"\"\n",
442 | " for i in range(len(graph)):\n",
443 | " edge = list(graph[i])\n",
444 | " for k in range(len(edge)):\n",
445 | " if type(edge[k]) is not str:\n",
446 | " edge[k] = edge[k].name\n",
447 | " edge[k] = edge[k].replace(',', ', ')\n",
448 | " graph[i] = (edge[0], edge[1], edge[2])\n",
449 | " return graph\n",
450 | "\n",
451 | "def ontograf_simple(orig_entity, onto):\n",
452 | " \"\"\"Interface func to search and retrieve infor for a given\n",
453 | " entity inside onto.\n",
454 | " \"\"\"\n",
455 | " if orig_entity is None:\n",
456 | " return []\n",
457 | " \n",
458 | " # Initial graph search\n",
459 | " graph = generate_knowledge_graph(orig_entity)\n",
460 | " \n",
461 | " # Prep for other key entities given the initial graph\n",
462 | " entities = []\n",
463 | " for edge in graph:\n",
464 | " entities.append(edge[2])\n",
465 | "\n",
466 | " # 1st-level of filters, append more info from children and parent nodes\n",
467 | " for entity in entities:\n",
468 | " sub_graph = generate_knowledge_graph(entity)\n",
469 | " for edge in sub_graph:\n",
470 | " if edge[2] == orig_entity:\n",
471 | " if (entity, edge[1], orig_entity) not in graph and entity != orig_entity:\n",
472 | " graph.append((entity, edge[1], orig_entity))\n",
473 | "\n",
474 | " # 2nd-level of filters, filter some ill-logical nodes\n",
475 | " graph = _filter_graph(graph, onto)\n",
476 | "\n",
477 | " # Convert everything inside graph into str\n",
478 | " graph = _to_string(graph)\n",
479 | "\n",
480 | " return graph"
481 | ]
482 | },
483 | {
484 | "cell_type": "code",
485 | "execution_count": 8,
486 | "metadata": {},
487 | "outputs": [],
488 | "source": [
489 | "def convert_to_graphviz(graph, name='KG'):\n",
490 | " \"\"\"Helper function to convert edge graph into graphviz.Digraph.\n",
491 | " \"\"\"\n",
492 | " e = graphviz.Digraph(name)\n",
493 | " e.attr('node', shape='box')\n",
494 | " for edge in graph:\n",
495 | " e.attr('node', shape='box')\n",
496 | " e.node(edge[0])\n",
497 | " e.node(edge[2])\n",
498 | " e.edge(edge[0], edge[2], label=edge[1])\n",
499 | " return e"
500 | ]
501 | },
502 | {
503 | "cell_type": "code",
504 | "execution_count": 9,
505 | "metadata": {},
506 | "outputs": [
507 | {
508 | "name": "stdout",
509 | "output_type": "stream",
510 | "text": [
511 | "--------------------\n",
512 | "True object_onto.PlasticBottle\n",
513 | "[('PlasticBottle', 'hasMaterial, some', 'Plastic'), ('PlasticBottle', 'subclass_of', 'Bottle'), ('PlasticBottle', 'isGraspableBy, some', 'Human'), ('PlasticBottle', 'has_individual', 'PlasticBottle1'), ('PlasticBottle', 'has_individual', 'PlasticBottle2'), ('Bottle', 'has_subclass', 'PlasticBottle'), ('Human', 'canGrasp, some', 'PlasticBottle')]\n"
514 | ]
515 | },
516 | {
517 | "data": {
518 | "image/svg+xml": [
519 | "\n",
520 | "\n",
522 | "\n",
524 | "\n",
525 | "\n"
617 | ],
618 | "text/plain": [
619 | ""
620 | ]
621 | },
622 | "execution_count": 9,
623 | "metadata": {},
624 | "output_type": "execute_result"
625 | }
626 | ],
627 | "source": [
628 | "print('-'*20)\n",
629 | "entity = keyword_search_onto('plasticbottle', onto)\n",
630 | "print(entity == onto.PlasticBottle, entity)\n",
631 | "kg = ontograf_simple(entity, onto)\n",
632 | "print(kg)\n",
633 | "convert_to_graphviz(kg)"
634 | ]
635 | },
636 | {
637 | "cell_type": "code",
638 | "execution_count": 10,
639 | "metadata": {},
640 | "outputs": [
641 | {
642 | "name": "stdout",
643 | "output_type": "stream",
644 | "text": [
645 | "--------------------\n",
646 | "False None\n",
647 | "[]\n"
648 | ]
649 | },
650 | {
651 | "data": {
652 | "image/svg+xml": [
653 | "\n",
654 | "\n",
656 | "\n",
658 | "\n",
659 | "\n"
666 | ],
667 | "text/plain": [
668 | ""
669 | ]
670 | },
671 | "execution_count": 10,
672 | "metadata": {},
673 | "output_type": "execute_result"
674 | }
675 | ],
676 | "source": [
677 | "print('-'*20)\n",
678 | "entity = keyword_search_onto('papercup', onto)\n",
679 | "print(entity == onto.GlassBottle, entity)\n",
680 | "kg = ontograf_simple(entity, onto)\n",
681 | "print(kg)\n",
682 | "convert_to_graphviz(kg)"
683 | ]
684 | },
685 | {
686 | "cell_type": "code",
687 | "execution_count": 11,
688 | "metadata": {},
689 | "outputs": [
690 | {
691 | "name": "stdout",
692 | "output_type": "stream",
693 | "text": [
694 | "--------------------\n",
695 | "True object_onto.Bottle\n",
696 | "[('Bottle', 'has_subclass', 'GlassBottle'), ('GlassBottle', 'subclass_of', 'Bottle'), ('Bottle', 'has_subclass', 'PlasticBottle'), ('PlasticBottle', 'subclass_of', 'Bottle'), ('Bottle', 'subclass_of', 'Container'), ('Container', 'has_subclass', 'Bottle')]\n"
697 | ]
698 | },
699 | {
700 | "data": {
701 | "image/svg+xml": [
702 | "\n",
703 | "\n",
705 | "\n",
707 | "\n",
708 | "\n"
781 | ],
782 | "text/plain": [
783 | ""
784 | ]
785 | },
786 | "execution_count": 11,
787 | "metadata": {},
788 | "output_type": "execute_result"
789 | }
790 | ],
791 | "source": [
792 | "print('-'*20)\n",
793 | "entity = keyword_search_onto('bottle', onto)\n",
794 | "print(entity == onto.Bottle, entity)\n",
795 | "kg = ontograf_simple(entity, onto)\n",
796 | "print(kg)\n",
797 | "convert_to_graphviz(kg)"
798 | ]
799 | },
800 | {
801 | "cell_type": "code",
802 | "execution_count": 12,
803 | "metadata": {},
804 | "outputs": [
805 | {
806 | "name": "stdout",
807 | "output_type": "stream",
808 | "text": [
809 | "--------------------\n",
810 | "True object_onto.Container\n",
811 | "[('Container', 'has_subclass', 'Bottle'), ('Bottle', 'subclass_of', 'Container'), ('Container', 'subclass_of', 'DomainThing'), ('DomainThing', 'has_subclass', 'Container')]\n"
812 | ]
813 | },
814 | {
815 | "data": {
816 | "image/svg+xml": [
817 | "\n",
818 | "\n",
820 | "\n",
822 | "\n",
823 | "\n"
876 | ],
877 | "text/plain": [
878 | ""
879 | ]
880 | },
881 | "execution_count": 12,
882 | "metadata": {},
883 | "output_type": "execute_result"
884 | }
885 | ],
886 | "source": [
887 | "print('-'*20)\n",
888 | "entity = keyword_search_onto('container', onto)\n",
889 | "print(entity == onto.Container, entity)\n",
890 | "kg = ontograf_simple(entity, onto)\n",
891 | "print(kg)\n",
892 | "convert_to_graphviz(kg)"
893 | ]
894 | },
895 | {
896 | "cell_type": "code",
897 | "execution_count": 13,
898 | "metadata": {},
899 | "outputs": [
900 | {
901 | "name": "stdout",
902 | "output_type": "stream",
903 | "text": [
904 | "--------------------\n",
905 | "True object_onto.Plastic\n",
906 | "[('Plastic', 'subclass_of', 'MaterialPartition'), ('Plastic', 'canWithstandTemperature, some', 'Cold'), ('Plastic', 'canWithstandTemperature, some', 'Mild'), ('MaterialPartition', 'has_subclass', 'Plastic')]\n"
907 | ]
908 | },
909 | {
910 | "data": {
911 | "image/svg+xml": [
912 | "\n",
913 | "\n",
915 | "\n",
917 | "\n",
918 | "\n"
977 | ],
978 | "text/plain": [
979 | ""
980 | ]
981 | },
982 | "execution_count": 13,
983 | "metadata": {},
984 | "output_type": "execute_result"
985 | }
986 | ],
987 | "source": [
988 | "print('-'*20)\n",
989 | "entity = keyword_search_onto('plastic', onto)\n",
990 | "print(entity == onto.Plastic, entity)\n",
991 | "kg = ontograf_simple(entity, onto)\n",
992 | "print(kg)\n",
993 | "convert_to_graphviz(kg)"
994 | ]
995 | },
996 | {
997 | "cell_type": "code",
998 | "execution_count": 14,
999 | "metadata": {},
1000 | "outputs": [
1001 | {
1002 | "name": "stdout",
1003 | "output_type": "stream",
1004 | "text": [
1005 | "--------------------\n",
1006 | "False object_onto.GlassBottle\n",
1007 | "[('GlassBottle', 'hasMaterial, some', 'Glass'), ('GlassBottle', 'subclass_of', 'Bottle'), ('GlassBottle', 'isGraspableBy, some', 'Human'), ('GlassBottle', 'has_individual', 'GlassBottle1'), ('Bottle', 'has_subclass', 'GlassBottle'), ('Human', 'canGrasp, some', 'GlassBottle')]\n"
1008 | ]
1009 | },
1010 | {
1011 | "data": {
1012 | "image/svg+xml": [
1013 | "\n",
1014 | "\n",
1016 | "\n",
1018 | "\n",
1019 | "\n"
1098 | ],
1099 | "text/plain": [
1100 | ""
1101 | ]
1102 | },
1103 | "execution_count": 14,
1104 | "metadata": {},
1105 | "output_type": "execute_result"
1106 | }
1107 | ],
1108 | "source": [
1109 | "print('-'*20)\n",
1110 | "entity = keyword_search_onto('glassbottle', onto)\n",
1111 | "print(entity == onto.HumanHand, entity)\n",
1112 | "kg = ontograf_simple(entity, onto)\n",
1113 | "print(kg)\n",
1114 | "convert_to_graphviz(kg)"
1115 | ]
1116 | },
1117 | {
1118 | "cell_type": "code",
1119 | "execution_count": 15,
1120 | "metadata": {},
1121 | "outputs": [
1122 | {
1123 | "name": "stdout",
1124 | "output_type": "stream",
1125 | "text": [
1126 | "--------------------\n",
1127 | "False object_onto.Cold\n",
1128 | "[('Cold', 'subclass_of', 'TemperatureValuePartition'), ('TemperatureValuePartition', 'has_subclass', 'Cold')]\n"
1129 | ]
1130 | },
1131 | {
1132 | "data": {
1133 | "image/svg+xml": [
1134 | "\n",
1135 | "\n",
1137 | "\n",
1139 | "\n",
1140 | "\n"
1173 | ],
1174 | "text/plain": [
1175 | ""
1176 | ]
1177 | },
1178 | "execution_count": 15,
1179 | "metadata": {},
1180 | "output_type": "execute_result"
1181 | }
1182 | ],
1183 | "source": [
1184 | "print('-'*20)\n",
1185 | "entity = keyword_search_onto('cold', onto)\n",
1186 | "print(entity == onto.HumanHand, entity)\n",
1187 | "kg = ontograf_simple(entity, onto)\n",
1188 | "print(kg)\n",
1189 | "convert_to_graphviz(kg)"
1190 | ]
1191 | },
1192 | {
1193 | "cell_type": "code",
1194 | "execution_count": 16,
1195 | "metadata": {},
1196 | "outputs": [
1197 | {
1198 | "name": "stdout",
1199 | "output_type": "stream",
1200 | "text": [
1201 | "--------------------\n",
1202 | "True None\n",
1203 | "[]\n"
1204 | ]
1205 | },
1206 | {
1207 | "data": {
1208 | "image/svg+xml": [
1209 | "\n",
1210 | "\n",
1212 | "\n",
1214 | "\n",
1215 | "\n"
1222 | ],
1223 | "text/plain": [
1224 | ""
1225 | ]
1226 | },
1227 | "execution_count": 16,
1228 | "metadata": {},
1229 | "output_type": "execute_result"
1230 | }
1231 | ],
1232 | "source": [
1233 | "print('-'*20)\n",
1234 | "entity = keyword_search_onto('hello', onto)\n",
1235 | "print(entity == onto.HumanHand, entity)\n",
1236 | "kg = ontograf_simple(entity, onto)\n",
1237 | "print(kg)\n",
1238 | "convert_to_graphviz(kg)"
1239 | ]
1240 | }
1241 | ],
1242 | "metadata": {
1243 | "kernelspec": {
1244 | "display_name": "Python 3",
1245 | "language": "python",
1246 | "name": "python3"
1247 | },
1248 | "language_info": {
1249 | "codemirror_mode": {
1250 | "name": "ipython",
1251 | "version": 3
1252 | },
1253 | "file_extension": ".py",
1254 | "mimetype": "text/x-python",
1255 | "name": "python",
1256 | "nbconvert_exporter": "python",
1257 | "pygments_lexer": "ipython3",
1258 | "version": "3.6.9"
1259 | }
1260 | },
1261 | "nbformat": 4,
1262 | "nbformat_minor": 2
1263 | }
1264 |
--------------------------------------------------------------------------------