diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37e5321 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Intellij + +*.iml +.idea + +.ipynb_checkpoints/ + +# virtualenv +env/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc6bcbd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +FROM openjdk:11.0.3-jdk +MAINTAINER Rui de Klerk + +# Dockerfile copied and adapted from Spencer Park: https://github.com/SpencerPark/ijava-binder/blob/master/Dockerfile + +RUN apt-get update +RUN apt-get install -y python3-pip + +# add requirements.txt, written this way to gracefully ignore a missing file +COPY . . +RUN ([ -f requirements.txt ] \ + && pip3 install --no-cache-dir -r requirements.txt) \ + || pip3 install --no-cache-dir jupyter jupyterlab + +USER root + +# Download the kernel release +RUN curl -L https://github.com/SpencerPark/IJava/releases/download/v1.3.0/ijava-1.3.0.zip > ijava-kernel.zip + +# Unpack and install the kernel +RUN unzip ijava-kernel.zip -d ijava-kernel \ + && cd ijava-kernel \ + && python3 install.py --sys-prefix + +# -- WIP -- +# Download Apache Jena +#RUN curl -L http://mirrors.up.pt/pub/apache/jena/binaries/apache-jena-3.11.0.zip > apache-jena-3.11.0.zip + +# Unpack and install Jena +#RUN unzip apache-jena-3.11.0.zip -d apache-jena + +# Download Apache Jena Fuseki +#RUN curl -L http://mirrors.up.pt/pub/apache/jena/binaries/apache-jena-fuseki-3.11.0.zip > apache-jena-fuseki-3.11.0.zip + +# Unpack and install Apache Jena Fuseki +#RUN unzip apache-jena-fuseki-3.11.0.zip -d fuseki +# -- WIP -- + +# Set up the user environment + +#ENV IJAVA_CLASSPATH apache-jena/lib/* ; fuseki/lib/* + +ENV NB_USER jovyan +ENV NB_UID 1000 +ENV HOME /home/$NB_USER + +# -- WIP -- +#RUN java -classpath apache-jena/lib/* ;\ +# fuseki/lib/* +# -- WIP -- + +RUN adduser --disabled-password \ + --gecos "Default user" \ + --uid $NB_UID \ + $NB_USER + +COPY . $HOME +RUN chown -R $NB_UID $HOME + +USER $NB_USER + +# Launch the notebook server +WORKDIR $HOME +CMD ["jupyter", "notebook", "--ip", "0.0.0.0"] \ No newline at end of file diff --git a/Java Notebooks/3rdPartyDependency.ipynb b/Java Notebooks/3rdPartyDependency.ipynb new file mode 100644 index 0000000..e48b6ff --- /dev/null +++ b/Java Notebooks/3rdPartyDependency.ipynb @@ -0,0 +1,199 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3rd Party Dependencies in an IJava Notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The recommended way to add a dependency is through one of the IJava magics. This way all dependencies are visible in the notebook to make them more portable for others to use. If the dependencies is available via maven then one of the maven magics should be used but if that isn't the case the `%jars` magic is another option.\n", + "\n", + "For some additional information see https://github.com/SpencerPark/IJava/blob/7f5aa9ab858859a010fd228364b080606399ae60/docs/magics.md." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### %jars\n", + "\n", + "This _line magic_ takes a space separated list of simple glob patterns for resolving jar files. For example we can add all the jars in `/usr/share/java/` to the classpath and also display the found files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "List added = %jars /usr/share/java/*.jar\n", + "added" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### %addMavenDependencies, %addMavenDependency, or %maven\n", + "\n", + "These _line magics_ add maven artifacts to the notebook classpath. All transitive dependencies are also added to the classpath. If the artifact is not on maven central then make sure to add the repository with `%mavenRepo`. Dependencies are of the form `groupId:artifactId:[packagingType:[classifier]]:version`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### %loadFromPOM and %%loadFromPOM\n", + "\n", + "Load any dependencies specified in a POM. The cell magic is designed to make it very simple to copy and paste from any READMEs specifying maven POM fragments to use in depending on an artifact (including repositories other than central).\n", + "\n", + "If used as a _line magic_ it accepts a POM to load dependencies from and optionally a list of scopes to import from. The scopes default to `compile`, `runtime`, `system`, and `import`.\n", + "\n", + "When used as a _cell magic_ the scopes may be given as in the line magic but the body of the cell must be a _partial_ POM literal.\n", + "\n", + "If the body is an xml `` tag, then the body is used as a POM without being modified.\n", + "\n", + "Otherwise, the magic attempts to build a POM based on the xml fragments it gets.\n", + "\n", + "``, ``, ``, and `` are given default values if not supplied which there is no reason to supply other than if they happen to be what is copy-and-pasted.\n", + "\n", + "All children of `` and `` are collected **along with any loose `` and `repository` tags**.\n", + "\n", + "Ex: To add a dependency not in central simply add a valid `` and `` and the magic will take care of putting it together into a POM." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " oss-sonatype-snapshots\n", + " https://oss.sonatype.org/content/repositories/snapshots/\n", + "\n", + "\n", + "\n", + " io.github.spencerpark\n", + " jupyter-jvm-basekernel\n", + " 2.0.0-SNAPSHOT\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Quick chart example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Find a library you like such as https://github.com/knowm/XChart. Copy the dependency information specified in the README for installation as a maven artifact, put it in a `%%loadFromPOM` and we are good to go!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " org.knowm.xchart\n", + " xchart\n", + " 3.5.2\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another option is to collapse that into the short syntax and simply use the `%maven` line magic." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%maven org.knowm.xchart:xchart:3.5.2\n", + "import org.knowm.xchart.*;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a quick chart" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "double[] xData = new double[] { 0.0, 1.0, 2.0 };\n", + "double[] yData = new double[] { 2.0, 1.0, 0.0 };\n", + "\n", + "XYChart chart = QuickChart.getChart(\"Sample Chart\", \"X\", \"Y\", \"y(x)\", xData, yData);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then render it inline!" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "BufferedImage@48029f6d: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: width = 600 height = 400 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "BitmapEncoder.getBufferedImage(chart);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".java", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "9+181" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Java Notebooks/BOT_reasoning.ipynb b/Java Notebooks/BOT_reasoning.ipynb new file mode 100644 index 0000000..c403bd9 --- /dev/null +++ b/Java Notebooks/BOT_reasoning.ipynb @@ -0,0 +1,310 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Jena Reasoning on a simple BOT instance\n", + "\n", + "In order to run Jena using the IJava kernel on Jupyter notebooks, first we need to use some [IJava Magics](https://github.com/SpencerPark/IJava/blob/7f5aa9ab858859a010fd228364b080606399ae60/docs/magics.md#line-magic-2) to load it:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " org.apache.jena\n", + " apache-jena-libs\n", + " pom\n", + " 3.11.0\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " \n", + " org.apache.cassandra\n", + " cassandra-all\n", + " 0.8.1\n", + "\n", + " \n", + " \n", + " org.slf4j\n", + " slf4j-log4j12\n", + " \n", + " \n", + " log4j\n", + " log4j\n", + " \n", + " \n", + "\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting up Jena \n", + "\n", + "first, lets import all the Classes we will need for reasoning" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import org.apache.jena.reasoner.*;\n", + "import org.apache.jena.rdf.model.InfModel;\n", + "import org.apache.jena.rdf.model.Statement;\n", + "import org.apache.jena.util.*;\n", + "import org.apache.jena.rdf.model.*;\n", + "import org.apache.jena.ontology.*;\n", + "import org.apache.jena.vocabulary.OWL ;\n", + "import org.apache.jena.vocabulary.RDF ;\n", + "import org.apache.jena.vocabulary.RDFS;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load an ABox from the the documentation example\n", + "Now,load a simple model that has been created similar to the example in the BOT documentation on https://w3c-lbd-cg.github.io/bot/?tab=0#two-storey-building \n", + "\n", + "This is provided in the `../data` directory\n", + "\n", + "it consist of just a number of statements:\n", + "\n", + "```\n", + ":SiteA a bot:Site ;\n", + " bot:hasBuilding :BuildingA .\n", + " \n", + ":BuildingA bot:hasStorey :Storey00 , :Storey01 .\n", + "\n", + ":Storey00 bot:hasSpace :SpaceA , :SpaceB .\n", + "\n", + ":Storey01 bot:hasSpace :SpaceC , :SpaceD .\n", + "```\n", + "\n", + "Let's print out what is known abou the :BuildingA\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/***************** facts BEFORE inference ****************/\n", + "( )\n", + "( )\n" + ] + } + ], + "source": [ + "// load a simple instance file from the example az\n", + "// https://w3c-lbd-cg.github.io/bot/?tab=0#two-storey-building\n", + "/****** the A-BOX *************/\n", + "Model simple_house = FileManager.get().loadModel(\"../data/simple_bot.ttl\");\n", + "System.out.println (\"/***************** facts BEFORE inference ****************/\");\n", + "Resource Site = simple_house.getResource(\"https://ldac.org/house#BuildingA\");\n", + "for (StmtIterator i = ((Model)simple_house).listStatements(new SimpleSelector( Site, null, (RDFNode)null )); i.hasNext();){\n", + " Statement stmt = i.nextStatement();\n", + " System.out.println (PrintUtil.print(stmt));\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the BOT TBox \n", + "Up to know, these are just the \"stupid\" facts asserted in the above snipptes. No knowledge about what the Resources actually are is present at present. \n", + "\n", + "In a second step the TBOX is loaded directly from its source.\n", + "\n", + "A Reasoner is created in that combines TBox and Abox and starts to make inferences" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "/***************** facts AFTER inference ****************/\n", + "( )\n", + "( )\n", + "( rdf:type owl:Thing)\n", + "( rdf:type )\n", + "( )\n", + "( )\n", + "( rdf:type )\n", + "( rdf:type rdfs:Resource)\n", + "( )\n", + "( )\n", + "( )\n", + "( )\n", + "( owl:sameAs )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n" + ] + } + ], + "source": [ + "// import the BOT Ontology from the source via HTTP\n", + "/****** the T-BOX *************/\n", + "Model bot = FileManager.get().loadModel(\"https://w3id.org/bot#\");\n", + "\n", + "// create on OWL reasoner and feed it the bot ontology model\n", + "Reasoner reasoner = ReasonerRegistry.getOWLReasoner();\n", + "reasoner = reasoner.bindSchema(bot);\n", + "\n", + "//create inferences from \n", + "InfModel infmodel = ModelFactory.createInfModel(reasoner, simple_house);\n", + "System.out.println (\"\\n\\n/***************** facts AFTER inference ****************/\");\n", + "// print out all statements asserted and inferred \n", + "Resource Site = infmodel.getResource(\"https://ldac.org/house#BuildingA\");\n", + "for (StmtIterator i = ((Model)infmodel).listStatements(new SimpleSelector( Site, null, (RDFNode)null )); i.hasNext();){\n", + " Statement stmt = i.nextStatement();\n", + " System.out.println (PrintUtil.print(stmt));\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extend the BOT ontology with a \"connectivity\" property\n", + "\n", + "A simple extension is loaded that consists of the following three statements:\n", + "```\n", + "@prefix bot: .\n", + "@prefix conn: .\n", + "@prefix rdfs: .\n", + "@prefix owl: .\n", + "\n", + "conn:isConnectedTo a owl:SymmetricProperty;\n", + " a owl:TransitiveProperty;\n", + " rdfs:range bot:Zone.\n", + "```\n", + "\n", + "The `owl:SymmetricProperty` means that \n", + "- if A is connected to B \n", + "- then it follows that B is connected to A\n", + "\n", + "The `owl:TransitiveProperty` means that\n", + "- if A is connected to B\n", + "- and B is connected to C\n", + "- then A is connected to C\n", + "\n", + "combining both also means \n", + "- C is connected to A\n", + "\n", + "In our ABox, we a few statements to that end have been added:\n", + "```\n", + ":SpaceA conn:isConnectedTo :SpaceB .\n", + ":SpaceB conn:isConnectedTo :SpaceC .\n", + ":Storey00 conn:isConnectedTo :SpaceA .\n", + "```\n", + "\n", + "Lets take a look at `:Storey00`\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "( )\n", + "( )\n", + "( )\n", + "( rdf:type )\n", + "( rdf:type owl:Thing)\n", + "( )\n", + "( )\n", + "( rdf:type )\n", + "( )\n", + "( )\n", + "( )\n", + "( rdf:type rdfs:Resource)\n", + "( owl:sameAs )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n", + "( owl:differentFrom )\n" + ] + } + ], + "source": [ + "Model conn = FileManager.get().loadModel(\"../data/conn.ttl\");\n", + "bot.add(conn);\n", + "\n", + "Reasoner reasoner = ReasonerRegistry.getOWLReasoner();\n", + "reasoner = reasoner.bindSchema(bot);\n", + "\n", + "//create inferences from \n", + "InfModel infmodel = ModelFactory.createInfModel(reasoner, simple_house);\n", + "\n", + "//simple_house.write(System.out,\"RDF/XML\");\n", + "Resource Site = infmodel.getResource(\"https://ldac.org/house#Storey00\");\n", + "for (StmtIterator i = ((Model)infmodel).listStatements(new SimpleSelector( Site, null, (RDFNode)null )); i.hasNext();){\n", + " Statement stmt = i.nextStatement();\n", + " System.out.println (PrintUtil.print(stmt));\n", + "}" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "12.0.1+12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Java Notebooks/HelloWorld.ipynb b/Java Notebooks/HelloWorld.ipynb new file mode 100644 index 0000000..b325f4d --- /dev/null +++ b/Java Notebooks/HelloWorld.ipynb @@ -0,0 +1,58 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello stdout!\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Hello stderr!\n" + ] + }, + { + "data": { + "text/plain": [ + "Hello Out!" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "System.out.println(\"Hello stdout!\");\n", + "System.err.println(\"Hello stderr!\");\n", + "\n", + "\"Hello Out!\";" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "12.0.1+12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Java Notebooks/JenaRoadTest.ipynb b/Java Notebooks/JenaRoadTest.ipynb new file mode 100644 index 0000000..2f0bc09 --- /dev/null +++ b/Java Notebooks/JenaRoadTest.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Loading Jena in Jupyter Notebooks\n", + "\n", + "In order to run Jena using the IJava kernel on Jupyter notebooks, first we need to use some [IJava Magics](https://github.com/SpencerPark/IJava/blob/7f5aa9ab858859a010fd228364b080606399ae60/docs/magics.md#line-magic-2) to load it:" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " org.apache.jena\n", + " apache-jena-libs\n", + " pom\n", + " 3.11.0\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prevent log4j from throwing error messages\n", + "\n", + "The code below should prevent log4j from throwing error messages when loading data from code." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " \n", + " org.apache.cassandra\n", + " cassandra-all\n", + " 0.8.1\n", + "\n", + " \n", + " \n", + " org.slf4j\n", + " slf4j-log4j12\n", + " \n", + " \n", + " log4j\n", + " log4j\n", + " \n", + " \n", + "\n", + " \n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "%jars c:\\\\jdrive\\\\lib\\\\apache-jena-3.12.0\\\\lib" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "%classpath c:\\\\jdrive\\\\lib\\\\apache-jena-3.12.0\\\\lib" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import Jena dependencies\n", + "\n", + "Let's go ahead and import some Jena dependencies we will need to create models and manage the content of files." + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [], + "source": [ + "import org.apache.jena.rdf.model.Model;\n", + "import org.apache.jena.rdf.model.ModelFactory;\n", + "import org.apache.jena.util.FileManager;\n", + "import org.apache.jena.util.*;\n", + "import org.apache.jena.ontology.impl.*;" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "test\n" + ] + }, + { + "ename": "EvalException", + "evalue": "Could not initialize class org.apache.jena.ontology.impl.OntModelImpl", + "output_type": "error", + "traceback": [ + "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1m\u001b[31mjava.lang.NoClassDefFoundError: Could not initialize class org.apache.jena.ontology.impl.OntModelImpl\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:286)\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:245)\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:228)\u001b[0m", + "\u001b[1m\u001b[31m\tat .(#85:1)\u001b[0m" + ] + } + ], + "source": [ + "System.out.println(\"test\");\n", + "Model m = ModelFactory.createOntologyModel( );;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Let's create a Jena model object and load the BOT ontology into it.
\n", + "If SLF4J throws a warning, ignore it." + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "ename": "EvalException", + "evalue": "Could not initialize class org.apache.jena.util.FileManager", + "output_type": "error", + "traceback": [ + "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1m\u001b[31mjava.lang.NoClassDefFoundError: Could not initialize class org.apache.jena.util.FileManager\u001b[0m", + "\u001b[1m\u001b[31m\tat .(#20:1)\u001b[0m" + ] + } + ], + "source": [ + "Model model = FileManager.get().loadModel(\"https://w3id.org/bot#\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "We can inspect the content of the file by printing it in the format of our preference, using System.out\n", + "Available formats:
\n", + ". Turtle
\n", + ". RDF/XML
\n", + ". RDF/JSON
\n", + ". N-Triples
\n", + ". TriG
\n", + ". N-Quads" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "ename": "EvalException", + "evalue": "null", + "output_type": "error", + "traceback": [ + "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1m\u001b[31mjava.lang.NullPointerException: null\u001b[0m", + "\u001b[1m\u001b[31m\tat .(#103:1)\u001b[0m" + ] + } + ], + "source": [ + "model.write(System.out, \"RDF/XML\");" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#Import the SHACL checker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " org.topbraid\n", + " shacl\n", + " 1.1.0\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "ename": "EvalException", + "evalue": "Could not initialize class org.apache.jena.ontology.impl.OntModelImpl", + "output_type": "error", + "traceback": [ + "\u001b[1m\u001b[31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1m\u001b[31mjava.lang.NoClassDefFoundError: Could not initialize class org.apache.jena.ontology.impl.OntModelImpl\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:286)\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:245)\u001b[0m", + "\u001b[1m\u001b[31m\tat org.apache.jena.rdf.model.ModelFactory.createOntologyModel(ModelFactory.java:228)\u001b[0m", + "\u001b[1m\u001b[31m\tat .(#85:1)\u001b[0m" + ] + } + ], + "source": [ + "import org.apache.jena.ontology.OntModel;\n", + "import org.apache.jena.reasoner.*;\n", + "import org.apache.jena.rdf.model.InfModel;\n", + "import org.apache.jena.rdf.model.Statement;\n", + "import org.apache.jena.util.*;\n", + "import org.apache.jena.rdf.model.*;\n", + "import org.apache.jena.ontology.*;\n", + "import org.apache.jena.vocabulary.OWL ;\n", + "import org.apache.jena.vocabulary.RDF ;\n", + "import org.apache.jena.vocabulary.RDFS ;\n", + "\n", + "\n", + "//OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM_MICRO_RULE_INF );\n", + "\n", + "OntModel m = ModelFactory.createOntologyModel( );\n", + "bot.add(m);\n", + "\n", + "Model simple_house = FileManager.get().loadModel(\"../data/simple_bot.ttl\");\n", + "\n", + "\n", + "//InfModel infmodel = ModelFactory.createOntologyModel(bot, simple_house);\n", + "\n", + "Reasoner reasoner = ReasonerRegistry.getOWLReasoner();\n", + "reasoner = reasoner.bindSchema(bot);\n", + "\n", + "InfModel infmodel = ModelFactory.createInfModel(reasoner, simple_house);\n", + "\n", + "\n", + "//simple_house.write(System.out,\"RDF/XML\");\n", + "Resource Site = infmodel.getResource(\"https://ldac.org/house#Storey00\");\n", + "for (StmtIterator i = ((Model)infmodel).listStatements(new SimpleSelector( Site, null, (RDFNode)null )); i.hasNext();){\n", + " Statement stmt = i.nextStatement();\n", + " System.out.println (PrintUtil.print(stmt));\n", + "}" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "12.0.1+12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Java Notebooks/hello_jena_hello_ldac.ipynb b/Java Notebooks/hello_jena_hello_ldac.ipynb new file mode 100644 index 0000000..f1b6398 --- /dev/null +++ b/Java Notebooks/hello_jena_hello_ldac.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Hello Jena, hello LDAC\n", + "### Constructing a simple RDF Graph with Jena\n", + "\n", + "In order to run Jena using the IJava kernel on Jupyter notebooks, first we need to use some [IJava Magics](https://github.com/SpencerPark/IJava/blob/7f5aa9ab858859a010fd228364b080606399ae60/docs/magics.md#line-magic-2) to load it:\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " org.apache.jena\n", + " apache-jena-libs\n", + " pom\n", + " 3.11.0\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%loadFromPOM\n", + "\n", + " \n", + " org.apache.cassandra\n", + " cassandra-all\n", + " 0.8.1\n", + "\n", + " \n", + " \n", + " org.slf4j\n", + " slf4j-log4j12\n", + " \n", + " \n", + " log4j\n", + " log4j\n", + " \n", + " \n", + "\n", + " \n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting up Jena \n", + "\n", + "first, let's import some of the standard classes for model manipulation in Jena" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import org.apache.jena.rdf.model.ModelFactory;\n", + "import org.apache.jena.util.FileManager;\n", + "import org.apache.jena.ontology.OntModel;\n", + "import org.apache.jena.reasoner.*;\n", + "import org.apache.jena.rdf.model.InfModel;\n", + "import org.apache.jena.rdf.model.Statement;\n", + "import org.apache.jena.util.*;\n", + "import org.apache.jena.rdf.model.*;\n", + "import org.apache.jena.ontology.*;\n", + "import org.apache.jena.vocabulary.OWL ;\n", + "import org.apache.jena.vocabulary.RDF ;\n", + "import org.apache.jena.vocabulary.RDFS ;\n", + "import org.apache.jena.vocabulary.VCARD;\n", + "import org.apache.jena.sparql.vocabulary.FOAF " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a simple TBox model" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "Model m = ModelFactory.createDefaultModel();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create some statements\n", + "Using the vcard vocabulary \n", + "https://www.w3.org/TR/vcard-rdf/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "String personURI = \"http://linkedbuildingdata.org/people/\";\n", + "\n", + "Resource maria = m.createResource(personURI+\"MariaPovedaVillalon\");\n", + "maria.addProperty (RDF.type, FOAF.Person);\n", + "maria.addProperty (FOAF.name, \"Maria Poveda Villalón\");\n", + "maria.addProperty (FOAF.firstName, \"Maria\");\n", + "maria.addProperty (FOAF.familyName, \"Poveda\");\n", + "\n", + "// create the pieter Resource, add VCARD information\n", + "String givenName = \"Pieter\";\n", + "String familyName = \"Pauwels\";\n", + "String fullName = givenName + \" \" + familyName;\n", + "\n", + "// create the resource\n", + "// and add the properties cascading style\n", + "Resource pieter \n", + " = m.createResource(personURI+givenName+familyName)\n", + " .addProperty(VCARD.FN, fullName)\n", + " .addProperty(VCARD.N,\n", + " m.createResource()\n", + " .addProperty(VCARD.Given, givenName)\n", + " .addProperty(VCARD.Family, familyName));\n", + "// make Pieter a foaf:Person\n", + "\n", + "pieter.addProperty(RDF.type, FOAF.Person);\n", + "\n", + "// create a statement about Maria and Pieter knowing each other\n", + "\n", + "Statement s = m.createStatement(maria, FOAF.knows, pieter);\n", + "m.add(s); // add the statement (triple) to the model\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Look at the model we have just created" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.write(System.out, \"Turtle\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Java", + "language": "java", + "name": "java" + }, + "language_info": { + "codemirror_mode": "java", + "file_extension": ".jshell", + "mimetype": "text/x-java-source", + "name": "Java", + "pygments_lexer": "java", + "version": "12.0.1+12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Notebooks/00-00-Check-Python-Setup.ipynb b/Notebooks/00-00-Check-Python-Setup.ipynb index 725575e..7e052c3 100644 --- a/Notebooks/00-00-Check-Python-Setup.ipynb +++ b/Notebooks/00-00-Check-Python-Setup.ipynb @@ -17,7 +17,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -30,10 +30,10 @@ { "data": { "text/plain": [ - "'3.7.3 | packaged by conda-forge | (default, Mar 27 2019, 23:01:00) \\n[GCC 7.3.0]'" + "'3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]'" ] }, - "execution_count": 1, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -66,21 +66,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'xlrd'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mxlrd\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'xlrd'" - ] - } - ], + "outputs": [], "source": [ "import xlrd" ] @@ -96,9 +84,21 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'rdflib'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mrdflib\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'rdflib'" + ] + } + ], "source": [ "import rdflib" ] @@ -112,43 +112,17 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { - "name": "stdout", + "name": "stderr", "output_type": "stream", "text": [ - "Collecting package metadata: done\n", - "Solving environment: done\n", - "\n", - "## Package Plan ##\n", - "\n", - " environment location: /srv/conda/envs/notebook\n", - "\n", - " added / updated specs:\n", - " - xlrd\n", - "\n", - "\n", - "The following packages will be downloaded:\n", - "\n", - " package | build\n", - " ---------------------------|-----------------\n", - " xlrd-1.2.0 | py_0 108 KB conda-forge\n", - " ------------------------------------------------------------\n", - " Total: 108 KB\n", - "\n", - "The following NEW packages will be INSTALLED:\n", + "WARNING: The conda.compat module is deprecated and will be removed in a future release.\n", "\n", - " xlrd conda-forge/noarch::xlrd-1.2.0-py_0\n", - "\n", - "\n", - "\n", - "Downloading and Extracting Packages\n", - "xlrd-1.2.0 | 108 KB | ##################################### | 100% \n", - "Preparing transaction: done\n", - "Verifying transaction: done\n", - "Executing transaction: done\n" + "CondaValueError: invalid package specification: #\n", + "\n" ] } ], @@ -169,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -182,10 +156,10 @@ { "data": { "text/plain": [ - "'/home/jovyan/Notebooks'" + "'C:\\\\jdrive\\\\src\\\\2019_ldac_summer_school\\\\SummerSchoolOfLDAC\\\\Notebooks'" ] }, - "execution_count": 11, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -198,10 +172,51 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting rdflib\n", + " Using cached https://files.pythonhosted.org/packages/3c/fe/630bacb652680f6d481b9febbb3e2c3869194a1a5fc3401a4a41195a2f8f/rdflib-4.2.2-py3-none-any.whl\n", + "Collecting isodate (from rdflib)\n", + " Using cached https://files.pythonhosted.org/packages/9b/9f/b36f7774ff5ea8e428fdcfc4bb332c39ee5b9362ddd3d40d9516a55221b2/isodate-0.6.0-py2.py3-none-any.whl\n", + "Requirement already satisfied: pyparsing in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from rdflib) (2.3.1)\n", + "Requirement already satisfied: six in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from isodate->rdflib) (1.12.0)\n", + "Installing collected packages: isodate, rdflib\n", + "Successfully installed isodate-0.6.0 rdflib-4.2.2\n" + ] + } + ], + "source": [ + "!pip install rdflib\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting SPARQLWrapper\n", + " Downloading https://files.pythonhosted.org/packages/b0/1d/d7c60a451a255fca655fe37eb3f6e3b3daa7d33fc87eeec0d8631d501e76/SPARQLWrapper-1.8.4-py3-none-any.whl\n", + "Requirement already satisfied: rdflib>=4.0 in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from SPARQLWrapper) (4.2.2)\n", + "Requirement already satisfied: pyparsing in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from rdflib>=4.0->SPARQLWrapper) (2.3.1)\n", + "Requirement already satisfied: isodate in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from rdflib>=4.0->SPARQLWrapper) (0.6.0)\n", + "Requirement already satisfied: six in d:\\bin\\dev\\anaconda3\\lib\\site-packages (from isodate->rdflib>=4.0->SPARQLWrapper) (1.12.0)\n", + "Installing collected packages: SPARQLWrapper\n", + "Successfully installed SPARQLWrapper-1.8.4\n" + ] + } + ], + "source": [ + "!pip install SPARQLWrapper\n" + ] } ], "metadata": { diff --git a/README.md b/README.md index 6dc3376..e659ae3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # Summer School Of LDAC -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/linkedbuildingdata/SummerSchoolOfLDAC/master) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jakob-beetz/SummerSchoolOfLDAC/multiKernel) + + +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jakob-beetz/SummerSchoolOfLDAC/multiKernel) + +Copy markdown link to clipboard This repository contains the documentation and source of the coding challenge of the [Summer School of Linked Data in Architecture and Construction](http://linkedbuildingdata.net/ldac2019/summerschool/) held 17 - 18 June in Lisbon, Portugal. The summer school precedes the [7th Workshop on Linked Data in Architecture and Construction (LDAC)](http://linkedbuildingdata.net/ldac2019/). ![Summer School Banner](figures/LogoLDACSummerschool.png) @@ -19,11 +24,14 @@ If you are not familiar to iPython/ Jupyter etc. please refer to the [introducto A couple of persons contributed to the content of this repository. Amongst others: * **Georg Ferdinand Schneider**, [RG](https://www.researchgate.net/profile/Georg_Schneider3) +* **Rui de Klerk**, [RG](https://www.researchgate.net/profile/Rui_De_Klerk) ## Acknowledgements The authors would like to thank Jake VanderPlas [@jakvdp](https://github.com/jakevdp) for providing his [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook/) [(Oreilly)](http://shop.oreilly.com/product/0636920034919.do) open source as the structure of the content provided in this repository follows the approach chosen by him for his book. +The authors would also like to thank Spencer Park [@SpencerPark](https://github.com/SpencerPark) for providing his [ijava-binder](https://github.com/SpencerPark/ijava-binder) scripts to work with the Java kernel in Jupyter notebooks, through Binder. + ## Data We store some open data obtained from other sources in the [data](data) folder of this repository: @@ -36,4 +44,4 @@ We store some open data obtained from other sources in the [data](data) folder o All source code provided in this repositoy is licensed under the [MIT license](LICENSE-CODE). ### Text -The textual description in the notebooks and all other content which is not source code is licensed under the [CC-BY-SA-4.0](LICENSE-TEXT) license. \ No newline at end of file +The textual description in the notebooks and all other content which is not source code is licensed under the [CC-BY-SA-4.0](LICENSE-TEXT) license. diff --git a/data/conn.ttl b/data/conn.ttl new file mode 100644 index 0000000..8a2ef6d --- /dev/null +++ b/data/conn.ttl @@ -0,0 +1,8 @@ +@prefix bot: . +@prefix conn: . +@prefix rdfs: . +@prefix owl: . + +conn:isConnectedTo a owl:SymmetricProperty; + a owl:TransitiveProperty; + rdfs:range bot:Zone. diff --git a/data/simple_bot.ttl b/data/simple_bot.ttl new file mode 100644 index 0000000..7a47fff --- /dev/null +++ b/data/simple_bot.ttl @@ -0,0 +1,38 @@ +@prefix bot: . +@prefix : . +@prefix conn: . +# A simple two storey building with two spaces at each floor. + +:SiteA a bot:Site ; + bot:hasBuilding :BuildingA . + +# Since the range of bot:hasBuilding is bot:Building it is +# automatically inferred that :BuildingA is a bot:Building. + +:BuildingA bot:hasStorey :Storey00 , :Storey01 . + +# Since the range of bot:hasStorey is bot:Storey it is automatically +# inferred that :Storey00 and :Storey01 are instances of bot:Storey. + +:Storey00 bot:hasSpace :SpaceA , :SpaceB . + +:Storey01 bot:hasSpace :SpaceC , :SpaceD . + + +# let's assume B is above C:L +:SpaceA conn:isConnectedTo :SpaceB . +:SpaceB conn:isConnectedTo :SpaceC . +:Storey00 conn:isConnectedTo :SpaceA . + +# Since the range of bot:hasSpace is bot:Space it is automatically inferred +# that :SpaceA, :SpaceB, :SpaceC and :SpaceD are instances of bot:Space. + +# Since bot:Site, bot:Building, bot:Storey and bot:Building are all sub classes of +# bot:Zone, :SiteA, :BuildingA, :Storey00 , :Storey01, :SpaceA, :SpaceB, +# :SpaceC and :SpaceD are all instances of bot:Zone + +# Since bot:hasBuilding, bot:hasStorey and bot:hasSpace are all sub properties of +# bot:containsZone the following can also be deduced: +# +# :SiteA bot:containsZone :BuildingA . +# :BuildingA bot:containsZone :Storey00 , :Storey01 . diff --git a/requirements.txt b/requirements.txt index 159649f..2765b0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,22 +5,25 @@ backcall==0.1.0 bleach==3.1.0 certifi==2019.3.9 chardet==3.0.4 +colorama==0.4.1 decorator==4.4.0 defusedxml==0.5.0 entrypoints==0.3 html5lib==1.0.1 idna==2.8 ipykernel==5.1.0 -ipython==7.5.0 +ipython==7.3.0 ipython-genutils==0.2.0 ipywidgets==7.4.2 isodate==0.6.0 jedi==0.13.3 Jinja2==2.10.1 jsonschema==3.0.1 +jupyter==1.0.0 jupyter-client==5.2.4 +jupyter-console==6.0.0 jupyter-core==4.4.0 -jupyterhub==0.9.4 +jupyterhub>=0.9.6 jupyterlab==0.35.4 jupyterlab-server==0.2.0 keepalive==0.5 @@ -29,11 +32,12 @@ MarkupSafe==1.1.1 mistune==0.8.4 nbconvert==5.4.1 nbformat==4.4.0 -notebook==5.7.8 +notebook==5.7.6 nteract-on-jupyter==2.0.12 +owlready2==0.17.0 pamela==1.0.0 pandocfilters==1.4.2 -parso==0.4.0 +parso==0.3.4 pexpect==4.7.0 pickleshare==0.7.5 prometheus-client==0.6.0 @@ -41,20 +45,23 @@ prompt-toolkit==2.0.9 ptyprocess==0.6.0 Pygments==2.3.1 pyparsing==2.4.0 -pyrsistent==0.15.1 +pyrsistent==0.14.11 python-dateutil==2.8.0 python-editor==1.0.4 python-oauth2==1.1.0 +pywinpty==0.5.5 pyzmq==18.0.1 +qtconsole==4.4.3 rdflib==4.2.2 requests==2.21.0 Send2Trash==1.5.0 +setuptools==40.8.0 six==1.12.0 SPARQLWrapper==1.8.2 SQLAlchemy==1.3.3 terminado==0.8.2 testpath==0.4.2 -tornado==6.0.2 +tornado==6.0.1 traitlets==4.3.2 urllib3==1.24.2 wcwidth==0.1.7