OWLClass clsA = df.getOWLClass(IRI.create(pizza_iri + "#A")); OWLClass clsB = df.getOWLClass(IRI.create(pizza_iri + "#B")); // Now create the axiom OWLAxiom axiom = df.getOWLSubClassOfAxiom(clsA, clsB); // add the axiom to the ontology. AddAxiom addAxiom = new AddAxiom(o, axiom); // We now use the manager to apply the change m.applyChange(addAxiom);
Brain brain = new Brain(); //Add the OWL classes brain.addClass("Nucleus"); brain.addClass("Cell"); //Add the OWL object property brain.addObjectProperty("part-of"); //Assert the axiom brain.subClassOf("Nucleus", "part-of some Cell");
(defontology o)
Class: o:A Annotations: rdfs:label "A"@en, rdfs:comment "A is a kind of thing."@en
(defclass A :label "A" :comment "A is a kind of thing.")
:colon and not colon:
:super rather that SubClassOf:
:super not :SubPropertyOf)
sub meaning ontologies can be built bottom up or Top-down.
(defclass B :super A :label "B")
> c(1,2,3) + 4 [1] 5 6 7
(defoproperty r) (defclass C :super (owl-some r A B))
C some r A
C some r B
Class: o:C SubClassOf: o:r some o:B, o:r some o:A
some-only the most common
(defclass D :super (some-only r A B))
n+2) axioms
Class: o:D SubClassOf: o:r some o:A, o:r some o:B, o:r only (o:A or o:B)
(defn and-not [a b] (owl-and a (owl-not b))) (defn some-and-not [r a b] (owl-some r (and-not a b))) (defclass E :super (some-and-not r A B))
Class: o:E SubClassOf: o:r some (o:A or (not (o:B)))
F has three subclasses
(defclass F :equivalent (owl-some r (owl-or A B))) ;; #{} (subclasses F) (reasoner-factory :hermit) ;; #{C D E} (isubclasses F)
git clone https://github.com/phillord/tawny-tutorial.git
lein run
The Tawny Tutorial is Installed and Ready
lein edit
Catnip running on http://localhost:nnnn
src/lisbon/hello.clj
lisbon.hello
hello
(ns lisbon.hello) (def hello "hello world")
hello)
hello to find it’s value (prosaically "hello world")
Build a Hello World Ontology!
src/lisbon/onto_hello.clj)
src/lisbon/onto_hello_s.clj)
_ in file name is - in namespace
:use makes tawny.owl namespace available
(ns lisbon.onto-hello (:use [tawny.owl]))
defontology statement
hello is a new variable
(defontology hello :iri "http://www.w3id.org/ontolink/tutorial/hello")
defclass statement
()
Hello is also a variable
Hello and hello are different
(defclass Hello)
defoproperty
o to distinguish annotation and datatype property
defclass and defoproperty take a number of frames
(defoproperty hasObject) (defclass World)
:super says "everything that follows is a super class"
HelloWorld has a super which is Hello
owl-some is the existential operator
(defclass HelloWorld :super Hello (owl-some hasObject World))
owl-some rather than some.
only and not owl-only
clojure.core
(owl-some hasObject World) (only hasObject World)
&&, || and !
owl-only)
tawny.english.
o.omn either in Catnip, a text editor or Protege to check
(save-ontology "o.omn" :omn)
refine
defclass form and re-evaluate
:label and :comment add annotations using OWL built-in
:annotation is general purpose frame
(refine HelloWorld :label "Hello World" :comment "Hello World is a kind of greeting directed generally at everything." :annotation (label "Olá mundo" "pt"))
lisbon/amino_acid_tree.clj
lisbon/amino_acid_tree_s.clj
(ns lisbon.amino-acid-tree (:use [tawny.owl]))
(defontology aa) (defclass AminoAcid) (defclass Alanine :super AminoAcid) (defclass Arginine :super AminoAcid) (defclass Asparagine :super AminoAcid) ;; and the rest...
Asparagine is not the same as Alanine or Arginine
(defclass Alanine :super AminoAcid :disjoint Arginine Asparagine)
Arginine to this
(defclass Arginine :super AminoAcid :disjoint Alanine Asparagine)
as-subclasses form
AminoAcid as super to all arguments
(defclass AminoAcid) (as-subclasses AminoAcid (defclass Alanine) (defclass Arginine) (defclass Asparagine) ;; and the rest... )
:disjoint keyword
(defclass AminoAcid) (as-subclasses AminoAcid :disjoint (defclass Alanine) (defclass Arginine) (defclass Asparagine) ;; and the rest... )
(defclass AminoAcid) (as-subclasses AminoAcid :disjoint :cover (defclass Alanine) (defclass Arginine) (defclass Asparagine) (defclass Aspartate) (defclass Cysteine) (defclass Glutamate) (defclass Glutamine) (defclass Glycine) (defclass Histidine) (defclass Isoleucine) (defclass Leucine) (defclass Lysine) (defclass Methionine) (defclass Phenylalanine) (defclass Proline) (defclass Serine) (defclass Threonine) (defclass Tryptophan) (defclass Tyrosine) (defclass Valine))
Class: aa:AminoAcid EquivalentTo: aa:Alanine or aa:Arginine or aa:Asparagine or aa:Aspartate or aa:Cysteine or aa:Glutamate or aa:Glutamine or aa:Glycine or aa:Histidine or aa:Isoleucine or aa:Leucine or aa:Lysine or aa:Methionine or aa:Phenylalanine or aa:Proline or aa:Serine or aa:Threonine or aa:Tryptophan or aa:Tyrosine or aa:Valine DisjointClasses: aa:Alanine, aa:Arginine, aa:Asparagine, aa:Aspartate, aa:Cysteine, aa:Glutamate, aa:Glutamine, aa:Glycine, aa:Histidine, aa:Isoleucine, aa:Leucine, aa:Lysine, aa:Methionine, aa:Phenylalanine, aa:Proline, aa:Serine, aa:Threonine, aa:Tryptophan, aa:Tyrosine, aa:Valine
:use clause means "use both tawny.owl and tawny.pattern".
(ns lisbon.amino-acid-props (:use [tawny owl pattern]))
(defontology aa) (defclass AminoAcid)
(defclass Size) (defoproperty hasSize :domain AminoAcid :range Size :characteristic :functional)
(as-subclasses Size :disjoint :cover (defclass Tiny) (defclass Small) (defclass Large))
(as-subclasses AminoAcid :disjoint :cover (defclass Alanine :super (owl-some hasSize Tiny)) (defclass Arginine :super (owl-some hasSize Large)) (defclass Asparagine :super (owl-some hasSize Small)))
Charge using the same pattern as Size.
(defclass Charge) (defoproperty hasCharge :domain AminoAcid :range Charge :characteristic :functional) (as-subclasses Charge :disjoint :cover (defclass Positive) (defclass Neutral) (defclass Negative))
hasCharge
(as-facet hasCharge Positive Neutral Negative)
refine although could just alter the code
(facet Neutral) rather than (owl-some hasCharge Neutral)
(refine Alanine :super (facet Neutral)) (refine Arginine :super (facet Positive)) (refine Asparagine :super (facet Neutral))
Hydrophobicity
(defclass Hydrophobicity) (defoproperty hasHydrophobicity :domain AminoAcid :range Hydrophobicity :characteristic :functional) (as-subclasses Hydrophobicity :disjoint :cover (defclass Hydrophobic) (defclass Hydrophilic)) (as-facet hasHydrophobicity Hydrophilic Hydrophobic)
(defclass Polarity) (defoproperty hasPolarity) (as-subclasses Polarity :disjoint :cover (defclass Polar) (defclass NonPolar)) (as-facet hasPolarity Polar NonPolar)
facet broadcasts
(refine Alanine :super (facet Hydrophobic NonPolar)) (refine Arginine :super (facet Hydrophilic Polar)) (refine Asparagine :super (facet Hydrophilic Polar))
Class: aa:Alanine SubClassOf: aa:hasCharge some aa:Neutral, aa:AminoAcid, aa:hasSize some aa:Tiny, aa:hasHydrophobicity some aa:Hydrophobic, aa:hasPolarity some aa:NonPolar
Polarity was wrong)
tawny.pattern
use it here
(ns lisbon.amino-acid-pattern (:use [tawny owl pattern]))
(defontology aa) (defclass AminoAcid)
defpartition defines that we will have a partition
[Tiny Small Large] are the values
hasSize is implicit — it will be created
(defpartition Size [Tiny Small Large] :domain AminoAcid)
ObjectProperty: aa:hasSize Domain: aa:AminoAcid Range: aa:Size Characteristics: Functional Class: aa:Size EquivalentTo: aa:Large or aa:Small or aa:Tiny
(defpartition Charge [Positive Neutral Negative] :domain AminoAcid) (defpartition Hydrophobicity [Hydrophobic Hydrophilic] :domain AminoAcid) (defpartition Polarity [Polar NonPolar] :domain AminoAcid) (defpartition SideChainStructure [Aromatic Aliphatic] :domain AminoAcid)
defpartition also applies the as-facet function
facet also
(as-subclasses AminoAcid (defclass Alanine :super (facet Neutral Hydrophobic NonPolar Aliphatic Tiny)) (defclass Arginine :super (facet Positive Hydrophilic Polar Aliphatic Large)) (defclass Asparagine :super (facet Neutral Hydrophilic Polar Aliphatic Small)) (defclass Aspartate :super (facet Negative Hydrophilic Polar Aliphatic Small)) ;; and the rest )
A rather than "A")
tawny.obo later to show numeric IDs
clojure.string is for string manipulation.
(ns lisbon.whats-in-a-name (:use [tawny owl obo]) (:require [clojure.string :as s))
:ontology frame
(defontology o) ;; => #<OWLClassImpl <8d9d3120-d374-4ffb-99d8-ffd93a7d5fdd#o#A>> (defclass A :ontology o)
:iri frame for our second ontology
(defontology i :iri "http://www.w3id.org/ontolink/example/i") ;; => #<OWLClassImpl <http://www.w3id.org/ontolink/example/i#B>> (defclass B :ontology i)
:iri-gen frame to supply a function
(defontology r :iri "http://www.w3id.org/ontolink/example/r" :iri-gen (fn [ont name] (iri (str (as-iri ont) "#" (s/reverse name))))) ;; => #<OWLClassImpl <http://www.w3id.org/ontolink/example/r#EDC>> (defclass CDE :ontology r)
(fn [ont name] ;; <1> (iri ;; <2> (str ;; <3> (as-iri ont) ;; <4> "#" ;; <5> (s/reverse name)))) ;; <6>
This is the first function we have seen so, we go through it in detail
Create an anonymous function, with parameters ont and name
Create an IRI object from the string
Concatentate all arguments
Get the Ontology IRI
"#"
Reverse the name passed in!
(defclass GO:00004324 :super (owl-some RO:0000013 GO:00003143) :annotation (annotation IAO:0504303 "Transporters are..."))
(defontology obo :iri "http://www.w3id.org/ontolink/example/obo" :iri-gen tawny.obo/obo-iri-generate)
(tawny.obo/obo-restore-iri obo "./src/lisbon/whats_in_a_name.edn")
;; => #<OWLClassImpl <http://purl.obolibrary.org/obo/EXAM_000003>> (defclass F :ontology obo) ;; => #<OWLClassImpl <http://purl.obolibrary.org/obo/EXAM_000002>> (defclass G :ontology obo) ;; => #<OWLObjectPropertyImpl <http://purl.obolibrary.org/obo/EXAM_000001>> (defoproperty ro :ontology obo)
;; => #<OWLClassImpl <http://purl.org/ontolink/preiri/#4b463bc1-414b-4730-89a3-7ff72902c744>> (defclass H :ontology obo)
obo-restore-iri line above reads this file
("ro" "http://purl.obolibrary.org/obo/EXAM_000001" "G" "http://purl.obolibrary.org/obo/EXAM_000002" "F" "http://purl.obolibrary.org/obo/EXAM_000003")
;; this stores any new IDs we have created (comment (tawny.obo/obo-store-iri obo "./src/lisbon/whats_in_a_name.edn"))
;; this coins permanent IDS, in a controlled process! (comment (tawny.obo/obo-generate-permanent-iri "./src/lisbon/whats_in_a_name.edn" "http://purl.obolibrary.org/obo/EXAM_"))
iri-gen function takes a string not a symbol!
;; String building! (defontology s) (owl-class "J" :ontology s) (object-property "r" :ontology s) (owl-class "K" :ontology s :super (owl-some "r" "J"))
r nor J have been defined
(comment (owl-class "L" :ontology s :super (owl-some r J)))
(owl-class "M" :ontology s :super "L")
Class: s:M SubClassOf: s:L Class: s:L
(ns lisbon.abc (:use [tawny.owl])) (defontology abc :iri "http://www.w3id.org/ontolink/example/abc.owl") (defclass A) (defclass B) (defclass C)
use many times before
use'd like any other
require
(ns lisbon.use-abc (:use [tawny.owl]) (:require [lisbon.abc]))
import function and it does not do the same thing.
(defontology useabc) (owl-import lisbon.abc/abc)
iri function.
(defclass MyA :super (iri "http://www.w3id.org/ontolink/example/abc.owl#A"))
require statement also allows us to use symbols
lisbon.abc
B.
(defclass MyB :super lisbon.abc/B)
Class: useabc:MyA SubClassOf: abc:A Class: useabc:MyB SubClassOf: abc:B
require or use is a part of Clojure
owl-import
abc.owl was developed in Tawny-OWL
(ns lisbon.read-abc-s (:use [tawny.owl]) (:require [tawny.read]))
owl-import a IRI
abcother.owl has been saved locally
(tawny.read/defread abc :iri "http://www.w3id.org/ontolink/example/abcother.owl" :location (tawny.owl/iri (clojure.java.io/resource "abcother.owl")))
(defontology myABC) (owl-import abc)
(defclass MyA :super A) (defclass MyB :super B)
tawny.owl through an alias
(ns lisbon.autosave (:require [tawny.owl :as o]) (:import [org.semanticweb.owlapi.model.OWLOntologyChangeListener]))
atom and change that
(def auto-save-listener "The current listener for handling auto-saves or nil." (atom nil))
(defn auto-save "Autosave the current ontology everytime any change happens." ([o filename format] (let [listener (proxy [org.semanticweb.owlapi.model.OWLOntologyChangeListener] [] (ontologiesChanged[l] (o/save-ontology o filename format)))] (reset! auto-save-listener listener) (.addOntologyChangeListener (o/owl-ontology-manager) listener) listener)))
o, filename, format are closed over
(proxy [org.semanticweb.owlapi.model.OWLOntologyChangeListener] [] (ontologiesChanged[l] (o/save-ontology o filename format)))
(reset! auto-save-listener listener)
o/owl-ontology-manager function returns an OWLOntologyManager
. syntax to call methods
addOntologyChangeListener on the manager
listener as an argument
(.addOntologyChangeListener (o/owl-ontology-manager) listener)
@ dereferences the atom
(defn auto-save-off "Stop autosaving ontologies." [] (when @auto-save-listener (.removeOntologyChangeListener (o/owl-ontology-manager) @auto-save-listener)))
auto-save function in tawny.repl
on-change function
(ns lisbon.amino-acid-build (:use [tawny owl pattern reasoner util]))
(defontology aabuild) (defclass AminoAcid) (defclass PhysicoChemicalProperty) (defpartition Size [Tiny Small Large] :domain AminoAcid :super PhysicoChemicalProperty) (defpartition Charge [Positive Neutral Negative] :domain AminoAcid :super PhysicoChemicalProperty) (defpartition Hydrophobicity [Hydrophobic Hydrophilic] :domain AminoAcid :super PhysicoChemicalProperty) (defpartition Polarity [Polar NonPolar] :domain AminoAcid :super PhysicoChemicalProperty) (defpartition SideChainStructure [Aromatic Aliphatic] :domain AminoAcid :super PhysicoChemicalProperty)
defdontfn gives default ontology handling
& properties is variadic or "one or more args".
owl-class function does NOT define a new variable
(defdontfn amino-acid [o entity & properties] (owl-class o entity :super (facet properties)))
defentity
(defentity defaminoacid "Defines a new amino acid." 'amino-acid)
map
->Named packages name and entity together
(defdontfn amino-acids [o & definitions] (map (fn [[entity & properties]] ;; need the "Named" constructor here (->Named entity (amino-acid o entity properties))) definitions))
(defmacro defaminoacids [& definitions] `(tawny.pattern/intern-owl-entities (apply amino-acids (tawny.util/name-tree ~definitions))))
:cover
(as-subclasses AminoAcid :disjoint :cover (defaminoacids [Alanine Neutral Hydrophobic NonPolar Aliphatic Tiny] [Arginine Positive Hydrophilic Polar Aliphatic Large] [Asparagine Neutral Hydrophilic Polar Aliphatic Small] [Aspartate Negative Hydrophilic Polar Aliphatic Small] [Cysteine Neutral Hydrophobic Polar Aliphatic Small] [Glutamate Negative Hydrophilic Polar Aliphatic Small] [Glutamine Neutral Hydrophilic Polar Aliphatic Large] [Glycine Neutral Hydrophobic NonPolar Aliphatic Tiny] [Histidine Positive Hydrophilic Polar Aromatic Large] [Isoleucine Neutral Hydrophobic NonPolar Aliphatic Large] [Leucine Neutral Hydrophobic NonPolar Aliphatic Large] [Lysine Positive Hydrophilic Polar Aliphatic Large] [Methionine Neutral Hydrophobic NonPolar Aliphatic Large] [Phenylalanine Neutral Hydrophobic NonPolar Aromatic Large] [Proline Neutral Hydrophobic NonPolar Aliphatic Small] [Serine Neutral Hydrophilic Polar Aliphatic Tiny] [Threonine Neutral Hydrophilic Polar Aliphatic Tiny] [Tryptophan Neutral Hydrophobic NonPolar Aromatic Large] [Tyrosine Neutral Hydrophobic Polar Aromatic Large] [Valine Neutral Hydrophobic NonPolar Aliphatic Small]))
Small facet is a SmallAminoAcid
(defclass SmallAminoAcid :equivalent (facet Small))
(defclass SmallPolarAminoAcid :equivalent (owl-and (facet Small Polar))) (defclass LargeNonPolarAminoAcid :equivalent (owl-and (facet Large NonPolar)))
(defn amino-acid-def [partition-values] (owl-class (str (clojure.string/join (map #(.getFragment (.getIRI %)) partition-values)) "AminoAcid") :equivalent (owl-and (facet partition-values))))
(defn cart [colls] (if (empty? colls) '(()) (for [x (first colls) more (cart (rest colls))] (cons x more))))
amino-acid-def function on cartesian product
(doall (map amino-acid-def ;; kill the empty list (rest (map #(filter identity %) ;; combination of all of them (cart ;; list of values for each partitions plus nil ;; (so we get shorter versions also!) (map #(cons nil (seq (direct-subclasses %))) ;; all our partitions (seq (direct-subclasses PhysicoChemicalProperty))))))))
(reasoner-factory :hermit) (consistent?)
AminoAcid
(count (subclasses AminoAcid)) (count (isubclasses AminoAcid))
(coherent?) (count (unsatisfiable))
(save-ontology "o.owl" :owl)
Negative and Hydrophobic)
(count (isubclasses SmallAminoAcid))
(count (filter #(not (.isDefined % aabuild)) (isubclasses SmallAminoAcid)))
:super? why not :subclass?
SubClassOf axiom between Man and Person with a comment.
(defclass Man :super (annotate Person (owl-comment "States that every man is a person")))
(label "Ciao" "it")
(defn etichetta [l] (label l "it"))
tawny.polyglot to use property bundles
tawny.memorize to remember mappings
tawny.render can perform a syntactic transformation
:super? why not :subclass?SubClassOf:
:super for the same purpose!
A has :frame B
A is a SubClassOf: B