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