2 | // This source code is available under the terms of the Affero General Public
3 | // License v3.
4 | //
5 | // Please see LICENSE.txt for full license terms, including the availability of
6 | // proprietary exceptions.
7 | // Questions, comments, or requests for clarification: licensing@clarkparsia.com
8 |
9 | package pellet;
10 |
11 | import java.util.List;
12 |
13 | import org.mindswap.pellet.KnowledgeBase;
14 | import org.mindswap.pellet.Role;
15 | import org.mindswap.pellet.taxonomy.printer.ClassTreePrinter;
16 | import org.mindswap.pellet.taxonomy.printer.TaxonomyPrinter;
17 |
18 | import aterm.ATermAppl;
19 |
20 | /**
21 | *
22 | * Title: PelletRealize
23 | *
24 | *
25 | * Description:
26 | *
27 | *
28 | * Copyright: Copyright (c) 2008
29 | *
30 | *
31 | * Company: Clark & Parsia, LLC.
32 | *
33 | *
34 | * @author Markus Stocker
35 | */
36 | public class PelletRealize extends PelletCmdApp {
37 |
38 | public PelletRealize() {
39 | super( );
40 | }
41 |
42 | @Override
43 | public String getAppCmd() {
44 | return "pellet realize " + getMandatoryOptions() + "[options] ...";
45 | }
46 |
47 | @Override
48 | public String getAppId() {
49 | return "PelletRealize: Compute and display the most specific instances for each class";
50 | }
51 |
52 | @Override
53 | public PelletCmdOptions getOptions() {
54 | PelletCmdOptions options = getGlobalOptions();
55 |
56 | options.add( getLoaderOption() );
57 | options.add( getIgnoreImportsOption() );
58 | options.add( getInputFormatOption() );
59 | options.add( getInferPropValuesOption() );
60 | options.add( getInferDataPropValuesOption() );
61 |
62 | return options;
63 | }
64 |
65 | @Override
66 | public void run() {
67 | KnowledgeBase kb = getKB();
68 |
69 | startTask( "consistency check" );
70 | boolean isConsistent = kb.isConsistent();
71 | finishTask( "consistency check" );
72 |
73 | if( !isConsistent )
74 | throw new PelletCmdException( "Ontology is inconsistent, run \"pellet explain\" to get the reason" );
75 |
76 | startTask( "classification" );
77 | kb.classify();
78 | finishTask( "classification" );
79 |
80 | startTask( "realization" );
81 | kb.realize();
82 | finishTask( "realization" );
83 |
84 | TaxonomyPrinter printer = new ClassTreePrinter();
85 | printer.print( kb.getTaxonomy() );
86 |
87 | // Jiba
88 |
89 | if ( options.getOption( "infer-prop-values" ).getValue() != null ) {
90 | for( ATermAppl ind : kb.getIndividuals() ) {
91 | for( Role role : kb.getRBox().getRoles() ) {
92 | if( role.isAnon() ) continue;
93 | if( role.isObjectRole() ) {
94 | ATermAppl name = role.getName();
95 | List values = kb.getObjectPropertyValues( name, ind );
96 | for( ATermAppl value : values ) {
97 | System.out.println("PROPINST: " + ind + " " + name + " " + value);
98 | }
99 | }
100 | }
101 | }
102 | }
103 |
104 | if ( options.getOption( "infer-data-prop-values" ).getValue() != null ) {
105 | for( ATermAppl ind : kb.getIndividuals() ) {
106 | for( Role role : kb.getRBox().getRoles() ) {
107 | if( role.isAnon() ) continue;
108 | if( role.isDatatypeRole() ) {
109 | ATermAppl name = role.getName();
110 | List values = kb.getDataPropertyValues( name, ind );
111 | for( ATermAppl value : values ) {
112 | System.out.println("DATAPROPVAL: " + ind + " " + name + " " + value);
113 | }
114 | }
115 | }
116 | }
117 | }
118 |
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/test/test_annot_on_bn2.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | ]>
10 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
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 | Annot on C
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Annot on D
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/pellet/org/mindswap/pellet/taxonomy/printer/ClassTreePrinter.java:
--------------------------------------------------------------------------------
1 | // Portions Copyright (c) 2006 - 2008, Clark & Parsia, LLC.
2 | // Clark & Parsia, LLC parts of this source code are available under the terms of the Affero General Public License v3.
3 | //
4 | // Please see LICENSE.txt for full license terms, including the availability of proprietary exceptions.
5 | // Questions, comments, or requests for clarification: licensing@clarkparsia.com
6 | //
7 | // ---
8 | // Portions Copyright (c) 2003 Ron Alford, Mike Grove, Bijan Parsia, Evren Sirin
9 | // Alford, Grove, Parsia, Sirin parts of this source code are available under the terms of the MIT License.
10 | //
11 | // The MIT License
12 | //
13 | // Permission is hereby granted, free of charge, to any person obtaining a copy
14 | // of this software and associated documentation files (the "Software"), to
15 | // deal in the Software without restriction, including without limitation the
16 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
17 | // sell copies of the Software, and to permit persons to whom the Software is
18 | // furnished to do so, subject to the following conditions:
19 | //
20 | // The above copyright notice and this permission notice shall be included in
21 | // all copies or substantial portions of the Software.
22 | //
23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 | // IN THE SOFTWARE.
30 |
31 | package org.mindswap.pellet.taxonomy.printer;
32 |
33 | import java.io.PrintWriter;
34 | import java.util.Iterator;
35 | import java.util.Set;
36 |
37 | import org.mindswap.pellet.PelletOptions;
38 | import org.mindswap.pellet.utils.ATermUtils;
39 | import org.mindswap.pellet.utils.QNameProvider;
40 | import org.mindswap.pellet.utils.TaxonomyUtils;
41 |
42 | import aterm.ATermAppl;
43 |
44 | /**
45 | * Title:
46 | *
47 | * Description: Specialized tree printer for class hierarchies that prints instaces for each class
48 | *
49 | * Copyright: Copyright (c) 2007
50 | *
51 | * Company: Clark & Parsia, LLC.
52 | *
53 | * @author Evren Sirin
54 | */
55 | public class ClassTreePrinter extends TreeTaxonomyPrinter implements TaxonomyPrinter {
56 | private QNameProvider qnames = new QNameProvider();
57 |
58 | public ClassTreePrinter() {
59 | }
60 |
61 | @Override
62 | protected void printNode(Set set) {
63 | super.printNode( set );
64 |
65 | Set instances = TaxonomyUtils.getDirectInstances( taxonomy, set.iterator().next() );
66 | if(instances.size() > 0) {
67 | out.print(" - (");
68 | boolean printed = false;
69 | int anonCount = 0;
70 | Iterator ins = instances.iterator();
71 | for(int k = 0; ins.hasNext(); k++) {
72 | ATermAppl x = ins.next();
73 |
74 | if( ATermUtils.isBnode( x ) ) {
75 | anonCount++;
76 | }
77 | else {
78 | if(printed)
79 | out.print(", ");
80 | else
81 | printed = true;
82 | printURI(out, x);
83 | }
84 | }
85 | if(anonCount > 0) {
86 | if(printed) out.print(", ");
87 | out.print(anonCount + " Anonymous Individual");
88 | if(anonCount > 1) out.print("s");
89 | }
90 | out.print(")");
91 | }
92 | }
93 |
94 | @Override
95 | protected void printURI(PrintWriter out, ATermAppl c) {
96 | String str = null;
97 |
98 | if(c.equals(ATermUtils.TOP))
99 | str = "http://www.w3.org/2002/07/owl#Thing";
100 | else if(c.equals(ATermUtils.BOTTOM))
101 | str = "http://www.w3.org/2002/07/owl#Nothing";
102 | else if( ATermUtils.isPrimitive( c ) )
103 | str = c.getName();
104 | else
105 | str = c.toString();
106 |
107 | out.print( str );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/doc/namespace.rst:
--------------------------------------------------------------------------------
1 | Namespaces
2 | ==========
3 |
4 | Ontologies can define entities located in other namespaces.
5 | An example is Gene Ontology (GO): the ontology IRI is 'http://purl.obolibrary.org/obo/go.owl',
6 | but the IRI of GO entities are not of the form 'http://purl.obolibrary.org/obo/go.owl#GO_entity' but
7 | 'http://purl.obolibrary.org/obo/GO_entity' (note the missing 'go.owl#').
8 |
9 |
10 | Accessing entities defined in another namespace
11 | -----------------------------------------------
12 |
13 | These entities can be accessed in Owlready2 using a namespace. The get_namepace(base_iri) global function
14 | returns a namespace for the given base IRI.
15 |
16 | The namespace can then be used with the dot notation, similarly to the ontology.
17 |
18 | ::
19 |
20 | >>> # Loads Gene Ontology (~ 170 Mb), can take a moment!
21 | >>> go = get_ontology("http://purl.obolibrary.org/obo/go.owl").load()
22 |
23 | >>> print(go.GO_0000001) # Not in the right namespace
24 | None
25 |
26 | >>> obo = get_namespace("http://purl.obolibrary.org/obo/")
27 |
28 | >>> print(obo.GO_0000001)
29 | obo.GO_0000001
30 |
31 | >>> print(obo.GO_0000001.iri)
32 | http://purl.obolibrary.org/obo/obo.GO_0000001
33 |
34 | >>> print(obo.GO_0000001.label)
35 | ['mitochondrion inheritance']
36 |
37 |
38 | .get_namepace(base_iri) can also be called on an Ontology, for example:
39 |
40 | ::
41 |
42 | >>> obo = go.get_namespace("http://purl.obolibrary.org/obo/")
43 |
44 | Namespaces created on an Ontology can also be used for asserting facts and creating classes, instances,...:
45 |
46 | ::
47 |
48 | >>> with obo:
49 | >>> class MyNewClass(Thing): pass # Create http://purl.obolibrary.org/obo/MyNewClass
50 |
51 |
52 | Creating classes in a specific namespace
53 | ----------------------------------------
54 |
55 | When creating a Class or a Property,
56 | the namespace attribute is used to build the full IRI of the Class,
57 | and to define in which ontology the Class is defined
58 | (RDF triples are added to this ontology).
59 | The Class IRI is equals to the namespace's base IRI (base_iri) + the Class name.
60 |
61 | An ontology can always be used as a namespace, as seen in :doc:`class`.
62 | A namespace object can be used if you want to locate the Class at a different IRI.
63 | For example:
64 |
65 | ::
66 |
67 | >>> onto = get_ontology("http://test.org/onto/")
68 | >>> namespace = onto.get_namespace("http://test.org/onto/pharmaco")
69 |
70 | >>> class Drug(Thing):
71 | ... namespace = namespace
72 |
73 |
74 | In the example above, the Drug Class IRI is "http://test.org/pharmaco/Drug", but the Drug Class
75 | belongs to the 'http://test.org/onto' ontology.
76 |
77 | Owlready2 proposes 3 methods for indicating the namespace:
78 |
79 | * the 'namespace' Class attribute
80 | * the 'with namespace' statement
81 | * if not provided, the namespace is inherited from the first parent Class
82 |
83 | The following examples illustrate the 3 methods:
84 |
85 | ::
86 |
87 | >>> class Drug(Thing):
88 | ... namespace = namespace
89 |
90 | >>> with namespace:
91 | ... class Drug(Thing):
92 | ... pass
93 |
94 | >>> class Drug2(Drug):
95 | ... # namespace is implicitely Drug.namespace
96 | ... pass
97 |
98 |
99 | Modifying a class defined in another ontology
100 | ---------------------------------------------
101 |
102 | In OWL, an ontology can also *modify* a Class already defined in another ontology.
103 |
104 | In Owlready2, this can be done using the 'with namespace' statement.
105 | Every RDF triples added (or deleted) inside a 'with namespace' statement
106 | goes in the ontology corresponding to the namespace of the 'with namespace' statement.
107 |
108 | The following example creates the Drug Class in a first ontology,
109 | and then asserts that Drug is a subclass of Substance in a second ontology.
110 |
111 | ::
112 |
113 | >>> onto1 = get_ontology("http://test.org/my_first_ontology.owl")
114 | >>> onto2 = get_ontology("http://test.org/my_second_ontology.owl")
115 |
116 | >>> with onto1:
117 | ... class Drug(Thing):
118 | ... pass
119 |
120 | >>> with onto2:
121 | ... class Substance(Thing):
122 | ... pass
123 |
124 | ... Drug.is_a.append(Substance)
125 |
126 |
--------------------------------------------------------------------------------
/test/onto2.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 | ]>
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | 3
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
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 |
--------------------------------------------------------------------------------
/close.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Owlready2
3 | # Copyright (C) 2013-2019 Jean-Baptiste LAMY
4 | # LIMICS (Laboratoire d'informatique médicale et d'ingénierie des connaissances en santé), UMR_S 1142
5 | # University Paris 13, Sorbonne paris-Cité, Bobigny, France
6 |
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 |
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU Lesser General Public License for more details.
16 |
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with this program. If not, see .
19 |
20 | from owlready2.namespace import *
21 | from owlready2.entity import *
22 | from owlready2.entity import _inherited_property_value_restrictions
23 | from owlready2.prop import *
24 | from owlready2.individual import *
25 | from owlready2.class_construct import *
26 |
27 |
28 | def close_world(self, Properties = None, close_instance_list = True, recursive = True):
29 | if isinstance(self, Thing): # An instance
30 | if Properties is None:
31 | Properties2 = (Prop for Prop in self._get_instance_possible_relations() if issubclass_python(Prop, ObjectProperty))
32 | else:
33 | Properties2 = Properties
34 |
35 | for Prop in Properties2:
36 | range_instances = list(Prop[self])
37 | range_classes = []
38 | for r in _inherited_property_value_restrictions(self, Prop, set()):
39 | if (r.type == SOME): range_classes .append(r.value)
40 | elif (r.type == VALUE): range_instances.append(r.value)
41 | if range_instances: range_classes.append(OneOf(range_instances))
42 |
43 | if not range_classes: self.is_a.append(Prop.only(Nothing))
44 | elif issubclass_python(Prop, FunctionalProperty): pass
45 | elif len(range_classes) == 1: self.is_a.append(Prop.only(range_classes[0]))
46 | else: self.is_a.append(Prop.only(Or(range_classes)))
47 |
48 | elif isinstance(self, ThingClass): # A class
49 | instances = set(self.instances())
50 | subclasses = set(self.descendants())
51 |
52 | if close_instance_list:
53 | if instances: self.is_a.append(OneOf(list(instances)))
54 |
55 | if Properties is None:
56 | Properties2 = (Prop for Prop in self._get_class_possible_relations() if issubclass_python(Prop, ObjectProperty))
57 | else:
58 | Properties2 = Properties
59 |
60 | for Prop in Properties2:
61 | range_instances = []
62 | range_classes = []
63 | for subclass in subclasses: # subclasses includes self
64 | for r in _inherited_property_value_restrictions(subclass, Prop, set()):
65 | if r.type == VALUE:
66 | range_instances.append(r.value)
67 | elif (r.type == SOME) or ((r.type == EXACTLY) and r.cardinality >= 1) or ((r.type == MIN) and r.cardinality >= 1):
68 | if isinstance(r.value, OneOf): range_instances.extend(r.value.instances)
69 | else: range_classes.append(r.value)
70 |
71 | for instance in instances:
72 | range_instances.extend(Prop[instance])
73 | for r in _inherited_property_value_restrictions(instance, Prop, set()):
74 | if (r.type == SOME): range_classes .append(r.value)
75 | elif (r.type == VALUE): range_instances.append(r.value)
76 |
77 | if range_instances: range_classes.append(OneOf(range_instances))
78 | if len(range_classes) == 1: self.is_a.append(Prop.only(range_classes[0]))
79 | elif range_classes: self.is_a.append(Prop.only(Or(range_classes)))
80 | else: self.is_a.append(Prop.only(Nothing))
81 |
82 | if recursive:
83 | subclasses.discard(self)
84 | for subclass in subclasses: close_world(subclass, Properties, close_instance_list, False)
85 | for instance in instances: close_world(instance, Properties, close_instance_list, False)
86 |
87 |
88 | elif isinstance(self, Ontology):
89 | for individual in self.individuals():
90 | close_world(individual, Properties, close_instance_list, recursive)
91 |
92 | for Class in self.classes():
93 | close_world(Class, Properties, close_instance_list, False) # False because all the loop will already close subclasses
94 |
95 |
--------------------------------------------------------------------------------
/test/test_datatype_one_of.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 | ]>
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 1
66 |
67 |
68 |
69 | 2
70 |
71 |
72 |
73 | 3
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | 1
105 |
106 |
107 | 1
108 | Annotation on a triple with a datatype value.
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/doc/world.rst:
--------------------------------------------------------------------------------
1 | Worlds
2 | ======
3 |
4 | Owlready2 stores every triples in a 'World' object, and it can handles several Worlds
5 | in parallel. 'default_world' is the World used by default.
6 |
7 |
8 | Persistent world: storing the quadstore in an SQLite3 file database
9 | -------------------------------------------------------------------
10 |
11 | Owlready2 uses an optimized quadstore. By default, the quadstore is stored in memory, but it can also be
12 | stored in an SQLite3 file. This allows persistance: all ontologies loaded and created are stored in the file,
13 | and can be reused later.
14 | This is interesting for big ontologies: loading huge ontologies can take time, while opening the SQLite3 file
15 | takes only a fraction of second, even for big files.
16 | It also avoid to load huge ontologies in memory, if you only need to access a few
17 | entities from these ontologies.
18 |
19 | The .set_backend() method of World sets the SQLite3 filename associated to the quadstore,
20 | for example:
21 |
22 | ::
23 |
24 | >>> default_world.set_backend(filename = "/path/to/your/file.sqlite3")
25 |
26 | .. note::
27 |
28 | If the quad store is not empty when calling .set_backend(), RDF triples are automatically copied.
29 | However, this operation can have a high performance cost (especially if there are many triples).
30 |
31 |
32 | When using persistence, the .save() method of World must be called for saving the actual
33 | state of the quadstore in the SQLite3 file:
34 |
35 | ::
36 |
37 | >>> default_world.save()
38 |
39 | Storing the quadstore in a file does not reduce the performance of Owlready2 (actually,
40 | it seems that Owlready2 performs a little *faster* when storing the quadstore on the disk).
41 |
42 | To reload an ontology stored in the quadstore (when the corresponding OWL file has been updated),
43 | the reload and reload_if_newer optional parameters of .load() can be used (the former reload the ontology,
44 | and the latter reload it only if the OWL file is more recent).
45 |
46 | By default, Owlready2 opens the SQLite3 database in exclusive mode. This mode is faster, but it does not allow
47 | several programs to use the same database simultaneously. If you need to have several Python programs that
48 | access simultaneously the same Owlready2 quadstore, you can disable the exclusive mode as follows:
49 |
50 | ::
51 |
52 | >>> default_world.set_backend(filename = "/path/to/your/file.sqlite3", exclusive = False)
53 |
54 |
55 |
56 | Using several isolated Worlds
57 | -----------------------------
58 |
59 | Owlready2 can support several, isolated, Worlds.
60 | This is interesting if you want to load several version
61 | of the same ontology, for example before and after reasoning.
62 |
63 | A new World can be created using the World class:
64 |
65 | ::
66 |
67 | >>> my_world = World()
68 | >>> my_second_world = World(filename = "/path/to/quadstore.sqlite3")
69 |
70 | Ontologies are then created and loaded using the .get_ontology() methods of the World
71 | (when working with several Worlds, this method replaces the get_ontology() global function):
72 |
73 | ::
74 |
75 | >>> onto = my_world.get_ontology("http://test.org/onto/").load()
76 |
77 | The World object can be used as a pseudo-dictionary for accessing entities using their IRI.
78 | (when working with several Worlds, this method replaces the IRIS global pseudo-dictionary):
79 |
80 | ::
81 |
82 | >>> my_world["http://test.org/onto/my_iri"]
83 |
84 | Finally, the reasoner can be executed on a specific World:
85 |
86 | ::
87 |
88 | >>> sync_reasoner(my_world)
89 |
90 |
91 | Working with RDFlib for performing SPARQL queries
92 | -------------------------------------------------
93 |
94 | Owlready2 uses an optimized RDF quadstore. This quadstore can also be accessed
95 | as an RDFlib graph as follows:
96 |
97 | ::
98 |
99 | >>> graph = default_world.as_rdflib_graph()
100 |
101 |
102 | In particular, the RDFlib graph can be used for performing SPARQL queries:
103 |
104 | ::
105 |
106 | >>> r = list(graph.query("""SELECT ?p WHERE {
107 | ?p .
108 | }"""))
109 |
110 |
111 |
112 |
113 | The results can be automatically converted to Python and Owlready using the .query_owlready() method instead of .query():
114 |
115 | ::
116 |
117 | >>> r = list(graph.query_owlready("""SELECT ?p WHERE {
118 | ?p .
119 | }"""))
120 |
121 |
122 | Owlready blank nodes can be created with the graph.BNode() method:
123 |
124 | ::
125 |
126 | >>> bn = graph.BNode()
127 | >>> with onto:
128 | ... graph.add((bn, rdflib.URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), rdflib.URIRef("http://www.w3.org/2002/07/owl#Class")))
129 |
--------------------------------------------------------------------------------
/test/crepes_et_galettes.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | ]>
10 |
11 |
12 |
19 |
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 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/test/test_owlxml.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | ]>
10 |
11 |
12 |
19 |
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 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Test
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 | #d2
154 | Test2
155 |
156 |
157 |
158 | xsd:string
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/test/test_owlxml_bug.owl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 | ]>
10 |
11 |
12 |
19 |
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 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Test
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 |
153 | #d2
154 | Test2
155 |
156 |
157 |
158 | xsd:string
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/doc/disjoint.rst:
--------------------------------------------------------------------------------
1 | Disjointness, open and local closed world reasoning
2 | ===================================================
3 |
4 | By default, OWL considers the world as 'open', *i.e.* everything that is not stated in the ontology is
5 | not 'false' but 'possible' (this is known as *open world assumption*).
6 | Therfore, things and facts that are 'false' or 'impossible' must be clearly stated as so in the ontology.
7 |
8 | Disjoint Classes
9 | ----------------
10 |
11 | Two (or more) Classes are disjoint if there is no Individual belonging to all these Classes (remember that,
12 | contrary to Python instances, an Individual can have several Classes, see :doc:`class`).
13 |
14 | A Classes disjointness is created with the AllDisjoint() function, which takes a list of Classes
15 | as parameter. In the example below, we have two Classes, Drug and ActivePrinciple, and we assert that they
16 | are disjoint (yes, we need to specify that explicitely -- sometimes ontologies seem a little dumb!).
17 |
18 | ::
19 |
20 | >>> from owlready2 import *
21 |
22 | >>> onto = get_ontology("http://test.org/onto.owl")
23 |
24 | >>> with onto:
25 | ... class Drug(Thing):
26 | ... pass
27 | ... class ActivePrinciple(Thing):
28 | ... pass
29 | ... AllDisjoint([Drug, ActivePrinciple])
30 |
31 |
32 | Disjoint Properties
33 | -------------------
34 |
35 | OWL also introduces Disjoint Properties.
36 | Disjoint Properties can also be created using AllDisjoint().
37 |
38 |
39 | Different Individuals
40 | ---------------------
41 |
42 | Two Individuals are different if they are distinct. In OWL, two Individuals might be considered as being actually
43 | the same, single, Individual, unless they are stated different.
44 | Difference is to Individuals what disjointness is to Classes.
45 |
46 | The following example creates two active principles and asserts that they are different (yes, we also need
47 | to state explicitely that acetaminophen and aspirin are not the same!)
48 |
49 | ::
50 |
51 | >>> acetaminophen = ActivePrinciple("acetaminophen")
52 | >>> aspirin = ActivePrinciple("aspirin")
53 |
54 | >>> AllDifferent([acetaminophen, aspirin])
55 |
56 | .. note::
57 |
58 | In Owlready2, AllDifferent is actually the same function as AllDisjoint -- the exact meaning depends on the
59 | parameters (AllDisjoint if you provide Classes, AllDifferent if you provide Instances,
60 | and disjoint Properties if you provide Properties).
61 |
62 |
63 | Querying and modifying disjoints
64 | --------------------------------
65 |
66 | The .disjoints() method returns a generator for iterating over AllDisjoint constructs involving the given Class
67 | or Property. For Individuals, .differents() behaves similarly.
68 |
69 | ::
70 |
71 | >>> for d in Drug.disjoints():
72 | ... print(d.entities)
73 | [onto.Drug, onto.ActivePrinciple]
74 |
75 | The 'entities' attribute of an AllDisjoint is writable, so you can modify the AllDisjoint construct by adding
76 | or removing entities.
77 |
78 | OWL also provides the 'disjointWith' and 'propertyDisjointWith' relations for pairwise disjoints (involving
79 | only two elements). Owlready2 exposes **all** disjoints as AllDisjoints, *including* those declared with
80 | the 'disjointWith' or 'propertyDisjointWith' relations. In the quad store (or when saving OWL files),
81 | disjoints involving 2 entities are defined using the 'disjointWith' or 'propertyDisjointWith' relations,
82 | while others are defined using AllDisjoint or AllDifferent.
83 |
84 |
85 | Closing Individuals
86 | -------------------
87 |
88 | The open world assumption also implies that the properties of a given Individual are not limited to the
89 | ones that are explicitely stated. For example, if you create a Drug Individual with a single Active
90 | Principle, it does not mean that it has *only* a single Active Principle.
91 |
92 | ::
93 |
94 | >>> with onto:
95 | ... class has_for_active_principle(Drug >> ActivePrinciple): pass
96 |
97 | >>> my_acetaminophen_drug = Drug(has_for_active_principle = [acetaminophen])
98 |
99 | In the example above, 'my_acetaminophen_drug' has an acetaminophen Active Principle (this fact is true) and it
100 | may have other Active Principle(s) (this fact is possible).
101 |
102 | If you want 'my_acetaminophen_drug' to be a Drug with acetaminophen and no other Active Principle, you have to
103 | state it explicitely using a restriction (see :doc:`restriction`):
104 |
105 | ::
106 |
107 | >>> my_acetaminophen_drug.is_a.append(has_for_active_principle.only(OneOf([acetaminophen])))
108 |
109 | Notice that we used OneOf() to 'turn' the acetaminophen Individual into a Class that we can use in the restriction.
110 |
111 | You'll quickly find that the open world assumption often leads to tedious and long lists
112 | of AllDifference and Restrictions. Hopefully, Owlready2 provides the close_world() function for automatically
113 | 'closing' an Individual. close_world() will automatically add ONLY restrictions as needed; it accepts an
114 | optional parameter: a list of the Properties to 'close' (defaults to all Properties whose domain is
115 | compatible with the Individual).
116 |
117 | ::
118 |
119 | >>> close_world(my_acetaminophen_drug)
120 |
121 |
122 | Closing Classes
123 | ---------------
124 |
125 | close_world() also accepts a Class. In this case, it closes the Class, its subclasses, and all their Individuals.
126 |
127 | By default, when close_world() is not called, the ontology performs **open world reasoning**.
128 | By selecting the Classes and the Individuals you want to 'close',
129 | the close_world() function enables **local closed world reasoning** with OWL.
130 |
131 | Closing an ontology
132 | -------------------
133 |
134 | Finally, close_world() also accepts an ontology. In this case, it closes all the Classes defined in the ontology.
135 | This corresponds to fully **closed world reasoning**.
136 |
137 |
--------------------------------------------------------------------------------
/test/Bench.java:
--------------------------------------------------------------------------------
1 | /*
2 | cd ./owlready2/hermit
3 | /usr/lib/jvm/java-7-openjdk/bin/javac -cp .:HermiT.jar ./org/semanticweb/HermiT/cli/CommandLine.java ./org/semanticweb/HermiT/Reasoner.java ./org/semanticweb/HermiT/hierarchy/HierarchyDumperFSS.java ./org/semanticweb/HermiT/hierarchy/InstanceManager.java
4 |
5 | javac -cp ./antibio_arcenciel/owlready_cas_dut_1/owlapi-3.4.3.jar ./owlready2/test/Bench.java
6 | java -cp ./antibio_arcenciel/owlready_cas_dut_1/owlapi-3.4.3.jar:./owlready2/test Bench > /dev/null
7 |
8 | Loading 11.229
9 | Listing 4.528
10 |
11 | */
12 |
13 | import java.io.*;
14 | import java.util.*;
15 |
16 | import org.semanticweb.owlapi.model.*;
17 | import org.semanticweb.owlapi.util.*;
18 | import org.semanticweb.owlapi.io.*;
19 | import org.semanticweb.owlapi.apibinding.*;
20 | import org.semanticweb.owlapi.vocab.*;
21 |
22 | class Bench {
23 | static int nb = 0;
24 |
25 | public static void main(String[] args) throws Exception {
26 |
27 | long t;
28 |
29 | OWLOntologyManager m = OWLManager.createOWLOntologyManager();
30 | OWLDataFactory df = OWLManager.getOWLDataFactory();
31 |
32 | t = (new Date().getTime());
33 |
34 | IRI iri = IRI.create("file:///home/jiba/telechargements/base_med/go.owl");
35 | //IRI iri = IRI.create("file:///home/jiba/telechargements/base_med/obi.owl");
36 | //IRI iri = IRI.create("file:///home/jiba/telechargements/base_med/vto.owl");
37 | //IRI iri = IRI.create("file:///home/jiba/telechargements/base_med/uberon.owl");
38 | //IRI iri = IRI.create("file:///home/jiba/src/owlready2/test/test.owl");
39 | OWLOntology o = m.loadOntologyFromOntologyDocument(iri);
40 |
41 | t = (new Date().getTime()) - t;
42 | System.err.print("Loading ");
43 | System.err.println(t / 1000.0f);
44 |
45 | /*
46 | File saveas = new File("/home/jiba/telechargements/base_med/go2.owl");
47 | OWLOntologyFormat format = m.getOntologyFormat(o);
48 | OWLXMLOntologyFormat owlxmlFormat = new OWLXMLOntologyFormat();
49 | if (format.isPrefixOWLOntologyFormat()) {
50 | owlxmlFormat.copyPrefixesFrom(format.asPrefixOWLOntologyFormat());
51 | }
52 | m.saveOntology(o, owlxmlFormat, IRI.create(saveas.toURI()));
53 |
54 | System.err.println("saved");
55 | */
56 |
57 |
58 |
59 | t = (new Date().getTime());
60 |
61 | /*
62 | int nb = 0;
63 | for (OWLClass cls : o.getClassesInSignature()) {
64 | nb += 1;
65 | System.out.println(cls_2_str(df, o, cls));
66 | Set superClasses = cls.getSuperClasses(o);
67 | for (OWLClassExpression desc : superClasses) {
68 | System.out.print(" is a ");
69 | if(desc instanceof OWLClass) {
70 | System.out.println(cls_2_str(df, o, (OWLClass) desc));
71 | }
72 | else if(desc instanceof OWLObjectSomeValuesFrom) {
73 | OWLObjectSomeValuesFrom some = (OWLObjectSomeValuesFrom) desc;
74 | Object prop = some.getProperty();
75 | Object fill = some.getFiller();
76 | if (prop instanceof OWLEntity)
77 | System.out.print (cls_2_str(df, o, (OWLEntity) prop));
78 | else
79 | System.out.print (prop);
80 | System.out.print (" some ");
81 | if (fill instanceof OWLEntity)
82 | System.out.println(cls_2_str(df, o, (OWLEntity) fill));
83 | else
84 | System.out.println(fill);
85 | }
86 | else {
87 | System.out.println(desc);
88 | }
89 | }
90 | }
91 | */
92 |
93 | recursive(df, o, df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/GO_0005575")), 0);
94 | recursive(df, o, df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/GO_0008150")), 0);
95 | recursive(df, o, df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/GO_0003674")), 0);
96 |
97 | System.err.print("NB ");
98 | System.err.println(nb);
99 |
100 | t = (new Date().getTime()) - t;
101 | System.err.print("Listing ");
102 | System.err.println(t / 1000.0f);
103 |
104 | Thread.sleep(40000);
105 | }
106 |
107 | public static void recursive(OWLDataFactory df, OWLOntology o, OWLClass cls, int depth) {
108 | String iri = cls.getIRI().toString();
109 | String name = iri.substring(iri.lastIndexOf("/") + 1, iri.length());
110 |
111 | OWLAnnotationProperty label = df.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL.getIRI());
112 |
113 | String tab = "";
114 | for (int i = 0; i < depth; i++) {
115 | tab += " ";
116 | }
117 |
118 | boolean ok = false;
119 | for (OWLAnnotation annotation : cls.getAnnotations(o, label)) {
120 | if (annotation.getValue() instanceof OWLLiteral) {
121 | OWLLiteral val = (OWLLiteral) annotation.getValue();
122 | System.out.println(tab + name + ":" + val.getLiteral());
123 | ok = true;
124 | break;
125 | }
126 | }
127 | if (ok == false) {
128 | System.out.println(tab + name);
129 | }
130 |
131 | nb += 1;
132 |
133 | Set subClasses = cls.getSubClasses(o);
134 | for (OWLClassExpression desc : subClasses) {
135 | if(desc instanceof OWLClass) {
136 | recursive(df, o, (OWLClass) desc, depth + 1);
137 | }
138 | }
139 | }
140 |
141 | public static String cls_2_str(OWLDataFactory df, OWLOntology o, OWLEntity cls) {
142 | String iri = cls.getIRI().toString();
143 | String name = iri.substring(iri.lastIndexOf("/") + 1, iri.length());
144 |
145 | OWLAnnotationProperty label = df.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL.getIRI());
146 |
147 | for (OWLAnnotation annotation : cls.getAnnotations(o, label)) {
148 | if (annotation.getValue() instanceof OWLLiteral) {
149 | OWLLiteral val = (OWLLiteral) annotation.getValue();
150 | return name + ":'" + val.getLiteral() + "'";
151 | }
152 | }
153 | return name;
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/pymedtermino2/icd10_french.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Owlready2
3 | # Copyright (C) 2019 Jean-Baptiste LAMY
4 | # LIMICS (Laboratoire d'informatique médicale et d'ingénierie des connaissances en santé), UMR_S 1142
5 | # University Paris 13, Sorbonne paris-Cité, Bobigny, France
6 |
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 |
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU Lesser General Public License for more details.
16 |
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with this program. If not, see .
19 |
20 |
21 | import sys, os, io, types, zipfile, urllib.request
22 | from collections import defaultdict, Counter
23 | from owlready2 import *
24 |
25 |
26 | def import_icd10_french(atih_data = "https://www.atih.sante.fr/plateformes-de-transmission-et-logiciels/logiciels-espace-de-telechargement/telecharger/gratuit/11616/456"):
27 | PYM = get_ontology("http://PYM/").load()
28 | ICD10 = PYM["ICD10"]
29 |
30 | print("Importing CIM10 from %s..." % atih_data)
31 | if atih_data.startswith("http:") or atih_data.startswith("https:"):
32 | f = urllib.request.urlopen(atih_data)
33 | f = io.BytesIO(f.read())
34 | else:
35 | f = open(atih_data, "rb")
36 |
37 | parents = []
38 |
39 | onto = get_ontology("http://atih/cim10/")
40 | with onto:
41 | class mco_had(AnnotationProperty): pass
42 | class psy (AnnotationProperty): pass
43 | class ssr (AnnotationProperty): pass
44 |
45 | with onto.get_namespace("http://PYM/SRC/"):
46 | ICD10_FRENCH = types.new_class("CIM10", (PYM["SRC"],))
47 | onto._set_obj_triple_spo (ICD10_FRENCH.storid, PYM.terminology.storid, PYM["SRC"].storid)
48 | onto._set_data_triple_spod(ICD10_FRENCH.storid, label.storid, "CIM10", "@fr")
49 |
50 | with onto.get_namespace("http://PYM/CIM10/"):
51 | for line in open(os.path.join(os.path.dirname(__file__), "icd10_french_group_name.txt")).read().split(u"\n"):
52 | line = line.strip()
53 | if line and not line.startswith("#"):
54 | code, term = line.split(" ", 1)
55 | icd10 = ICD10[code]
56 | if not icd10:
57 | icd10 = ICD10["%s.9" % code]
58 | if not icd10:
59 | if code == "B95-B98": icd10 = ICD10["B95-B97.9"]
60 | elif code == "G10-G14": icd10 = ICD10["G10-G13.9"]
61 | elif code == "J09-J18": icd10 = ICD10["J10-J18.9"]
62 | elif code == "K55-K64": icd10 = ICD10["K55-K63.9"]
63 | elif code == "O94-O99": icd10 = ICD10["O95-O99.9"]
64 |
65 | if icd10 is None:
66 | if not code in {"C00-C75", "V01-X59", "U00-U99", "U00-U49", "U82-U85", "U90-U99"}:
67 | print("WARNING: cannot align %s (%s) with ICD10 in UMLS!" % (code, term))
68 |
69 | start, end = code.split("-")
70 | end = "%s.99" % end
71 | for parent_start, parent_end, parent in parents:
72 | if (start >= parent_start) and (end <= parent_end):
73 | break
74 | else:
75 | if not code in {'F00-F99', 'H60-H95', 'E00-E90', 'R00-R99', 'L00-L99', 'O00-O99', 'C00-D48', 'M00-M99', 'U00-U99', 'S00-T98', 'K00-K93', 'G00-G99', 'I00-I99', 'H00-H59', 'N00-N99', 'V01-Y98', 'Q00-Q99', 'P00-P96', 'Z00-Z99', 'A00-B99', 'D50-D89', 'J00-J99'}:
76 | print("WARNING: cannot find parent for %s (%s)!" % (code, term))
77 | parent = ICD10_FRENCH
78 |
79 | icd10_french = types.new_class(code, (parent,))
80 | icd10_french.label = locstr(term, "fr")
81 | onto._set_obj_triple_spo(icd10_french.storid, PYM.terminology.storid, ICD10_FRENCH.storid)
82 | if icd10:
83 | icd10.unifieds = icd10.unifieds
84 | #with PYM:
85 | for cui in icd10.unifieds: cui.originals.append(icd10_french)
86 |
87 | parents.append((start, end, icd10_french))
88 |
89 |
90 | with zipfile.ZipFile(f, "r") as atih_zip:
91 | for line in atih_zip.open("LIBCIM10MULTI.TXT", "r"):
92 | if isinstance(line, bytes): line = line.decode("latin")
93 | line = line.strip()
94 | code, mco_had, ssr, psy, term_court, term = line.split("|")
95 | code = code.strip()
96 | if len(code) > 3: code = "%s.%s" % (code[:3], code[3:])
97 |
98 |
99 | if "+" in code:
100 | parent_code = code.split("+", 1)[0]
101 | else:
102 | parent_code = code[:-1]
103 | if parent_code.endswith("."): parent_code = code[:-2]
104 | parent = ICD10_FRENCH[parent_code]
105 |
106 | if not parent:
107 | code2 = code.split("+", 1)[0]
108 | for parent_start, parent_end, parent in reversed(parents):
109 | if (code2 >= parent_start) and (code2 <= parent_end):
110 | break
111 | else:
112 | print("WARNING: cannot find parent for %s (%s)!" % (code, term))
113 | parent = None
114 |
115 | icd10 = ICD10[code]
116 |
117 | if term.startswith("*** SU16 *** "): term = term.replace("*** SU16 *** ", "")
118 |
119 | icd10_french = types.new_class(code, (parent,))
120 | onto._set_obj_triple_spo(icd10_french.storid, PYM.terminology.storid, ICD10_FRENCH.storid)
121 | icd10_french.label = locstr(term, "fr")
122 | icd10_french.mco_had = [int(mco_had)]
123 | icd10_french.ssr = [ssr]
124 | icd10_french.psy = [int(psy)]
125 | if icd10:
126 | icd10_french.unifieds = icd10.unifieds
127 | #with PYM:
128 | for cui in icd10.unifieds: cui.originals.append(icd10_french)
129 |
130 | default_world.save()
131 |
132 |
--------------------------------------------------------------------------------
/disjoint.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Owlready2
3 | # Copyright (C) 2013-2019 Jean-Baptiste LAMY
4 | # LIMICS (Laboratoire d'informatique médicale et d'ingénierie des connaissances en santé), UMR_S 1142
5 | # University Paris 13, Sorbonne paris-Cité, Bobigny, France
6 |
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 |
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU Lesser General Public License for more details.
16 |
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with this program. If not, see .
19 |
20 | from owlready2.namespace import *
21 | from owlready2.entity import *
22 | from owlready2.prop import *
23 | from owlready2.class_construct import *
24 |
25 |
26 | class AllDisjoint(object):
27 | def __init__(self, entities, ontology = None, bnode = None):
28 | #if not CURRENT_NAMESPACES[-1] is None: self.ontology = CURRENT_NAMESPACES[-1].ontology
29 | #else: self.ontology = ontology or entities[0].namespace.ontology
30 | self.ontology = (CURRENT_NAMESPACES.get() and CURRENT_NAMESPACES.get()[-1]) or ontology or entities[0].namespace.ontology
31 |
32 | # For AllDisjoint, storid can be either:
33 | # * a blank node, when at least 3 entities are involved
34 | # * a triple, when only 2 entities, e.g. (entity1.storid, owl_disjointwith, entity2.storid)
35 |
36 | if isinstance(entities, int):
37 | assert isinstance(bnode, int)
38 | self.storid = bnode
39 | self._list_bnode = entities
40 | elif isinstance(entities, tuple):
41 | self.storid = entities
42 | else:
43 | self.storid = bnode
44 | self._list_bnode = None
45 | self.entities = self.Properties = self.individuals = CallbackList(entities, self, AllDisjoint._callback)
46 |
47 | if not LOADING: self._create_triples()
48 |
49 | def __getattr__(self, attr):
50 | if attr == "entities":
51 | if isinstance(self.storid, int):
52 | r = self.ontology._parse_list(self._list_bnode)
53 | else:
54 | r = [self.ontology.world._to_python(self.storid[0]), self.ontology.world._to_python(self.storid[2])]
55 | r = CallbackList(r, self, AllDisjoint._callback)
56 | setattr(self, attr,r)
57 | return r
58 | return super().__getattribute__(attr)
59 |
60 | def _callback(self, old):
61 | if self.ontology:
62 | self._destroy_triples()
63 | self._create_triples ()
64 |
65 | def _destroy_triples(self):
66 | if isinstance(self.storid, int):
67 | self.ontology._del_obj_triple_spo(self.storid, None, None)
68 | self.ontology._del_list(self._list_bnode)
69 | elif isinstance(self.storid, tuple):
70 | self.ontology._del_obj_triple_spo(*self.storid)
71 |
72 | def destroy(self): self._destroy_triples()
73 |
74 | def _create_triples(self):
75 | for entity in self.entities:
76 | if isinstance(entity, Construct): entity._set_ontology(self.ontology)
77 |
78 | if len(self.entities) == 2:
79 | if isinstance(self.entities[0], ThingClass):
80 | self.storid = (self.entities[0].storid, owl_disjointwith, self.entities[1].storid)
81 | self.ontology._add_obj_triple_spo(*self.storid)
82 | return
83 | elif isinstance(self.entities[0], PropertyClass):
84 | self.storid = (self.entities[0].storid, owl_propdisjointwith, self.entities[1].storid)
85 | self.ontology._add_obj_triple_spo(*self.storid)
86 | return
87 | # It seems that there is no 1-1 relation for individuals
88 | # => continue
89 |
90 | if len(self.entities) >= 2:
91 | if not isinstance(self.storid, int): self.storid = self.ontology.world.new_blank_node()
92 | if not self._list_bnode: self._list_bnode = self.ontology.world.new_blank_node()
93 |
94 | if isinstance(self.entities[0], ThingClass):
95 | self.ontology._add_obj_triple_spo(self.storid, rdf_type, owl_alldisjointclasses)
96 | self.ontology._add_obj_triple_spo(self.storid, owl_members, self._list_bnode)
97 |
98 | elif isinstance(self.entities[0], PropertyClass):
99 | self.ontology._add_obj_triple_spo(self.storid, rdf_type, owl_alldisjointproperties)
100 | self.ontology._add_obj_triple_spo(self.storid, owl_members, self._list_bnode)
101 |
102 | else: # Individuals
103 | self.ontology._add_obj_triple_spo(self.storid, rdf_type, owl_alldifferent)
104 | self.ontology._add_obj_triple_spo(self.storid, owl_distinctmembers, self._list_bnode)
105 |
106 | self.ontology._set_list(self._list_bnode, self.entities)
107 |
108 | def __repr__(self):
109 | if self.ontology != self.entities[0].namespace.ontology: onto = ", ontology = %s" % self.ontology
110 | else: onto = ""
111 | return "AllDisjoint([%s]%s)" % (", ".join(repr(Class) for Class in self.entities), onto)
112 |
113 | AllDifferent = AllDisjoint
114 |
115 |
116 | def partition(mother, children):
117 | mother.is_a.append(Or(children))
118 | AllDisjoint(children)
119 |
120 |
121 | # class DisjointUnion(LogicalClassConstruct):
122 | # _owl_op = owl_disjointunion
123 | # is_a = ()
124 |
125 | # def _satisfied_by(self, x):
126 | # for Class in self.Classes:
127 | # if Class._satisfied_by(x): return True
128 | # return False
129 |
130 | # def __repr__(self):
131 | # s = []
132 | # for x in self.Classes:
133 | # if isinstance(x, LogicalClassConstruct): s.append("(%s)" % x)
134 | # else: s.append(repr(x))
135 | # return "%s([%s])" % (self.__class__.__name__, ", ".join(s))
136 |
--------------------------------------------------------------------------------
/test/test_parser.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 |
3 | HERE = os.path.dirname(__file__)
4 |
5 | def rm(f):
6 | try: os.unlink(f)
7 | except: pass
8 |
9 |
10 | def do(c):
11 | #print(c)
12 | r = os.system(c)
13 | if r: raise Exception("Error when running:'%s'!" % c)
14 |
15 | def make_variants(orig_filename, force_variant = None):
16 | control(orig_filename)
17 |
18 | if (not force_variant) or (force_variant == "original"):
19 | print("Test %s %s ..." % (orig_filename, "original"))
20 | rm("/tmp/t.rdf")
21 | b = open(orig_filename, "rb").read()
22 | open("/tmp/t.rdf", "wb").write(b)
23 | yield "original"
24 |
25 | if (not force_variant) or (force_variant == "owlready2-ntriples"):
26 | print("Test %s %s ..." % (orig_filename, "owlready2-ntriples"))
27 | rm("/tmp/t.rdf")
28 | do("""python -c 'from owlready2 import *;\
29 | onto = get_ontology("file://%s").load();\
30 | onto.save("/tmp/t.rdf", format = "ntriples");\
31 | '""" % orig_filename)
32 | yield "owlready2-ntriples"
33 |
34 | if (not force_variant) or (force_variant == "owlready2-rdfxml"):
35 | print("Test %s %s ..." % (orig_filename, "owlready2-rdfxml"))
36 | rm("/tmp/t.rdf")
37 | do("""python -c 'from owlready2 import *;\
38 | onto = get_ontology("file://%s").load();\
39 | onto.save("/tmp/t.rdf", format = "rdfxml");\
40 | '""" % orig_filename)
41 | yield "owlready2-rdfxml"
42 |
43 | if (not force_variant) or (force_variant == "rapper-ntriples"):
44 | print("Test %s %s ..." % (orig_filename, "rapper-ntriples"))
45 | rm("/tmp/t.rdf")
46 | do("rapper %s > /tmp/t.rdf 2> /dev/null" % orig_filename)
47 | yield "rapper-ntriples"
48 |
49 | if (not force_variant) or (force_variant == "rapper-rdfxml"):
50 | print("Test %s %s ..." % (orig_filename, "rapper-rdfxml"))
51 | rm("/tmp/t.rdf")
52 | do("rapper %s -o rdfxml > /tmp/t.rdf 2> /dev/null" % orig_filename)
53 | yield "rapper-rdfxml"
54 |
55 | if (not force_variant) or (force_variant == "rapper-rdfxml-abbrev"):
56 | print("Test %s %s ..." % (orig_filename, "rapper-rdfxml-abbrev"))
57 | rm("/tmp/t.rdf")
58 | do("rapper %s -o rdfxml-abbrev > /tmp/t.rdf 2> /dev/null" % orig_filename)
59 | yield "rapper-rdfxml-abbrev"
60 |
61 | if (not force_variant) or (force_variant == "owlapi-rdfxml"):
62 | print("Test %s %s ..." % (orig_filename, "owlapi-rdfxml"))
63 | rm("/tmp/t.rdf")
64 | owlapi(orig_filename, "/tmp/t.rdf", "rdf")
65 | rapper("/tmp/t.rdf", "/tmp/control.nt")
66 | yield "owlapi-rdfxml"
67 |
68 | if (not force_variant) or (force_variant == "owlapi-owlxml"):
69 | print("Test %s %s ..." % (orig_filename, "owlapi-owlxml"))
70 | rm("/tmp/t.rdf")
71 | owlapi(orig_filename, "/tmp/t.rdf", "owl")
72 |
73 | owlapi("/tmp/t.rdf", "/tmp/control.rdf", "rdf")
74 | rapper("/tmp/control.rdf", "/tmp/control.nt")
75 | yield "owlapi-owlxml"
76 |
77 | def rapper(filename, dest):
78 | rm(dest)
79 | do("rapper %s -g > %s 2> /dev/null" % (filename, dest))
80 | b = open(dest, "rb").read()
81 | lb = b.split(b"\n")
82 | #ls = [i.replace(b"\\" + b"\"", b"\\\\" + b"\"").decode("unicode-escape").replace("\n", "\\n").replace("\\", "\\\\") for i in lb]
83 | ls = []
84 | for i in lb:
85 | if not i: continue
86 | s,p,o = i.split(None, 2)
87 | if o.startswith(b'"'):
88 | v, d = o[1:].rsplit(b'"', 1)
89 | v = v.decode("unicode-escape").replace('\\', '\\\\').replace("\n", "\\n").replace('"', '\\"').encode("utf8")
90 | i = b'%s %s "%s"%s' % (s, p, v, d)
91 | ls.append(i)
92 | s = b"\n".join(ls)
93 | open(dest, "wb").write(s)
94 |
95 |
96 | def owlapi(orig, dest, format):
97 | #do("java -cp ./antibio_arcenciel/owlready_cas_dut_1/owlapi-3.4.3.jar:%s/test Save %s %s %s 2> /dev/null" % (HERE, orig, format, dest))
98 | do("java -cp %s/../hermit/HermiT.jar:%s Save %s %s %s 2> /dev/null" % (HERE, HERE, orig, format, dest))
99 |
100 |
101 | def control(filename): rapper(filename, "/tmp/control.nt")
102 |
103 | def test(filename, variant):
104 | rm("/tmp/py.nt")
105 | rm("/tmp/py.rdf")
106 | #do("python ./owlready2/rdfxml_2_ntriples.py %s > /tmp/py.nt 2> /dev/null" % tmp_filename)
107 | do("""python -c 'from owlready2 import *;\
108 | onto = get_ontology("file:///tmp/t.rdf").load();\
109 | onto.save("/tmp/py.nt", format = "ntriples");\
110 | onto.save("/tmp/py.rdf", format = "rdfxml");\
111 | '""")
112 |
113 | rm("/tmp/log")
114 | do("python %s/../ntriples_diff.py /tmp/control.nt /tmp/py.nt > /tmp/log" % HERE)
115 | s = open("/tmp/log").read()
116 | if s.strip() != "":
117 | print(" FAILED (ntriples)")
118 | return 0
119 |
120 | rm("/tmp/py.nt")
121 | rapper("/tmp/py.rdf", "/tmp/py.nt")
122 |
123 | rm("/tmp/log")
124 | do("python %s/../ntriples_diff.py /tmp/control.nt /tmp/py.nt > /tmp/log" % HERE)
125 | s = open("/tmp/log").read()
126 | if s.strip() != "":
127 | print(" FAILED (rdfxml)")
128 | return 0
129 |
130 | return 1
131 |
132 |
133 | if len(sys.argv) > 2:
134 | rdf_files = [sys.argv[1]]
135 | force_variant = sys.argv[2]
136 |
137 | elif len(sys.argv) > 1:
138 | rdf_files = [sys.argv[1]]
139 | force_variant = None
140 |
141 | else:
142 | rdf_files = [
143 | "/home/jiba/src/owlready2/test/test.owl",
144 | "/home/jiba/src/owlready2/test/test_ns.owl",
145 | "/home/jiba/src/owlready2/test/test_breakline.owl",
146 | "/home/jiba/telechargements/base_med/aeo.owl",
147 | "/home/jiba/telechargements/base_med/agro.owl",
148 | "/home/jiba/telechargements/base_med/bfo.owl",
149 | "/home/jiba/telechargements/base_med/bfo-1.1.owl",
150 | "/home/jiba/telechargements/base_med/obi.owl",
151 | "/home/jiba/telechargements/base_med/uberon.owl",
152 | "/home/jiba/telechargements/base_med/vto.owl",
153 | "/home/jiba/telechargements/base_med/go.owl",
154 | ]
155 | force_variant = None
156 |
157 |
158 | nb_ok = nb_test = 0
159 | for filename in rdf_files:
160 | for variant in make_variants(filename, force_variant):
161 | nb_test += 1
162 | nb_ok += test(filename, variant)
163 |
164 | print("%s/%s tests passed" % (nb_ok, nb_test))
165 |
166 |
167 |
--------------------------------------------------------------------------------
/test/catalog-v001.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Owlready2
3 | # Copyright (C) 2013-2019 Jean-Baptiste LAMY
4 | # LIMICS (Laboratoire d'informatique médicale et d'ingénierie des connaissances en santé), UMR_S 1142
5 | # University Paris 13, Sorbonne paris-Cité, Bobigny, France
6 |
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 |
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU Lesser General Public License for more details.
16 |
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with this program. If not, see .
19 |
20 | VERSION = "0.25"
21 |
22 | JAVA_EXE = "java"
23 |
24 | from owlready2.base import *
25 | #_render_func = default_render_func
26 |
27 | from owlready2.namespace import *
28 | from owlready2.entity import *
29 | from owlready2.prop import *
30 | from owlready2.prop import _FUNCTIONAL_FOR_CACHE
31 | from owlready2.individual import *
32 | from owlready2.class_construct import *
33 | from owlready2.disjoint import *
34 | from owlready2.annotation import *
35 | from owlready2.reasoning import *
36 | from owlready2.reasoning import _keep_most_specific
37 | from owlready2.close import *
38 |
39 | import owlready2.namespace, owlready2.entity, owlready2.prop, owlready2.class_construct, owlready2.triplelite
40 | owlready2.triplelite.Or = Or
41 | owlready2.namespace.EntityClass = EntityClass
42 | owlready2.namespace.ThingClass = ThingClass
43 | owlready2.namespace.PropertyClass = PropertyClass
44 | owlready2.namespace.AnnotationPropertyClass = AnnotationPropertyClass
45 | owlready2.namespace.ObjectPropertyClass = ObjectPropertyClass
46 | owlready2.namespace.DataPropertyClass = DataPropertyClass
47 | owlready2.namespace.ObjectProperty = ObjectProperty
48 | owlready2.namespace.DataProperty = DataProperty
49 | owlready2.namespace.AnnotationProperty = AnnotationProperty
50 | owlready2.namespace.Thing = Thing
51 | owlready2.namespace.Property = Property
52 | owlready2.namespace.Or = Or
53 | owlready2.namespace.And = And
54 | owlready2.namespace.Not = Not
55 | owlready2.namespace.Restriction = Restriction
56 | owlready2.namespace.OneOf = OneOf
57 | owlready2.namespace.FusionClass = FusionClass
58 | owlready2.namespace.AllDisjoint = AllDisjoint
59 | owlready2.namespace.ConstrainedDatatype = ConstrainedDatatype
60 | owlready2.namespace.Inverse = Inverse
61 | owlready2.namespace.IndividualValueList = IndividualValueList
62 | owlready2.entity.Thing = Thing
63 | owlready2.entity.Nothing = Nothing
64 | owlready2.entity.Construct = Construct
65 | owlready2.entity.And = And
66 | owlready2.entity.Or = Or
67 | owlready2.entity.Not = Not
68 | owlready2.entity.OneOf = OneOf
69 | owlready2.entity.Restriction = Restriction
70 | owlready2.entity.ObjectPropertyClass= ObjectPropertyClass
71 | owlready2.entity.ObjectProperty = ObjectProperty
72 | owlready2.entity.DataProperty = DataProperty
73 | owlready2.entity.AnnotationProperty = AnnotationProperty
74 | owlready2.entity.ReasoningPropertyClass = ReasoningPropertyClass
75 | owlready2.entity.FunctionalProperty = FunctionalProperty
76 | #owlready2.entity.ValueList = ValueList
77 | owlready2.entity.AllDisjoint = AllDisjoint
78 | owlready2.entity.Inverse = Inverse
79 | owlready2.entity._FUNCTIONAL_FOR_CACHE = _FUNCTIONAL_FOR_CACHE
80 | owlready2.entity._property_value_restrictions = owlready2.prop._property_value_restrictions
81 | owlready2.entity._inherited_properties_value_restrictions = owlready2.prop._inherited_properties_value_restrictions
82 | owlready2.disjoint.Or = Or
83 | owlready2.prop.Restriction = Restriction
84 | owlready2.prop.ConstrainedDatatype = ConstrainedDatatype
85 | owlready2.prop.Construct = Construct
86 | owlready2.prop.AnnotationProperty = AnnotationProperty
87 | owlready2.prop.Thing = Thing
88 | owlready2.prop.PropertyChain = PropertyChain
89 | owlready2.prop._check_superclasses = True
90 |
91 | owlready2.prop.ThingClass = ThingClass
92 | owlready2.prop.And = And
93 | owlready2.prop.Or = Or
94 | owlready2.prop.OneOf = OneOf
95 | owlready2.annotation.Construct = Construct
96 |
97 | owlready2.individual._keep_most_specific = _keep_most_specific
98 | owlready2.individual.Construct = Construct
99 | owlready2.individual.TransitiveProperty = TransitiveProperty
100 | owlready2.individual.SymmetricProperty = SymmetricProperty
101 | owlready2.individual.ReflexiveProperty = ReflexiveProperty
102 | owlready2.individual.InverseFunctionalProperty = InverseFunctionalProperty
103 | owlready2.individual.AnnotationPropertyClass = AnnotationPropertyClass
104 | owlready2.class_construct.Thing = Thing
105 | owlready2.class_construct.ThingClass = ThingClass
106 | owlready2.class_construct.EntityClass = EntityClass
107 |
108 | #owlready2.reasoning.Construct = Construct
109 |
110 | del owlready2
111 |
112 | from owlready2.rule import *
113 |
114 | LOADING.__exit__()
115 |
116 | # Not real property
117 | del owl_world._props["Property"]
118 | del owl_world._props["ObjectProperty"]
119 | del owl_world._props["DatatypeProperty"]
120 | del owl_world._props["FunctionalProperty"]
121 | del owl_world._props["InverseFunctionalProperty"]
122 | del owl_world._props["TransitiveProperty"]
123 | del owl_world._props["SymmetricProperty"]
124 | del owl_world._props["AsymmetricProperty"]
125 | del owl_world._props["ReflexiveProperty"]
126 | del owl_world._props["IrreflexiveProperty"]
127 | del owl_world._props["AnnotationProperty"]
128 |
129 | default_world = IRIS = World()
130 | get_ontology = default_world.get_ontology
131 | get_namespace = default_world.get_namespace
132 |
133 |
134 | def default_render_func(entity):
135 | if isinstance(entity.storid, int) and (entity.storid < 0): return "_:%s" % (-entity.storid)
136 | return "%s.%s" % (entity.namespace.name, entity.name)
137 |
138 | def set_render_func(func):
139 | type.__setattr__(EntityClass, "__repr__", func)
140 | type.__setattr__(Thing , "__repr__", func)
141 |
142 | set_render_func(default_render_func)
143 |
--------------------------------------------------------------------------------