I have an ontology loaded. I can step through the classes and properties.
What I would like to be able to do is create a new ontology with some of the concepts from the first one. I need to do two things: 1) create a new blank ontology (which I'll call ontoOut). There must be a way that I'm not findind, but in the mean time, I created an empty ontology in protege and opened that, so I have a work arouind 2) add concepts (classes and properties) to ontoOut. If there were an addClass method and and addProperties method that would do it. I tried this ontoOut[gist.Person] which didn't fail, but didn't show up in the output but it didn't make it to the output when I said ontoOut.save(). gist is the namespace and gist.Person is a class from the input ontology, and when I interogate it (for instance gist.Person.equivalent_to I get the restrictions. I feel like I'm close but don't quite see how to bridge this last gap |
Administrator
|
Hi,
To create a new ontology, just use get_ontology(IRI) but do not call .load(). However, Owlready still miss a "concetp-copying" method. Such a method is not entirely trivial (e.g. should the related concept be also copied? recursively?). You may duplicate the RDF triples defining a concept with RDFlib though. Jiba |
Thanks.
I know it's not trivial. I have designed an algorithm that I think will get what I need anyway (I will do the recursion and make some decisions about what to include and not include) For right now a shallow copy would suffice (by shallow I mean the class, with its restrictions, and annotations), I will handle the superclasses and disjoints myself. I'm following my nose, looks like I need to use a setattr, which I've never done. When I get some spare time (probably not today) I'll read the source code to see if I can find where to add the classes and properties. Thanks much, very impressed with this package |
I've delved into this deeper. I think I sort of understand what you've done. Let me run this by you and see if I'm on the right track and see if we can figure out a way for me to do what I want to do.
I naively believed that there were class objects in your system, one per class in owl, and that I could move them, by copying from one ontology to another. It now looks to me like class is just a wrapper around a query that picks up ?class rdf:type owl:Class from your SQL table. To actually copy a class would require copying the annotations (not too hard) but also the equivalent_to and is_a, which could involve following a bunch of blank nodes through the table. Also I don't quite get the relation of the classes to the ontology itself. something I saw somewhere in the code suggested that classes were exclusively owned by an ontology, which might make such a move difficult (although for my purpose if I knew it was being moved, I'd just be careful not to save the original ontology after I started pilfering it for parts). I also saw a warning about the blank nodes relative to an ontology, but as I don't get the whole structure here that has me puzzled. What I would love to have to solve the problem I want to solve would be a shallow clone function. I believe if the clone function for a class copied the annotation properties and the equivalent_to and is_a to another ontology that would handle the class case. I haven't investigated the properties yet, but it would seem to me that if it cloned the annotations, all the types (to pick up functional, transitive etc) its superproperties and the domain and ranges (which unfortunately could be complex class expressions as well) and the data types, that would do it. If you want to respond directly to me to discuss this further: mccomb@semanticarts.com |
I feel like I'm so close, but something isn't lining up.
I load an ontology, everything looks good. Then I do this ontoOut= get_ontology("https://ontologies.semanticarrs.com/gistSubSet.owl/") ontoOut.get_namespace("https://ontologies.semanticarts.com/gist/") print (gist.Person.equivalent_to) print ("aspect",gist.Aspect.is_a) print ("gist.Aspectname", gist.Aspect.name) with ontoOut: types.new_class(gist.Aspect.name) for c in ontoOut.classes(): print ("c2",c) ontoOut.save(file = "gistSubSet.owl") I used your suggestion to set up the output ontology (previously I had been opening an empty ontology) I'm not seeing either approach to work yet. The first three print lines are just reasurring me that the classes I loaded from input ontology are still ok the new_classes method seems like it should set up a class (I didn't assign it to a class name in python, if I have to do that how will I do it dynamically (I want to create many dozens, and won't know at coding time what they are) The output [gist.LivingThing & gist.offspringOf.some(gist.Person) & gist.name.some(<class 'str'>)] aspect [gist.Category] gist.Aspectname Aspect First line, Person has its fromal definition Second line aspect has its is_a Third line Aspect has a name But the "c2"'s dont show and the output file is just the headers and name of ontology I'm overlooking something obvious here but don't see it. Thanks again |
Administrator
|
Hi,
Yes, the class is just a wrapper arround the data stored in the SQL tables. equivalent_to and is_a need to be copied, recursively. Each class has a "default" owning ontology, however, part of the class may be defined in other ontologies. But equivalent_to and is_a are blank nodes, and blank nodes are anonymous and thus they are "ontology-local" : an ontology cannot refer to the blank node from another ontology. I think you missed something in types.new_class() : you must specify the parent classes. If you don't, you create a standard Python class, not a Owlready class. So you need something like types.new_class("class_name", (Thing,)) to create a new class that is a Thing. You can put the new class in a (temporary) variable name, and then adds its parent in .is_a. In addition, you can add the blank nodes, as long as you remove them from their former child class (blank nodes cannot be shared by several classes from different ontologies). The code example below does that. Jiba ----8<------------ from owlready2 import * onto_orig = get_ontology("http://test.org/onto_orig.owl") with onto_orig: class A(Thing): pass class B(Thing): pass class C(Thing): pass class D(Thing): is_a = [A & (B | C)] onto_dest = get_ontology("http://test.org/onto_dest.owl") with onto_dest: for class_orig in onto_orig.classes(): class_dest = types.new_class(class_orig.name, (Thing,)) for parent in list(class_orig.is_a): if not isinstance(parent, Thing): class_orig.is_a.remove(parent) # Bank node class_dest.is_a.append(parent) onto_dest.save("/tmp/o.owl") print(open("/tmp/o.owl").read()) |
From: Jiba [via Owlready] <ml+[hidden email]>
Sent: Monday, September 30, 2019 9:02:31 AM To: Dave McComb <[hidden email]> Subject: Re: How to move concepts from one ontology to another Hi,
Yes, the class is just a wrapper arround the data stored in the SQL tables. equivalent_to and is_a need to be copied, recursively. Each class has a "default" owning ontology, however, part of the class may be defined in other ontologies. But equivalent_to and is_a are blank nodes, and blank nodes are anonymous and thus they are "ontology-local" : an ontology cannot refer to the blank node from another ontology. I think you missed something in types.new_class() : you must specify the parent classes. If you don't, you create a standard Python class, not a Owlready class. So you need something like types.new_class("class_name", (Thing,)) to create a new class that is a Thing. You can put the new class in a (temporary) variable name, and then adds its parent in .is_a. In addition, you can add the blank nodes, as long as you remove them from their former child class (blank nodes cannot be shared by several classes from different ontologies). The code example below does that. Jiba ----8<------------ from owlready2 import * onto_orig = get_ontology("http://test.org/onto_orig.owl") with onto_orig: class A(Thing): pass class B(Thing): pass class C(Thing): pass class D(Thing): is_a = [A & (B | C)] onto_dest = get_ontology("http://test.org/onto_dest.owl") with onto_dest: for class_orig in onto_orig.classes(): class_dest = types.new_class(class_orig.name, (Thing,)) for parent in list(class_orig.is_a): if not isinstance(parent, Thing): class_orig.is_a.remove(parent) # Bank node class_dest.is_a.append(parent) onto_dest.save("/tmp/o.owl") print(open("/tmp/o.owl").read()) If you reply to this email, your message will be added to the discussion below:
http://owlready.8326.n8.nabble.com/How-to-move-concepts-from-one-ontology-to-another-tp1386p1399.html
|
Free forum by Nabble | Edit this page |