2021 project ontology in Gistv1
Saved notebook · 39 cells. Code and outputs below are retained from the original; nothing was executed for this reading copy. Environment dependencies, missing data and the model limitations remain as described in the linked guide.
Cell 1 · code
import os
import graphviz
import owlready2 as owl
import weakref
import graph_onto as GO # set up within this directory
Cell 2 · code
onto_path = 'file://' + os.path.abspath('ontologies/gistCore9.5.0')
onto = owl.get_ontology(onto_path).load()
print('Loaded owl file at:', onto_path)
# onto1 = get_ontology("file:///Users/lawrence/ontologies/project_example.owl").load() NEED TO ADD EMPTY ONTOLOGY
# onto.base_iri
Cell 3 · code
# OPTION LOOK ACROSS ALL CLASSES using the generator
for x in onto.classes():
print(x)
Cell 4 · code
# OPTION Or transform the generator into a list with the list() function
class_as_list=list(onto.classes())
print (class_as_list[-10]) # Get a random class in collection
list (onto.disjoint_classes()) # or look at disjoint classes
# Or, rather than simply classes,etreive all disjoint individual entity objects, stored in the dict
disjoints = list(onto.disjoints())
for x in disjoints:
print(x, ' ',x.__dict__,'\n')
Cell 5 · code
# FIND THE CLASSES OF INTEREST
Project_search_results_as_list=onto.search(iri='*Project*') # search for entities by looking along the full IRI
Task_search_results_as_list=onto.search(iri='*Task')
Artifact_search_results_as_list=onto.search(iri='*Artifact')
print(Project_search_results_as_list,Task_search_results_as_list,Artifact_search_results_as_list)
Cell 6 · code
# SELECT THE CLASSES OF INTEREST FROM SEARCH RESULTS
Project_class_actually=Project_search_results_as_list[0]
Task_class_actually=Task_search_results_as_list[0]
Artifact_class_actually=Artifact_search_results_as_list[0]
Cell 7 · code
# OPTION HAVE A LOOK AT CLASS PROPERTIES
print ('is a', Artifact_class_actually.is_a) # this gives SUPER classes
print('equivalent_to:', Artifact_class_actually.equivalent_to)
print('has subclasses: ', onto.search(subclass_of=Artifact_class_actually)) # this give SUB classes
for sc in Artifact_class_actually.ancestors():
print (sc)
for sc in Artifact_class_actually.descendants():
print (sc)
print(Artifact_class_actually.__dict__)
Cell 8 · code
# CREATE INSTANCES OF THIS CLASS
Cell 9 · code
#Refer to each project as ProjectX[0] etc
Project=[]
ProjectX=[]
for p in range (0,3):
name='Project'+str(p)
Project.append(name) # this does nothing
ProjectX.append(Project_class_actually(Project[p]))
print (Project[p], ' ',ProjectX[p])
Cell 10 · code
# TaskX[0] etc
Task=[]
TaskX=[]
for t in range (0,9):
name='Task'+str(t)
Task.append(name)
TaskX.append(Task_class_actually(Task[t]))
print (Task[t], ' ',TaskX[t])
Cell 11 · code
# ArtifactX[0] etc
Artifact=[]
ArtifactX=[]
for t in range (0,3):
name='Artifact'+str(t)
Artifact.append(name)
ArtifactX.append(Artifact_class_actually(Artifact[t]))
print (Artifact[t], ' ',ArtifactX[t])
Cell 12 · code
ProjectX[2]
Saved output
gist.Project2
Cell 13 · code
# The first parameter is the name (or identifier) of the Individual; it corresponds to the .name attribute in Owlready2.
# If not given, the name if automatically generated from the Class name and a number.
random_name=Project_class_actually('Project_Fruitloop100')# create a one off project EASIEST
ProjectX.append(Project_class_actually('Project_Fruitloop200')) # SECOND EASIEST
ProjectX.append(Project_class_actually('Project_Fruitloop300',namespace=onto,hasSubTask=[TaskX[0]])) # THIRD EASIEST
Cell 14 · code
# OPTIONAL
# ACCESS INSTANCES BY GENERAL VARIABLE OR BY ITERATING THROUGH CLASS
print (ProjectX[0].name,ProjectX[0].iri)
list (onto.individuals())
# note that this particular ontology has ensured some individuals are disjoint
# Some tasks will not be disjoint, but Project people will be, so good to have a go at creating this
print ('\n different indiviudals')
list (onto.different_individuals())
list (onto.individuals())
Cell 15 · code
# OPTIONAL
for p in Project_class_actually.instances(): print (p.name)
for t in Task_class_actually.instances(): print (t.name)
for t in Artifact_class_actually.instances():print (t.name)
Cell 16 · code
# CREATE RELATIONSHIPS
Cell 17 · code
# Most simple
# ProjectX[0].hasSubTask = [TaskX[0],TaskX[1],TaskX[2]]
Cell 18 · code
# Second most simple
# ProjectX[0] is type Gist.Project and is not subscriptable further. But below is a generator so can use:
#for p in Project_class_actually.instances(): p.hasSubTask = [TaskX[0]]
Cell 19 · code
# Third most simple
Cell 20 · code
#problem is here, that I dont know what order the instances are presented in. So only good for slapdash
counter=0
for p in Project_class_actually.instances():
p.hasSubTask = [TaskX[counter],TaskX[counter+1],TaskX[counter+2]]
counter+=3
Cell 21 · code
counter=0
for p in Project_class_actually.instances():
p.produces = [ArtifactX[counter]]
counter+=1
Cell 22 · code
#OPTIONAL check relationships have worked
print (ProjectX[0].get_properties(),'\n') # OR..
for p in Project_class_actually.instances(): print (p.get_properties(),'\n')
print(ProjectX[2].INDIRECT_hasSubTask,'\n') # alternative
print(ProjectX[2].INDIRECT_produces,'\n')
property_list=list(onto.properties()) #list of all generic properties:
rel = property_list[-1] # select a particular relation from the list
print(rel, rel.__dict__)
Cell 23 · code
#Interested in the relation 'produces'
# the .class_property_type attribute of Properties allows to indicate how to handle class properties:
# “some”: handle class properties as existential restrictions (i.e. SOME restrictions and VALUES restrictions).
# “only”: handle class properties as universal restrictions (i.e. ONLY restrictions).
# “relation”: handle class properties as relations (i.e. simple RDF triple, as in Linked Data).
print(onto.search(produces = "*")) #searches for individuals related w ‘produces’
pr=onto.search(iri='*produces*') # this focusses on the relationship itself
print (pr)
print('class_property_some:', pr[0]._class_property_some)
print('class_property_only:', pr[0]._class_property_only)
print('class_property_relation:', pr[0]._class_property_relation)
print(pr[0].__dict__)
# print('name(string):', pr[0].name)
#print('module_type:', pr[0].__module__)
# print('is_a:', pr[0].is_a) # will come back saying its an owl property
Cell 24 · code
#calling the functions from *.py file
Cell 25 · code
entity = GO.keyword_search_onto('Artifact', onto)
print(entity == onto.Artifact, entity,'-'*20,'\n')
kg = GO.ontograf_simple(entity, onto)
print(kg)
GO.convert_to_graphviz(kg)
Cell 26 · code
# so far, I have introduced a new property ' produces' between instances of Project and Artifact.
#This does not appear in the class rules, and it will need to presumably.
Cell 27 · code
onto.save(file = "/Users/lawrence/Documents/GitHub/Data-models-for-projects/Project_model.owl", format = "rdfxml")
Cell 28 · code
Artifact_class_actually.instances()
Saved output
[gist.Artifact0, gist.Artifact1, gist.Artifact2]
Cell 29 · code
# ACTION THIS BELOW
# We can see from this, that relationship properties have to be created both sides
print(onto.search(hasSubTask = "*"))
ProjectX[0].__dict__
TaskX[0].__dict__
Saved output
[gist.Project0, gist.Project1, gist.Project2]
Cell 30 · code
# annotations are one of the property types where the objects are names or strings or link addresses (IRIs),
# but over which no reasoning may occur. Annotations provide the labels, definitions, comments, and pointers to the actual objects in the system. We can assign values in a straightforward manner to annotations (in this case, <code>altLabel</code>):
Cell 31 · code
ProjectX[0].altLabel = ["Digital_Reset_project",'2021_Cloud_project']
Cell 32 · code
ProjectX[0].get_properties()
Cell 33 · code
print(ProjectX[0].altLabel)
Cell 34 · code
# Owlready2 enables us to also place restrictions on our classes
#nthrough a special type of class constructed by the system.
some - Property.some(Range_Class)
only - Property.only(Range_Class)
min - Property.min(cardinality, Range_Class)
max - Property.max(cardinality, Range_Class)
exactly - Property.exactly(cardinality, Range_Class)
value - Property.value(Range_Individual / Literal value)
has_self - Property.has_self(Boolean value).
Cell 35 · markdown
Operators
Owlready2 provides three logical operators between classes (including class constructs and restrictions):
- ‘&’ - And operator (intersection). For example: Class1 & Class2. It can also be written: And([Class1, Class2])
-
‘ ’ - Or operator (union). For example: Class1 Class2. It can also be written: Or([Class1, Class2]) - Not() - Not operator (negation or complement). For example: Not(Class1).
Cell 36 · markdown
Both HermiT and Pellet are written in Java, so require access to a JVM on your system. If you have difficulty running these systems it is likely because you: 1) do not have a recent version of Java installed on your system; or 2) do not have a proper PATH statement in your environmental variables to find the Java executable. If you encounter such problems, please consult third-party sources to get Java properly configured for your system before continuing with this installment.
Cell 37 · code
owl.sync_reasoner()
Cell 38 · code
owl.sync_reasoner_pellet()
Cell 39 · code