Hello!
I have tried lately to make some transfer some data from one ontology to another one. I first mireoted some terms from one ontology to include them in another one and now I would like to transfer some more properties, especially restrictions and the corresponding properties. While handling different ontologies is easy, I was wondering how exactly to perform the transfer. Here is some toy code where I was trying to simply transfer some class, and then the associated restrictions. from owlready2 import * onto = get_ontology("http://test.org/onto.owl") with onto: class Drug(Thing): pass class ActivePrinciple(Thing): pass class has_for_active_principle(Drug >> ActivePrinciple): pass class NonPlaceboDrug(Drug): equivalent_to = [Drug & has_for_active_principle.some(ActivePrinciple)] class someActivePrinciple(ActivePrinciple): pass class MyDrug(Drug): has_for_active_principle = [someActivePrinciple] # make onto2 onto2 = get_ontology("http://test.org/onto2.owl") with onto2: class Drug2(Thing): pass class ActivePrinciple2(Thing): pass class has_for_active_principle2(Drug >> ActivePrinciple): pass # Try to merge things MyDrug = onto.MyDrug onto2.MyDrug = MyDrug onto.save(file = r"c:\temp\owlready.rdf", format = "rdfxml") onto2.save(file = r"c:\temp\owlready2.rdf", format = "rdfxml") The #Try to merge things is where things break. I tried several other approaches but had no luck. Any idea on how to transfer onto.MyDrug into onto2, and then its property restriction ? BTW, I find the handling of these property restrictions (i.e. owl:equivalentClass, rdfs:subClassOf/owl:Restriction) especially elegant in owlready2! Cheers, Guillaume |
Answering your own message looks lame but I came to the following solution which I would like to submit here for review, as it feels like the script is somehow abusing the system, in particular
owlready2.Restrictiondoes not seem documented and I wonder if I make a proper use of it. Here is the script: from owlready2 import * world = World() onto = world.get_ontology("http://test.org/onto.owl") with onto: class Drug(Thing): pass class ActivePrinciple(Thing): pass class has_for_active_principle(Drug >> ActivePrinciple): pass class someActivePrinciple(ActivePrinciple): pass class MyDrug(Drug): has_for_active_principle = [someActivePrinciple] #this one has some property restriction # let's separate the worlds world2 = World() onto2 = world2.get_ontology("http://test.org/onto.owl") with onto2: class Drug(Thing): pass class ActivePrinciple(Thing): pass class has_for_active_principle(Drug >> ActivePrinciple): pass class someActivePrinciple(ActivePrinciple): pass class MyDrug(Thing): # not a subClass of Drug pass # missing the has_for_active_principle restriction # get the restriction we want to extract restriction = onto.MyDrug.is_a.pop(1) myRestriction = Restriction(Property=world2.search_one(iri=restriction.property.iri), type=restriction.type, value=world2.search_one(iri=restriction.value.iri)) MyDrugOnto2 = world2.search_one(iri='*MyDrug') MyDrugOnto2.is_a.append(myRestriction) onto.save(file=r"c:\temp\owlready.rdf", format="rdfxml") onto2.save(file=r"c:\temp\owlready2.rdf", format="rdfxml") Any thought ? |
In reply to this post by gp
Interestingly, nothing "broke" when I ran this. Nice work! It is amusing to rip assertions from ontology to another this way with
restriction = *onto.MyDrug.is_a.pop(1)* # Removes the existential restriction from MyDrug in first ontology myRestriction = Restriction(Property=world2.search_one(iri=restriction.property.iri), type=restriction.type, value=world2.search_one(iri=restriction.value.iri)) MyDrugOnto2 = world2.search_one(iri='*MyDrug') MyDrugOnto2.is_a.append(myRestriction) Although it's probably better to just retrieve a copy: restriction = onto.MyDrug.is_a[1] |
https://owlready2.readthedocs.io/en/latest/onto.html#importing-other-ontologies
provides a means to import another ontology. I tried it, and when I opened *onto2* in protege, it showed *onto* was an imported ontology, but it didn't seem to change anything, even after reasoning with Pellet. |
Well the pop command is an artifact, just because it was quick to get the restriction this way.
As of are you sure this works in the general case? The purpose of reconstructing the restriction object was to avoid mixing up things, especially if the same "world" is used. In this case importing the ontology (i.e. an owl:importXXX entry) is not an option as there would be too much pollution. The attempt here is more some sort of extended mireoting. Or did I miss your point here? |
Administrator
|
Hello,
Transfering entities from an ontology to another is not so easy, especially for some constructs like AllDisjoint (if an AllDisjoint includes the transfered classes, should it be transferred or not ?). I think the better way to do that is at the RDF level in the quadstore. Adding a .set_ontology() method would be great, but I'm very short in time currently :-( Best regards, Jiba |
I actually wondered the same thing and I guess this should be left to the programmer to decide on this.
In my case I indeed only want to transfer a closure axiom if everything is in place in the target ontology (i.e. every iri involved in the closure axiom is already defined/used in the target ontology). It is indeed not trivial to iterate in an elegant manner across the cascade of axioms when dealing with complex restrictions of the likes of owl:equivalentClass [ owl:intersectionOf ( XX:YYYYY [ rdf:type owl:Restriction ...Maybe a few helper functions to 1) iterate over all involved iris (one can then check them, do whatever is needed) 2) given a certain "subject" (be it the equivalent of a blank node) get all involved "properties", and also the same for any given "property" and the involved "objects", so one can navigate through the various elements in an iterative fashion? I understand the S P O description is not ideal to depict some ontology, but I found it convenient here. My idea is to navigate through the various closure axioms in a fashion similar to traversing a graph (like you would do using a SPARQL query for instance) but in a programmatic manner (and which one cannot do using SPARQL without predefining the structure). These functionalities might already exist and I might well have missed them completely. Just my two c... Guillaume |
Administrator
|
Hi,
Owlready has graph function: you can access them with e.g. default_world.graph.get_triples(subject_or_none, predicate_or_none, object_or_none),... I still need to document that part ! Best regards, Jiba |
Yes I think this will make it, mixing sparql queries with python code is probably a good approach to do the work!
|
In reply to this post by Jiba
I was thinking/hoping I would be able to transfer classes from one ontology to another, but it seems it's a much more complicated operation than I realized (due to recursion, etc.). How would one do this "at the RDF level in the quadstore" as suggested above? Is that something I could leverage owlready2 for, or perhaps rdflib (or rdflib through owlready2)? All these tools (and rdf/owl/sparql/ontologies) are pretty new to me but I'm diving in deep.
I'm not looking for specific instructions, just a potential general approach. I understand there may be some tools that might help, like Ontofox, but I would like to transfer thousands of entities and select annotations and properties...so I'm looking for a programmatic strategy I could implement myself. |
Administrator
|
Hi,
Indeed, recursion is the problem: how "deep" the copy should be? If it is not deep, the interest is limited. But if it is "fully" deep, everything will be copied... Here is how I would approach the problem: I would create a "Copier" class, with a "copy(entity)" method. The method would (1) retain the information that the given entity has been copied, (2) perform a shallow copy of the entity and (3) also copy any relation/restriction that involves only entities that have been copied previously. For example, let's consider two classes A and B, with A a subclass of B. If we copy first A, then a new class A' will be created in the new ontology. Then, If we copy B, a new class B' will be created and A' sublcass of B' will also be copied. Comments are welcome :) Jiba |
Free forum by Nabble | Edit this page |