From 4fce6376a40dc9df236cb5c8761cf00b1bb95e4b Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 19 Mar 2024 09:58:34 +0100 Subject: [PATCH 1/6] Update dependencies One should especially focus on the Sphinx update (from v5 to v7), rdflib update (from v6 to v7) and the necessity to keep pydata-sphinx-theme at its current version due to too many differences in the look and feel of the docs if updated to the latest version. Also, all currently unversioned dependencies have been fixed to a version. --- requirements_docs.txt | 2 +- sphinx/requirements.txt | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/requirements_docs.txt b/requirements_docs.txt index 8922d01..837f883 100644 --- a/requirements_docs.txt +++ b/requirements_docs.txt @@ -1 +1 @@ -rdflib==6.3.2 +rdflib==7.0.0 diff --git a/sphinx/requirements.txt b/sphinx/requirements.txt index cc54149..8cd5054 100644 --- a/sphinx/requirements.txt +++ b/sphinx/requirements.txt @@ -1,33 +1,33 @@ accessible-pygments==0.0.4 -alabaster==0.7.13 +alabaster==0.7.16 Babel==2.14.0 -beautifulsoup4==4.12.2 -certifi==2023.11.17 +beautifulsoup4==4.12.3 +certifi==2024.2.2 charset-normalizer==3.3.2 docutils==0.20.1 idna==3.6 imagesize==1.4.1 -importlib-metadata==6.7.0 +importlib-metadata==7.0.2 Jinja2==3.1.3 -MarkupSafe==2.1.3 -nbsphinx +MarkupSafe==2.1.5 +nbsphinx==0.9.3 packaging==23.2 -pandoc +pandoc==2.3 pydata-sphinx-theme==0.13.3 Pygments==2.17.2 pytz==2024.1 requests==2.31.0 snowballstemmer==2.2.0 -soupsieve==2.4.1 -Sphinx==5.3.0 -sphinxcontrib-applehelp==1.0.2 -sphinxcontrib-devhelp==1.0.2 +soupsieve==2.5 +Sphinx==7.2.6 +sphinx-design==0.5.0 +sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-devhelp==1.0.6 sphinxcontrib-globalsubs==0.1.1 -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.5 sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.5 -typing_extensions==4.7.1 -urllib3==2.0.7 -zipp==3.15.0 -sphinx-design +sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-serializinghtml==1.1.10 +typing_extensions==4.10.0 +urllib3==2.2.1 +zipp==3.18.1 From 63fec27cac713783d2740c6c2294d2821ed1142e Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 19 Mar 2024 10:08:08 +0100 Subject: [PATCH 2/6] Run `make html` directly in CI for building docs Avoid using the - quite outdated - ammaraskar/sphinx-action GitHub Action. It was forcefully using Python 3.8 due to using a very old version of the underlying docker image sphinx-doc/sphinx. --- .github/workflows/doc.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 932f075..c97fe7e 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -32,16 +32,16 @@ jobs: run: | python -m pip install --upgrade pip pip install -U setuptools wheel - pip install -r requirements_docs.txt + pip install -r requirements_docs.txt -r sphinx/requirements.txt - name: Render documentation from ttl run: python sphinx/ttl_to_rst.py - name: Build HTML - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "sphinx/" - pre-build-command: "apt-get update -y; apt-get install -y pandoc" + run: | + apt-get update && apt-get install -y pandoc + make html + working-directory: sphinx # Still upload built documentation as an artifact if not deploying # This is to provide the opportunity to download the built documentation From ccbb574ce37791ae636b0ab867cb45bb8ff1a2bd Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 19 Mar 2024 10:19:54 +0100 Subject: [PATCH 3/6] Use sudo when installing pandoc in CI workflow --- .github/workflows/doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index c97fe7e..0fcf8e5 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -39,7 +39,7 @@ jobs: - name: Build HTML run: | - apt-get update && apt-get install -y pandoc + sudo apt-get update && sudo apt-get install -y pandoc make html working-directory: sphinx From 8fff0a658ffc9cbed19e2f967ae0de720fdf4206 Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 19 Mar 2024 10:21:49 +0100 Subject: [PATCH 4/6] Move installing pandoc up to the proper step in workflow --- .github/workflows/doc.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 0fcf8e5..347b0bb 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -30,6 +30,10 @@ jobs: - name: Install dependencies run: | + # System dependencies + sudo apt-get update && sudo apt-get install -y pandoc + + # Python dependencies python -m pip install --upgrade pip pip install -U setuptools wheel pip install -r requirements_docs.txt -r sphinx/requirements.txt @@ -38,9 +42,7 @@ jobs: run: python sphinx/ttl_to_rst.py - name: Build HTML - run: | - sudo apt-get update && sudo apt-get install -y pandoc - make html + run: make html working-directory: sphinx # Still upload built documentation as an artifact if not deploying From 0b6c23a6bec6b8955eb0a50faa13eaf2438dbb80 Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 30 Jul 2024 09:38:49 +0200 Subject: [PATCH 5/6] Update dependencies Support installing all requirements files at once (resolving that there are no sub-dependency issues). --- sphinx/requirements.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sphinx/requirements.txt b/sphinx/requirements.txt index 2e41947..5483849 100644 --- a/sphinx/requirements.txt +++ b/sphinx/requirements.txt @@ -2,32 +2,32 @@ accessible-pygments==0.0.5 alabaster==0.7.16 Babel==2.15.0 beautifulsoup4==4.12.3 -certifi==2024.2.2 +certifi==2024.7.4 charset-normalizer==3.3.2 docutils==0.20.1 -idna==3.6 +idna==3.7 imagesize==1.4.1 -importlib-metadata==8.0.0 +importlib-metadata==8.2.0 Jinja2==3.1.4 MarkupSafe==2.1.5 -nbsphinx==0.9.3 -packaging==24.1 +nbsphinx==0.9.4 +packaging==23.2 # EMMOntoPy does not support v24 pandoc==2.3 -pydata-sphinx-theme==0.13.3 +pydata-sphinx-theme==0.15.4 Pygments==2.18.0 pytz==2024.1 requests==2.32.3 snowballstemmer==2.2.0 soupsieve==2.5 Sphinx==7.2.6 -sphinx-design==0.5.0 -sphinxcontrib-applehelp==1.0.8 -sphinxcontrib-devhelp==1.0.6 +sphinx-design==0.6.0 # does not support sphinx v8 +sphinxcontrib-applehelp==2.0.0 +sphinxcontrib-devhelp==2.0.0 sphinxcontrib-globalsubs==0.1.1 -sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-htmlhelp==2.1.0 sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.7 -sphinxcontrib-serializinghtml==1.1.10 +sphinxcontrib-qthelp==2.0.0 +sphinxcontrib-serializinghtml==2.0.0 typing_extensions==4.12.2 -urllib3==2.2.1 +urllib3==2.2.2 zipp==3.19.2 From aa32334a2cb5a0d612534dd3cdcc689984601395 Mon Sep 17 00:00:00 2001 From: Casper Welzel Andersen Date: Tue, 30 Jul 2024 10:49:27 +0200 Subject: [PATCH 6/6] Update docs to remove all build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All warnings have been removed by: - Move `!pip install` statements to a separate cell in all notebooks, making the cell "shellscript" code and add a sentence immediately before stating the same thing. - Add all files to a Sphinx `toctree` tag, specifically extending the header nav with the "More" dropdown, which includes "contribute", "tools", and "resources". - Find online and add the image for the Protégé configuration. Update the configuration to remove the primary sidebar from pages that have no section navigation. Since no warnings are produced (locally) now, the CI workflow has been updated to include the `-W` flag for sphinx-build, which treats warnings as errors during the build. --- .github/workflows/doc.yml | 4 + sphinx/about.rst | 2 +- sphinx/conf.py | 17 +- sphinx/contribute.rst | 6 +- ...le_linked_data_battery_cell_metadata.ipynb | 387 +++++++++--------- ...ed_data_custom_battery_cell_metadata.ipynb | 323 ++++++++------- ..._linked_data_timeseries_battery_data.ipynb | 273 ++++++------ sphinx/example_linked_data_zinc_powder.ipynb | 344 ++++++++-------- sphinx/example_person_jsonld_nb.ipynb | 13 +- sphinx/examples.rst | 17 +- sphinx/img/protege_config_contribute.png | Bin 0 -> 17789 bytes sphinx/index.rst | 4 + 12 files changed, 733 insertions(+), 657 deletions(-) create mode 100644 sphinx/img/protege_config_contribute.png diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 347b0bb..f653506 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -44,6 +44,10 @@ jobs: - name: Build HTML run: make html working-directory: sphinx + env: + # -v: Verbose + # -W: Turn warnings into errors + SPHINXOPTS: "-v -W" # Still upload built documentation as an artifact if not deploying # This is to provide the opportunity to download the built documentation diff --git a/sphinx/about.rst b/sphinx/about.rst index 277f8b4..f075cb6 100644 --- a/sphinx/about.rst +++ b/sphinx/about.rst @@ -1,5 +1,5 @@ About the Battery Interface Ontology -========================== +==================================== The Battery Interface Ontology (BattINFO) is a semantic resource for the terms and relations needed to describe things, processes, and data in the battery domain. It can be used to **generate linked data** for the Semantic Web, **comply with the FAIR data guidelines**, support **interoperaility of data** among different systems, and more! diff --git a/sphinx/conf.py b/sphinx/conf.py index 1a98f28..7d5cdab 100644 --- a/sphinx/conf.py +++ b/sphinx/conf.py @@ -120,6 +120,8 @@ html_theme_options = { # "show_nav_level": 4 + "header_links_before_dropdown": 5, # show 5 links before "More" dropdown + "primary_sidebar_end": [], } # Add any paths that contain custom themes here, relative to this directory. @@ -161,7 +163,14 @@ #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +html_sidebars = { + "**": ["sidebar-nav-bs"], + "about": [], + "battinfo": [], + "contribute": [], + "faq": [], + "getstarted": [], +} # Additional templates that should be rendered to pages, maps page names to # template names. @@ -299,4 +308,10 @@ # MatAttributeDocumenter.add_directive_header = _add_directive_header +suppress_warnings = [ + # Suppress "duplicate label" warnings in `battinfo.rst`. + # These are due to similarly named (prefLabel) concepts in the ontology, + # as the prefLabel is used as the section title. + "autosectionlabel.battinfo", + ] diff --git a/sphinx/contribute.rst b/sphinx/contribute.rst index bce0327..b0b7751 100644 --- a/sphinx/contribute.rst +++ b/sphinx/contribute.rst @@ -24,7 +24,7 @@ We recommend using the `forking workflow `__ to contribute additions/deletions. Fork this repository, clone the fork on your local PC, create your branch based on the existing ``dev`` -branch (e.g. ``dev_john_doe``) and work on the editions in you local +branch (e.g. ``dev_john_doe``) and work on the editions in you local copy. You can edit ontologes in two main ways. One is programmatically, using @@ -32,7 +32,7 @@ for instance `EMMOntoPy `__. The second and more common is using the interface provided by the Protégé software. In case of the latter, `install Protégé `__ and use it to open the -ontology file you wish to edit. Before adding elements, ensure Prot´égé +ontology file you wish to edit. Before adding elements, ensure Protégé is configured to create IRIs in the right format: - Open Protégé @@ -49,5 +49,5 @@ is configured to create IRIs in the right format: request `__. - We will merge the request after assessing it. -.. |Protege config.| image:: doc/img/protege_config_contribute.png +.. |Protege config.| image:: img/protege_config_contribute.png diff --git a/sphinx/example_linked_data_battery_cell_metadata.ipynb b/sphinx/example_linked_data_battery_cell_metadata.ipynb index 0d4389e..d6cbb22 100644 --- a/sphinx/example_linked_data_battery_cell_metadata.ipynb +++ b/sphinx/example_linked_data_battery_cell_metadata.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "1wseTQGaB4x9" + }, "source": [ "# Example: Simple Battery Cell Metadata\n", "\n", @@ -30,23 +19,25 @@ "- How to use the ontology to fetch more information from other sources **[Advanced]** \n", "\n", "A live version of this notebook is available on Google Colab [here](https://colab.research.google.com/drive/10F5YRAnO5ubY4Ut3uEjv5rLqvr_GRFC5?usp=sharing)\n" - ], - "metadata": { - "id": "1wseTQGaB4x9" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "jcTVz9-DEh3m" + }, "source": [ "## Describe the powder using ontology terms in JSON-LD format\n", "The JSON-LD data that we will use is:" - ], - "metadata": { - "id": "jcTVz9-DEh3m" - } + ] }, { "cell_type": "code", + "execution_count": 42, + "metadata": { + "id": "gohQKEBrF2QP" + }, + "outputs": [], "source": [ "jsonld = {\n", " \"@context\": \"https://raw.githubusercontent.com/emmo-repo/domain-battery/master/context.json\",\n", @@ -65,77 +56,63 @@ " \"hasMeasurementUnit\": \"emmo:MilliAmpereHour\"\n", " }\n", " }" - ], - "metadata": { - "id": "gohQKEBrF2QP" - }, - "execution_count": 42, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "in30p-x4H91Y" + }, "source": [ "## Parse this description into a graph\n", "Now let's see how a machine would process this data by reading it into a Graph!\n", "\n", - "First, we install and import the python dependencies that we need for this example." - ], + "First, we install and import the python dependencies that we need for this example.\n", + "\n", + "Note, the `pip install` statement is to be run in a shell/terminal." + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { - "id": "in30p-x4H91Y" - } + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "# Install dependencies\n", + "pip install jsonschema rdflib requests matplotlib > /dev/null" + ] }, { "cell_type": "code", + "execution_count": 43, + "metadata": { + "id": "wk4sFl_eA2ML" + }, + "outputs": [], "source": [ - "# Install and import dependencies\n", - "!pip install jsonschema rdflib requests matplotlib > /dev/null\n", - "\n", + "# Import dependencies\n", "import json\n", "import rdflib\n", "import requests\n", - "import sys\n", - "from IPython.display import Image, display\n", - "import matplotlib.pyplot as plt" - ], - "metadata": { - "id": "wk4sFl_eA2ML" - }, - "execution_count": 43, - "outputs": [] + "from IPython.display import Image, display" + ] }, { "cell_type": "markdown", - "source": [ - "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." - ], "metadata": { "id": "lotp-0QABV-2" - } + }, + "source": [ + "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." + ] }, { "cell_type": "code", - "source": [ - "# Create a new graph\n", - "g = rdflib.Graph()\n", - "\n", - "# Parse our json-ld data into the graph\n", - "g.parse(data=json.dumps(jsonld), format=\"json-ld\")\n", - "\n", - "# Create a SPARQL query to return all the triples in the graph\n", - "query_all = \"\"\"\n", - "SELECT ?subject ?predicate ?object\n", - "WHERE {\n", - " ?subject ?predicate ?object\n", - "}\n", - "\"\"\"\n", - "\n", - "# Execute the SPARQL query\n", - "all_the_things = g.query(query_all)\n", - "\n", - "# Print the results\n", - "for row in all_the_things:\n", - " print(row)\n" - ], + "execution_count": 44, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -143,11 +120,10 @@ "id": "zWibLw6NIrrq", "outputId": "6be74891-73f3-43ff-a4d1-29b6697f8b11" }, - "execution_count": 44, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "(rdflib.term.BNode('N4c3bba051ecb4cb7a8336502c67cf29b'), rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), rdflib.term.URIRef('file:///content/NominalCapacity'))\n", "(rdflib.term.BNode('N4c52ea3012a7451c8194bcd5f42b1679'), rdflib.term.URIRef('https://schema.org/manufacturer'), rdflib.term.URIRef('https://www.wikidata.org/wiki/Q3041255'))\n", @@ -162,10 +138,35 @@ "(rdflib.term.URIRef('https://www.wikidata.org/wiki/Q3041255'), rdflib.term.URIRef('https://schema.org/name'), rdflib.term.Literal('SINTEF'))\n" ] } + ], + "source": [ + "# Create a new graph\n", + "g = rdflib.Graph()\n", + "\n", + "# Parse our json-ld data into the graph\n", + "g.parse(data=json.dumps(jsonld), format=\"json-ld\")\n", + "\n", + "# Create a SPARQL query to return all the triples in the graph\n", + "query_all = \"\"\"\n", + "SELECT ?subject ?predicate ?object\n", + "WHERE {\n", + " ?subject ?predicate ?object\n", + "}\n", + "\"\"\"\n", + "\n", + "# Execute the SPARQL query\n", + "all_the_things = g.query(query_all)\n", + "\n", + "# Print the results\n", + "for row in all_the_things:\n", + " print(row)\n" ] }, { "cell_type": "markdown", + "metadata": { + "id": "C-w1TbxkI4W5" + }, "source": [ "You can see that our human-readable JSON-LD file has been transformed into some nasty looking (but machine-readable!) triples. Let's look at a couple in more detail to understand what's going on.

\n", "\n", @@ -201,13 +202,27 @@ "## Query the graph using SPARQL [Moderate]\n", "\n", "Now, let's write a SPARQL query to get back some specific thing...like what is the name of the manufacturer?" - ], - "metadata": { - "id": "C-w1TbxkI4W5" - } + ] }, { "cell_type": "code", + "execution_count": 45, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6bXHGG4cI-kr", + "outputId": "5c79fa6e-50a4-4fc2-c513-149bd8cd9170" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(rdflib.term.Literal('SINTEF'),)\n" + ] + } + ], "source": [ "query = \"\"\"\n", "PREFIX schema: \n", @@ -225,39 +240,39 @@ "# Print the results\n", "for row in results:\n", " print(row)\n" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "6bXHGG4cI-kr", - "outputId": "5c79fa6e-50a4-4fc2-c513-149bd8cd9170" - }, - "execution_count": 45, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "(rdflib.term.Literal('SINTEF'),)\n" - ] - } ] }, { "cell_type": "markdown", + "metadata": { + "id": "b7LJC8BubFce" + }, "source": [ "## Fetch additional information from other sources [Advanced]\n", "Ontologies contain a lot of information about the meaning of things, but they don't always contain an exhaustive list of all the properties. Instead, they often point to other sources where that information exists rather than duplicating it. Let's see how you can use the ontology to fetch additional information from other sources.\n", "\n", "First, we parse the ontology into the knowledge graph and retrieve the IRIs for the terms that we are interested in. In this case, we want to retrieve more information about CR2032 from Wikidata, so we query the ontology to find CR2032's Wikidata ID." - ], - "metadata": { - "id": "b7LJC8BubFce" - } + ] }, { "cell_type": "code", + "execution_count": 46, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ntT1Rf_yM6sZ", + "outputId": "7eb1b90f-c97e-4d1e-b311-ca9355501c2e" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Wikidata ID of CR2032: Q5013811\n" + ] + } + ], "source": [ "# Parse the ontology into the knowledge graph\n", "ontology = \"https://raw.githubusercontent.com/emmo-repo/domain-battery/master/inferred_version/battery-inferred.ttl\"\n", @@ -285,36 +300,36 @@ " wikidata_id = row.wikidataId.split('/')[-1]\n", "\n", "print(f\"The Wikidata ID of CR2032: {wikidata_id}\")" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XGXFrNa5dKSr" + }, + "source": [ + "Now that we have the Wikidata ID for CR2032, we can query their SPARQL endpoint to retrieve some property. Let's ask it for the thickness." + ] + }, + { + "cell_type": "code", + "execution_count": 47, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, - "id": "ntT1Rf_yM6sZ", - "outputId": "7eb1b90f-c97e-4d1e-b311-ca9355501c2e" + "id": "zTBOZAf-dWQQ", + "outputId": "9f9d1c00-d74f-4c76-ceb5-b58b21853c41" }, - "execution_count": 46, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ - "The Wikidata ID of CR2032: Q5013811\n" + "Wikidata says the thickness of a CR2032 cell is: 20 http://www.wikidata.org/entity/Q174789\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "Now that we have the Wikidata ID for CR2032, we can query their SPARQL endpoint to retrieve some property. Let's ask it for the thickness." ], - "metadata": { - "id": "XGXFrNa5dKSr" - } - }, - { - "cell_type": "code", "source": [ "# Query the Wikidata knowledge graph for more information about zinc\n", "wikidata_endpoint = \"https://query.wikidata.org/sparql\"\n", @@ -340,57 +355,20 @@ "thickness = data['results']['bindings'][0]['value']['value']\n", "unit = data['results']['bindings'][0]['unit']['value']\n", "print(f\"Wikidata says the thickness of a CR2032 cell is: {thickness} {unit}\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "zTBOZAf-dWQQ", - "outputId": "9f9d1c00-d74f-4c76-ceb5-b58b21853c41" - }, - "execution_count": 47, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Wikidata says the thickness of a CR2032 cell is: 20 http://www.wikidata.org/entity/Q174789\n" - ] - } ] }, { "cell_type": "markdown", - "source": [ - "We can also retrieve more complex data. For example, let's ask Wikidata to show us an image of a CR2032." - ], "metadata": { "id": "-xdSIS6Idy5m" - } + }, + "source": [ + "We can also retrieve more complex data. For example, let's ask Wikidata to show us an image of a CR2032." + ] }, { "cell_type": "code", - "source": [ - "# SPARQL query to get the image of the CR2032 cell (Q758)\n", - "query = \"\"\"\n", - "SELECT ?image WHERE {\n", - " wd:%s wdt:P18 ?image .\n", - "}\n", - "\"\"\" % wikidata_id\n", - "\n", - "# Execute the request\n", - "response = requests.get(wikidata_endpoint, params={'query': query, 'format': 'json'})\n", - "data = response.json()\n", - "\n", - "# Extract and display the image URL\n", - "if data['results']['bindings']:\n", - " image_url = data['results']['bindings'][0]['image']['value']\n", - " print(f\"Image of a CR2032- cell: {image_url}\")\n", - " display(Image(url=image_url, width=300)) # Adjust width and height as needed\n", - "\n", - "else:\n", - " print(\"No image found.\")" - ], + "execution_count": 48, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -399,17 +377,15 @@ "id": "T7bkBY0sNqNY", "outputId": "c9c3bcf4-d278-4acd-a93b-5a7d553d66fd" }, - "execution_count": 48, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Image of a CR2032- cell: http://commons.wikimedia.org/wiki/Special:FilePath/CR2032%20battery%2C%20KTS-2728.jpg\n" ] }, { - "output_type": "display_data", "data": { "text/html": [ "" @@ -418,21 +394,60 @@ "" ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "# SPARQL query to get the image of the CR2032 cell (Q758)\n", + "query = \"\"\"\n", + "SELECT ?image WHERE {\n", + " wd:%s wdt:P18 ?image .\n", + "}\n", + "\"\"\" % wikidata_id\n", + "\n", + "# Execute the request\n", + "response = requests.get(wikidata_endpoint, params={'query': query, 'format': 'json'})\n", + "data = response.json()\n", + "\n", + "# Extract and display the image URL\n", + "if data['results']['bindings']:\n", + " image_url = data['results']['bindings'][0]['image']['value']\n", + " print(f\"Image of a CR2032- cell: {image_url}\")\n", + " display(Image(url=image_url, width=300)) # Adjust width and height as needed\n", + "\n", + "else:\n", + " print(\"No image found.\")" ] }, { "cell_type": "markdown", - "source": [ - "Finally, let's retireve the id for CR2032 in the Google Knowledge Graph and see what it has to say!" - ], "metadata": { "id": "mRcFo-MBDVBW" - } + }, + "source": [ + "Finally, let's retireve the id for CR2032 in the Google Knowledge Graph and see what it has to say!" + ] }, { "cell_type": "code", + "execution_count": 49, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nAAC5bo8FLD6", + "outputId": "d3543deb-ce22-4d90-f054-6b705c94fb49" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Google Knowledge Graph entry for a CR2032 cell: https://www.google.com/search?kgmid=/g/11bc5qf2g9\n" + ] + } + ], "source": [ "# SPARQL query to get the Google Knowledge Graph ID of the CR2032 cell\n", "query = \"\"\"\n", @@ -454,33 +469,21 @@ "\n", "else:\n", " print(\"None found.\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "nAAC5bo8FLD6", - "outputId": "d3543deb-ce22-4d90-f054-6b705c94fb49" - }, - "execution_count": 49, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "The Google Knowledge Graph entry for a CR2032 cell: https://www.google.com/search?kgmid=/g/11bc5qf2g9\n" - ] - } ] + } + ], + "metadata": { + "colab": { + "provenance": [] }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "T1qUAeCDVNq3" - }, - "execution_count": 49, - "outputs": [] + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/sphinx/example_linked_data_custom_battery_cell_metadata.ipynb b/sphinx/example_linked_data_custom_battery_cell_metadata.ipynb index 7388b3d..e6838fe 100644 --- a/sphinx/example_linked_data_custom_battery_cell_metadata.ipynb +++ b/sphinx/example_linked_data_custom_battery_cell_metadata.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "1wseTQGaB4x9" + }, "source": [ "# Example: Custom Battery Cell Metadata\n", "\n", @@ -29,23 +18,25 @@ "- How to use the ontology to fetch more information from other sources **[Advanced]** \n", "\n", "A live version of this notebook is available on Google Colab [here](https://colab.research.google.com/drive/1k3dGZTz4bDeH4JPToqXsN0svCUkswPDN?usp=sharing)\n" - ], - "metadata": { - "id": "1wseTQGaB4x9" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "jcTVz9-DEh3m" + }, "source": [ "## Describe the powder using ontology terms in JSON-LD format\n", "The JSON-LD data that we will use is:" - ], - "metadata": { - "id": "jcTVz9-DEh3m" - } + ] }, { "cell_type": "code", + "execution_count": 48, + "metadata": { + "id": "gohQKEBrF2QP" + }, + "outputs": [], "source": [ "jsonld_LFPGr = {\n", " \"@context\": \"https://raw.githubusercontent.com/emmo-repo/domain-battery/master/context.json\",\n", @@ -112,78 +103,62 @@ " \"hasMeasurementUnit\": \"emmo:Volt\"\n", " }\n", " }" - ], - "metadata": { - "id": "gohQKEBrF2QP" - }, - "execution_count": 48, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "in30p-x4H91Y" + }, "source": [ "## Parse this description into a graph\n", "Now let's see how a machine would process this data by reading it into a Graph!\n", "\n", - "First, we install and import the python dependencies that we need for this example." - ], - "metadata": { - "id": "in30p-x4H91Y" - } + "First, we install and import the python dependencies that we need for this example.\n", + "\n", + "Note, the `pip install` statement is to be run in a shell/terminal." + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], "source": [ - "# Install and import dependencies\n", - "!pip install jsonschema rdflib requests matplotlib > /dev/null\n", - "\n", - "import json\n", - "import rdflib\n", - "import requests\n", - "import sys\n", - "from IPython.display import Image, display\n", - "import matplotlib.pyplot as plt" - ], + "# Install dependencies\n", + "pip install jsonschema rdflib requests matplotlib > /dev/null" + ] + }, + { + "cell_type": "code", + "execution_count": 49, "metadata": { "id": "wk4sFl_eA2ML" }, - "execution_count": 49, - "outputs": [] + "outputs": [], + "source": [ + "# Import dependencies\n", + "import json\n", + "import rdflib\n", + "import requests" + ] }, { "cell_type": "markdown", - "source": [ - "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." - ], "metadata": { "id": "lotp-0QABV-2" - } + }, + "source": [ + "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." + ] }, { "cell_type": "code", - "source": [ - "# Create a new graph\n", - "g = rdflib.Graph()\n", - "\n", - "# Parse our json-ld data into the graph\n", - "g.parse(data=json.dumps(jsonld_LFPGr), format=\"json-ld\")\n", - "g.parse(data=json.dumps(jsonld_LNOGr), format=\"json-ld\")\n", - "\n", - "# Create a SPARQL query to return all the triples in the graph\n", - "query_all = \"\"\"\n", - "SELECT ?subject ?predicate ?object\n", - "WHERE {\n", - " ?subject ?predicate ?object\n", - "}\n", - "\"\"\"\n", - "\n", - "# Execute the SPARQL query\n", - "all_the_things = g.query(query_all)\n", - "\n", - "# Print the results\n", - "for row in all_the_things:\n", - " print(row)\n" - ], + "execution_count": 50, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -191,11 +166,10 @@ "id": "zWibLw6NIrrq", "outputId": "785ba3d8-9dbc-4b89-df62-931c96bb8216" }, - "execution_count": 50, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "(rdflib.term.BNode('N1fa58317b5c04a40bdc836b0e29a051d'), rdflib.term.URIRef('https://schema.org/name'), rdflib.term.Literal('My LFP-Graphite R2032 Coin Cell'))\n", "(rdflib.term.BNode('Na8888f67843f40fa8bc9efe32a39bd02'), rdflib.term.URIRef('http://emmo.info/electrochemistry#electrochemistry_860aa941_5ff9_4452_8a16_7856fad07bee'), rdflib.term.BNode('N1fe8535096ed436e92cc736bb203262f'))\n", @@ -240,23 +214,63 @@ "(rdflib.term.BNode('N1fa58317b5c04a40bdc836b0e29a051d'), rdflib.term.URIRef('http://emmo.info/electrochemistry#electrochemistry_5d299271_3f68_494f_ab96_3db9acdd3138'), rdflib.term.BNode('N318dda34a11b4390946ce22a6278c83c'))\n" ] } + ], + "source": [ + "# Create a new graph\n", + "g = rdflib.Graph()\n", + "\n", + "# Parse our json-ld data into the graph\n", + "g.parse(data=json.dumps(jsonld_LFPGr), format=\"json-ld\")\n", + "g.parse(data=json.dumps(jsonld_LNOGr), format=\"json-ld\")\n", + "\n", + "# Create a SPARQL query to return all the triples in the graph\n", + "query_all = \"\"\"\n", + "SELECT ?subject ?predicate ?object\n", + "WHERE {\n", + " ?subject ?predicate ?object\n", + "}\n", + "\"\"\"\n", + "\n", + "# Execute the SPARQL query\n", + "all_the_things = g.query(query_all)\n", + "\n", + "# Print the results\n", + "for row in all_the_things:\n", + " print(row)\n" ] }, { "cell_type": "markdown", + "metadata": { + "id": "C-w1TbxkI4W5" + }, "source": [ "You can see that our human-readable JSON-LD file has been transformed into some nasty looking (but machine-readable!) triples.\n", "\n", "## Query the Graph to select instances with certain properties [Advanced]\n", "\n", "Now, let's write a SPARQL query to return the names of cells that have a nominal voltage greater than 3.5 V?" - ], - "metadata": { - "id": "C-w1TbxkI4W5" - } + ] }, { "cell_type": "code", + "execution_count": 51, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6bXHGG4cI-kr", + "outputId": "d74c6a2b-9dc7-4c7f-b5b2-7db4643f310d" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(rdflib.term.Literal('My LNO-Graphite R2032 Coin Cell'),)\n" + ] + } + ], "source": [ "# Fetch the context\n", "context_url = 'https://raw.githubusercontent.com/emmo-repo/domain-battery/master/context.json'\n", @@ -295,38 +309,38 @@ "# Print the results\n", "for row in results:\n", " print(row)\n" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "b7LJC8BubFce" + }, + "source": [ + "## Fetch additional information from other sources [Advanced]\n", + "\n", + "Ontologies contain a lot of information about the meaning of things, but they don't always contain an exhaustive list of all the properties. Instead, they often point to other sources where that information exists rather than duplicating it. Let's see how you can use the ontology to fetch additional information from other sources." + ] + }, + { + "cell_type": "code", + "execution_count": 52, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, - "id": "6bXHGG4cI-kr", - "outputId": "d74c6a2b-9dc7-4c7f-b5b2-7db4643f310d" + "id": "ntT1Rf_yM6sZ", + "outputId": "8945b2dc-8573-4d8e-e1b7-a0d2709569e5" }, - "execution_count": 51, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ - "(rdflib.term.Literal('My LNO-Graphite R2032 Coin Cell'),)\n" + "The PubChem ID of Lithiun Nickel Oxide is: Q81988484\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Fetch additional information from other sources [Advanced]\n", - "\n", - "Ontologies contain a lot of information about the meaning of things, but they don't always contain an exhaustive list of all the properties. Instead, they often point to other sources where that information exists rather than duplicating it. Let's see how you can use the ontology to fetch additional information from other sources." ], - "metadata": { - "id": "b7LJC8BubFce" - } - }, - { - "cell_type": "code", "source": [ "# Parse the ontology into the knowledge graph\n", "ontology = \"https://raw.githubusercontent.com/emmo-repo/domain-electrochemistry/master/electrochemistry-inferred.ttl\"\n", @@ -354,36 +368,36 @@ " wikidata_id = row.wikidataId.split('/')[-1]\n", "\n", "print(f\"The PubChem ID of Lithiun Nickel Oxide is: {wikidata_id}\")" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mRcFo-MBDVBW" + }, + "source": [ + "Finally, let's retireve more information about Lithium Nickel Oxide from Wikidata and PubChem" + ] + }, + { + "cell_type": "code", + "execution_count": 53, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, - "id": "ntT1Rf_yM6sZ", - "outputId": "8945b2dc-8573-4d8e-e1b7-a0d2709569e5" + "id": "nAAC5bo8FLD6", + "outputId": "7bc59e2f-2892-4163-c1fa-d129b96f3433" }, - "execution_count": 52, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ - "The PubChem ID of Lithiun Nickel Oxide is: Q81988484\n" + "The PubChem ID for a LithiumNickelOxide cell: 138395181\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "Finally, let's retireve more information about Lithium Nickel Oxide from Wikidata and PubChem" ], - "metadata": { - "id": "mRcFo-MBDVBW" - } - }, - { - "cell_type": "code", "source": [ "# Query the Wikidata knowledge graph for more information\n", "wikidata_endpoint = \"https://query.wikidata.org/sparql\"\n", @@ -406,57 +420,22 @@ "\n", "else:\n", " print(\"None found.\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "nAAC5bo8FLD6", - "outputId": "7bc59e2f-2892-4163-c1fa-d129b96f3433" - }, - "execution_count": 53, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "The PubChem ID for a LithiumNickelOxide cell: 138395181\n" - ] - } ] }, { "cell_type": "code", - "source": [ - "def get_pubchem_compound_data(cid):\n", - " base_url = \"https://pubchem.ncbi.nlm.nih.gov/rest/pug\"\n", - " compound_url = f\"{base_url}/compound/cid/{cid}/JSON\"\n", - " response = requests.get(compound_url)\n", - " if response.status_code == 200:\n", - " return response.json()\n", - " else:\n", - " return None\n", - "\n", - "# Fetch data for the compound with CID 138395181\n", - "compound_data = get_pubchem_compound_data(PubChemId)\n", - "if compound_data:\n", - " pretty_json = json.dumps(compound_data, indent=4) # Pretty-print the JSON data\n", - " print(pretty_json)\n", - "else:\n", - " print(\"Data not found or error in API request.\")" - ], + "execution_count": 54, "metadata": { - "id": "T1qUAeCDVNq3", "colab": { "base_uri": "https://localhost:8080/" }, + "id": "T1qUAeCDVNq3", "outputId": "9fabdf0b-adda-4d94-e85c-067efea39029" }, - "execution_count": 54, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "{\n", " \"PC_Compounds\": [\n", @@ -844,7 +823,39 @@ "}\n" ] } + ], + "source": [ + "def get_pubchem_compound_data(cid):\n", + " base_url = \"https://pubchem.ncbi.nlm.nih.gov/rest/pug\"\n", + " compound_url = f\"{base_url}/compound/cid/{cid}/JSON\"\n", + " response = requests.get(compound_url)\n", + " if response.status_code == 200:\n", + " return response.json()\n", + " else:\n", + " return None\n", + "\n", + "# Fetch data for the compound with CID 138395181\n", + "compound_data = get_pubchem_compound_data(PubChemId)\n", + "if compound_data:\n", + " pretty_json = json.dumps(compound_data, indent=4) # Pretty-print the JSON data\n", + " print(pretty_json)\n", + "else:\n", + " print(\"Data not found or error in API request.\")" ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/sphinx/example_linked_data_timeseries_battery_data.ipynb b/sphinx/example_linked_data_timeseries_battery_data.ipynb index 1711df4..fe3a312 100644 --- a/sphinx/example_linked_data_timeseries_battery_data.ipynb +++ b/sphinx/example_linked_data_timeseries_battery_data.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "1wseTQGaB4x9" + }, "source": [ "# Example: Timeseries Battery Data\n", "\n", @@ -27,43 +16,58 @@ "- How machines convert JSON-LD into triples \n", "- How to process tabular data using its ontology metadata **[Advanced]** \n", "\n", - "A live version of this notebook is available on Google Colab [here](https://colab.research.google.com/drive/1i-z6m6MEtQw_MG0Ypn37i0jfySYwize3?usp=sharing)\n" - ], + "A live version of this notebook is available on Google Colab [here](https://colab.research.google.com/drive/1i-z6m6MEtQw_MG0Ypn37i0jfySYwize3?usp=sharing)\n", + "\n", + "Note, the `pip install` statement is to be run in a shell/terminal." + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { - "id": "1wseTQGaB4x9" - } + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "# Import dependencies\n", + "pip install jsonschema rdflib requests matplotlib > /dev/null" + ] }, { "cell_type": "code", + "execution_count": 64, + "metadata": { + "id": "GoMrOFoalJ4L" + }, + "outputs": [], "source": [ - "# Install and import dependencies\n", - "!pip install jsonschema rdflib requests matplotlib > /dev/null\n", - "\n", + "# Import dependencies\n", "import json\n", "import rdflib\n", "import requests\n", - "import sys\n", "import pandas as pd\n", "import matplotlib.pyplot as plt" - ], - "metadata": { - "id": "GoMrOFoalJ4L" - }, - "execution_count": 64, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "jcTVz9-DEh3m" + }, "source": [ "## Describe the csv file using ontology terms in JSON-LD format\n", "The JSON-LD data that we will use is:" - ], - "metadata": { - "id": "jcTVz9-DEh3m" - } + ] }, { "cell_type": "code", + "execution_count": 65, + "metadata": { + "id": "gohQKEBrF2QP" + }, + "outputs": [], "source": [ "metadata = {\n", " \"@context\": \"https://raw.githubusercontent.com/emmo-repo/domain-battery/master/context.json\",\n", @@ -110,56 +114,30 @@ " \"csvw:aboutUrl\": \"#time-{time}\"\n", " }\n", " }" - ], - "metadata": { - "id": "gohQKEBrF2QP" - }, - "execution_count": 65, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "in30p-x4H91Y" + }, "source": [ "## Parse this description into a graph\n", "Now let's see how a machine would process this data by reading it into a Graph!\n" - ], - "metadata": { - "id": "in30p-x4H91Y" - } + ] }, { "cell_type": "markdown", - "source": [ - "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." - ], "metadata": { "id": "lotp-0QABV-2" - } + }, + "source": [ + "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." + ] }, { "cell_type": "code", - "source": [ - "# Create a new graph\n", - "g = rdflib.Graph()\n", - "\n", - "# Parse our json-ld data into the graph\n", - "g.parse(data=json.dumps(metadata), format=\"json-ld\")\n", - "\n", - "# Create a SPARQL query to return all the triples in the graph\n", - "query_all = \"\"\"\n", - "SELECT ?subject ?predicate ?object\n", - "WHERE {\n", - " ?subject ?predicate ?object\n", - "}\n", - "\"\"\"\n", - "\n", - "# Execute the SPARQL query\n", - "all_the_things = g.query(query_all)\n", - "\n", - "# Print the results\n", - "for row in all_the_things:\n", - " print(row)\n" - ], + "execution_count": 66, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -167,11 +145,10 @@ "id": "zWibLw6NIrrq", "outputId": "99b89cbb-cd31-4020-ed18-e91f4ad322a6" }, - "execution_count": 66, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "(rdflib.term.BNode('Ne0e29b515ec84d53800f1108468b85fc'), rdflib.term.URIRef('http://www.w3.org/ns/csvw#name'), rdflib.term.Literal('time'))\n", "(rdflib.term.BNode('Nd0887b1b0a7741c588e7c70dc5b3f56b'), rdflib.term.URIRef('http://www.w3.org/ns/csvw#datatype'), rdflib.term.Literal('number'))\n", @@ -211,23 +188,62 @@ "(rdflib.term.BNode('Ncc179b393bc14fdeae7d2a34157c3cd2'), rdflib.term.URIRef('http://www.w3.org/ns/csvw#columns'), rdflib.term.BNode('Nd0887b1b0a7741c588e7c70dc5b3f56b'))\n" ] } + ], + "source": [ + "# Create a new graph\n", + "g = rdflib.Graph()\n", + "\n", + "# Parse our json-ld data into the graph\n", + "g.parse(data=json.dumps(metadata), format=\"json-ld\")\n", + "\n", + "# Create a SPARQL query to return all the triples in the graph\n", + "query_all = \"\"\"\n", + "SELECT ?subject ?predicate ?object\n", + "WHERE {\n", + " ?subject ?predicate ?object\n", + "}\n", + "\"\"\"\n", + "\n", + "# Execute the SPARQL query\n", + "all_the_things = g.query(query_all)\n", + "\n", + "# Print the results\n", + "for row in all_the_things:\n", + " print(row)\n" ] }, { "cell_type": "markdown", + "metadata": { + "id": "C-w1TbxkI4W5" + }, "source": [ "You can see that our human-readable JSON-LD file has been transformed into some nasty looking (but machine-readable!) triples.\n", "\n", "## Query the Graph to select instances with certain properties [Advanced]\n", "\n", "Now, let's write a SPARQL query to first get the location where the raw data is stored..." - ], - "metadata": { - "id": "C-w1TbxkI4W5" - } + ] }, { "cell_type": "code", + "execution_count": 67, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bzvQgeS0mTTS", + "outputId": "5de79de6-916e-4f97-ffe9-1e51189d3d2b" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://raw.githubusercontent.com/BIG-MAP/BattINFO/master/sphinx/assets/data/discharge_timeseries.csv\n" + ] + } + ], "source": [ "# Create a SPARQL query to return url of the raw data\n", "query = \"\"\"\n", @@ -245,42 +261,20 @@ "for row in results:\n", " csv_url = str(row[0]) # Convert the Literal to a string\n", " print(csv_url)\n" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "bzvQgeS0mTTS", - "outputId": "5de79de6-916e-4f97-ffe9-1e51189d3d2b" - }, - "execution_count": 67, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "https://raw.githubusercontent.com/BIG-MAP/BattINFO/master/sphinx/assets/data/discharge_timeseries.csv\n" - ] - } ] }, { "cell_type": "markdown", - "source": [ - "Now we will read it into a pandas dataframe." - ], "metadata": { "id": "d4-xrCS0vHsy" - } + }, + "source": [ + "Now we will read it into a pandas dataframe." + ] }, { "cell_type": "code", - "source": [ - "# Read the CSV file into a pandas DataFrame\n", - "# You may need to adjust this based on the specifics of your CSV file\n", - "df = pd.read_csv(csv_url)\n", - "print(df.head(10))" - ], + "execution_count": 68, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -288,11 +282,10 @@ "id": "JK-mhTMqnUp-", "outputId": "d2144690-5f28-41b6-c4ec-e079c6178774" }, - "execution_count": 68, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ " Time / s Voltage / V Current / A\n", "0 0.00000 4.200000 0.0\n", @@ -307,19 +300,46 @@ "9 215.15625 4.027523 2.0\n" ] } + ], + "source": [ + "# Read the CSV file into a pandas DataFrame\n", + "# You may need to adjust this based on the specifics of your CSV file\n", + "df = pd.read_csv(csv_url)\n", + "print(df.head(10))" ] }, { "cell_type": "markdown", - "source": [ - "Finally, we can query the metadata in the Graph to check if certain quantities are present (using ontology terms for Time and CellVoltage) and if so, plot them together..." - ], "metadata": { "id": "sXV4KcIcvK_4" - } + }, + "source": [ + "Finally, we can query the metadata in the Graph to check if certain quantities are present (using ontology terms for Time and CellVoltage) and if so, plot them together..." + ] }, { "cell_type": "code", + "execution_count": 69, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 564 + }, + "id": "YgHzwFzwn1TB", + "outputId": "b5436c51-7d2a-441d-88ff-763bc550198b" + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA04AAAIjCAYAAAA0vUuxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABoX0lEQVR4nO3dd3hUZf7+8XvSe+8QCJAQelcgSFFQEASxIosi9lVc5aduYXd1Latg/VrWvivo7iJ2bCgLSBWU3iF0QkklvSeT8/sjZGQEJgkkOZPk/bquuWTOOXPmM5Oj5uZ5ns+xGIZhCAAAAABwTi5mFwAAAAAAzo7gBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANSC4AQAAAAAtSA4AQAAAEAtCE4AAAAAUAuCEwAAAADUguAEAGgQhw8flsVi0dy5c80updlavny5LBaLli9fbnYpAIBfITgBQCs0YcIE+fj4qKCg4JzHTJkyRR4eHjp58uR5v8/ChQv1+OOPn/frW4Jp06bJYrHU+pg2bZrZpQIAHHAzuwAAQNObMmWKvv76a33xxReaOnXqGfuLi4v15ZdfasyYMQoNDT3v91m4cKFef/31Vh2e7rnnHo0aNcr2/NChQ3rsscd09913a+jQobbtnTp10sCBA1VSUiIPDw8zSgUAOEBwAoBWaMKECfL399e8efPOGpy+/PJLFRUVacqUKSZU17IMHjxYgwcPtj3fsGGDHnvsMQ0ePFg333zzGcd7eXk1ZXkAgDpiqh4AtELe3t669tprtXTpUmVkZJyxf968efL399eECRMkSQcPHtQNN9ygkJAQ+fj4aNCgQfr2228dvse0adP0+uuvS5LdlLQaL7zwgpKSkhQaGipvb2/1799fn3766RnnKSkp0QMPPKCwsDBbTcePH5fFYjljJOv48eO6/fbbFRkZKU9PT3Xv3l3vvfderd9Hjx49dOmll56xvaqqSm3atNH1119v2zZ//nz1799f/v7+CggIUM+ePfXKK6/U+h51cbY1TiNGjFCPHj20bds2DR8+XD4+PoqPj7d9VytWrNDAgQPl7e2txMRELVmy5Izznu/3AgD4BcEJAFqpKVOmqLKyUh9//LHd9uzsbC1atEjXXHONvL29lZ6erqSkJC1atEj33Xefnn76aZWWlmrChAn64osvznn+e+65R5dffrkk6d///rftUeOVV15R37599eSTT+qZZ56Rm5ubbrjhhjMC2bRp0/Taa69p7NixevbZZ+Xt7a1x48ad8X7p6ekaNGiQlixZovvvv1+vvPKK4uPjdccdd+jll192+F1MmjRJK1euVFpamt321atX68SJE7rpppskSYsXL9bkyZMVHBysZ599VrNnz9aIESP0448/Ojz/hcrJydFVV12lgQMH6rnnnpOnp6duuukmffTRR7rppps0duxYzZ49W0VFRbr++uvt1q5dyPcCADiNAQBolSorK43o6Ghj8ODBdtvfeustQ5KxaNEiwzAMY8aMGYYkY9WqVbZjCgoKjA4dOhhxcXGG1Wo1DMMwDh06ZEgy5syZYztu+vTpxrn+V1NcXGz3vLy83OjRo4dx2WWX2bZt3LjRkGTMmDHD7thp06YZkoy//e1vtm133HGHER0dbWRlZdkde9NNNxmBgYFnvN/pkpOTDUnGa6+9Zrf9vvvuM/z8/GyvffDBB42AgACjsrLynOeqzfr168/4nmosW7bMkGQsW7bMtm348OGGJGPevHm2bXv27DEkGS4uLsZPP/1k275o0aIzzn0h3wsA4BeMOAFAK+Xq6qqbbrpJa9eu1eHDh23b582bp8jISI0cOVJSdYOHiy++WJdccontGD8/P9199906fPiwdu3adV7v7+3tbftzTk6O8vLyNHToUG3atMm2/fvvv5ck3XfffXav/d3vfmf33DAMffbZZxo/frwMw1BWVpbtMXr0aOXl5dmd99c6d+6sPn366KOPPrJts1qt+vTTTzV+/HhbrUFBQSoqKtLixYvP6zOfLz8/P9uolyQlJiYqKChIXbt21cCBA23ba/588OBBSRf+vQAAfkFwAoBWrKb5w7x58yRJx44d06pVq3TTTTfJ1dVVknTkyBElJiae8dquXbva9p+Pb775RoMGDZKXl5dCQkIUHh6uN998U3l5ebZjjhw5IhcXF3Xo0MHutfHx8XbPMzMzlZubq3feeUfh4eF2j9tuu02SzrqW63STJk3Sjz/+qOPHj0uqXm+UkZGhSZMm2Y6577771LlzZ1155ZVq27atbr/9dlu4a0xt27a1Wx8mSYGBgYqNjT1jm1QdRKWG+V4AANXoqgcArVj//v3VpUsXffjhh/rzn/+sDz/8UIZhNHo3vVWrVmnChAkaNmyY3njjDUVHR8vd3V1z5syxhbj6qKqqkiTdfPPNuvXWW896TK9evRyeY9KkSZo5c6Y++eQTzZgxQx9//LECAwM1ZswY2zERERHasmWLFi1apO+++07fffed5syZo6lTp+r999+vd911VRNi67rdMAxJDfO9AACqEZwAoJWbMmWKHn30UW3btk3z5s1TQkKCLrroItv+9u3bKzk5+YzX7dmzx7b/XH49SlLjs88+k5eXlxYtWiRPT0/b9jlz5tgd1759e1VVVenQoUNKSEiwbd+/f7/dceHh4fL395fVarW7Z1J9dOjQQRdffLE++ugj3X///fr88881ceJEu/okycPDQ+PHj9f48eNVVVWl++67T2+//bYeffTRM0bCzNYQ3wsAoBpT9QCglasZXXrssce0ZcuWM0abxo4dq3Xr1mnt2rW2bUVFRXrnnXcUFxenbt26nfPcvr6+kqTc3Fy77a6urrJYLLJarbZthw8f1oIFC+yOGz16tCTpjTfesNv+2muvnXG+6667Tp999pl27NhxRh2ZmZnnrPF0kyZN0k8//aT33ntPWVlZdtP0JOnkyZN2z11cXGwjNmVlZXV6j6bUUN8LAIARJwBo9Tp06KCkpCR9+eWXknRGcPrTn/6kDz/8UFdeeaUeeOABhYSE6P3339ehQ4f02WefycXl3H8H179/f0nSAw88oNGjR9saUowbN04vvfSSxowZo9/85jfKyMjQ66+/rvj4eG3bts3u9dddd51efvllnTx5UoMGDdKKFSu0d+9eSfYjWrNnz9ayZcs0cOBA3XXXXerWrZuys7O1adMmLVmyRNnZ2bV+FzfeeKMeeeQRPfLIIwoJCTljlObOO+9Udna2LrvsMrVt21ZHjhzRa6+9pj59+tjWfDmbhvheAACMOAEA9EtYuvjii8+YbhYZGak1a9bo8ssv12uvvaaZM2fKw8NDX3/9ta655hqH57322mv1u9/9Tt9//71uueUWTZ48WZJ02WWX6V//+pfS0tI0Y8YMffjhh3r22WfPer4PPvhA06dP17fffqs//vGPKi8vt3W/8/Lysqtz3bp1uu222/T555/b7lmUnZ2tZ599tk7fQ9u2bZWUlKSCggJde+21cnd3t9t/8803y8vLS2+88Ybuu+8+vf/++5o0aZK+++47hwHSTA3xvQAAJItRs4IUAIBmYsuWLerbt6/+85//NHojCwAAJEacAABOrqSk5IxtL7/8slxcXDRs2DATKgIAtEascQIAOLXnnntOGzdu1KWXXio3NzdbG/C77777jPsYAQDQWJiqBwBwaosXL9YTTzyhXbt2qbCwUO3atdMtt9yiv/zlL3Jz4+//AABNg+AEAAAAALVgjRMAAAAA1ILgBAAAAAC1aHWTw6uqqnTixAn5+/vb3TgRAAAAQOtiGIYKCgoUExNT6/34Wl1wOnHiBF2YAAAAANgcPXpUbdu2dXhMqwtO/v7+kqq/nICAAJOrAQAAAGCW/Px8xcbG2jKCI60uONVMzwsICCA4AQAAAKjTEh6aQwAAAABALQhOAAAAAFALghMAAAAA1KLVrXECAACAOQzDUGVlpaxWq9mloJVwdXWVm5tbg9yGiOAEAACARldeXq7U1FQVFxebXQpaGR8fH0VHR8vDw+OCzkNwAgAAQKOqqqrSoUOH5OrqqpiYGHl4eDTICADgiGEYKi8vV2Zmpg4dOqSEhIRab3LrCMEJAAAAjaq8vFxVVVWKjY2Vj4+P2eWgFfH29pa7u7uOHDmi8vJyeXl5nfe5aA4BAACAJnEhf9sPnK+Guu64egEAAACgFgQnAAAAAKgFwQkAAABoJHFxcXr55ZfNLsMpLF++XBaLRbm5uWaXcl4ITgAAAMCvjB8/XmPGjDnrvlWrVslisWjbtm31Pq/FYtGCBQsusDrnM23aNFkslnM+4uLilJSUpNTUVAUGBppd7nkhOAEAAAC/cscdd2jx4sU6duzYGfvmzJmjAQMGqFevXiZU5pxeeeUVpaam2h5S9fdU83z9+vXy8PBQVFRUs21FT3ACAABAkzIMQ8XllaY8DMOoU41XXXWVwsPDNXfuXLvthYWF+uSTT3THHXdIkj777DN1795dnp6eiouL04svvnjOc8bFxUmSrrnmGtsojCQdOHBAV199tSIjI+Xn56eLLrpIS5YssXttamqqxo0bJ29vb3Xo0EHz5s07Yxpgbm6u7rzzToWHhysgIECXXXaZtm7des56kpKS9Mc//tFuW2Zmptzd3bVy5UpJ0htvvKGEhAR5eXkpMjJS119//VnPFRgYqKioKNtDkoKCgmzPw8PDz5iqN3fuXAUFBembb75RYmKifHx8dP3116u4uFjvv/++4uLiFBwcrAceeEBWq9X2XmVlZXrkkUfUpk0b+fr6auDAgVq+fPk5P2dD4T5OAAAAaFIlFVZ1e2yRKe+968nR8vGo/VdgNzc3TZ06VXPnztVf/vIX2yjJJ598IqvVqsmTJ2vjxo268cYb9fjjj2vSpElas2aN7rvvPoWGhmratGlnnHP9+vWKiIjQnDlzNGbMGLm6ukqqDmNjx47V008/LU9PT33wwQcaP368kpOT1a5dO0nS1KlTlZWVpeXLl8vd3V0PPfSQMjIy7M5/ww03yNvbW999950CAwP19ttva+TIkdq7d69CQkLOqGfKlCl67rnnNHv2bNvn++ijjxQTE6OhQ4dqw4YNeuCBB/Tvf/9bSUlJys7O1qpVq+r1fdemuLhYr776qubPn6+CggJde+21uuaaaxQUFKSFCxfq4MGDuu666zRkyBBNmjRJknT//fdr165dmj9/vmJiYvTFF19ozJgx2r59uxISEhq0vtMRnAAAAICzuP322/X8889rxYoVGjFihKTq6WfXXXedAgMD9dJLL2nkyJF69NFHJUmdO3fWrl279Pzzz581OIWHh0v6ZSSmRu/evdW7d2/b86eeekpffPGFvvrqK91///3as2ePlixZovXr12vAgAGSpH/+8592IWH16tVat26dMjIy5OnpKUl64YUXtGDBAn366ae6++67z6jnxhtv1IwZM7R69WoNHTpUkjRv3jxNnjxZFotFKSkp8vX11VVXXSV/f3+1b99effv2vYBv9EwVFRV688031alTJ0nS9ddfr3//+99KT0+Xn5+funXrpksvvVTLli3TpEmTlJKSojlz5iglJUUxMTGSpEceeUTff/+95syZo2eeeaZB6zsdwclEm1NylJZXqm4xAWof6mt2OQAAAE3C291Vu54cbdp711WXLl2UlJSk9957TyNGjND+/fu1atUqPfnkk5Kk3bt36+qrr7Z7zZAhQ/Tyyy/LarXaRpRqU1hYqMcff1zffvutUlNTVVlZqZKSEqWkpEiSkpOT5ebmpn79+tleEx8fr+DgYNvzrVu3qrCwUKGhoXbnLikp0YEDB876vuHh4briiiv03//+V0OHDtWhQ4e0du1avf3225Kkyy+/XO3bt1fHjh01ZswYjRkzRtdcc418fHzq9LnqwsfHxxaaJCkyMlJxcXHy8/Oz21YzurZ9+3ZZrVZ17tzZ7jxlZWVnfPaGRnAy0burDmrh9jQ9eXV3TR1McAIAAK2DxWKp03Q5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7LPPdM899yg3N1dWq7WhamsU+fn5CgwMVF5engICAswuBwAAtGKpeSWa8u7POphVpDZB3vr4t4PVJsjb7LKAVqM+2eCCuuotX75c06ZN07Rp02S1WnXXXXddyOkAAABalehAb310z2B1DPfV8dwSTXn3J2Ww5glwSvUOTseOHdPf//53xcfH67LLLtPhw4f1xhtvKDU1VW+99VZj1AgAANBihft76r93DlTbYG8dPlmsm//1s7KLys0uC8Cv1Dk4ffzxxxozZow6dOigN998UzfeeKP27t2rFStWaOrUqfL2ZlgZAADgfEQHemvenYMUFeClvemFmvrezyrkPk+AU6lzcLr55pvl7e2tL774QkePHtUzzzyj+Pj4xqwNAACg1WgX6qP/3DlQob4e2nE8X/f+Z6MqrFVmlwXglDo3h8jIyFBERERj19PoaA4BAACc2bZjuZr09k8qqbDqun5t9cINvWSxWMwuC2iRGqU5REsITQAAAM6uV9sgvTGln1xdLPps0zG9tHiv2SUB0AV21QMAAEDDu7RLhJ65pock6bUf9uu/Px8xuSIABCcAAAAnNOmidnpwZIIk6dEFO7R0d7rJFQGtW52D08GDBxuzDgAAAPzKjFEJunFAW1UZ0v3zNmvL0VyzSwJarToHp169eqlHjx7685//rJ9//rkxawIAAIAki8Wip6/pqeGdw1VSYdXtc9frcFaR2WUBrVKdg1NWVpZmzZqljIwMXX311YqOjtZdd92lr7/+WqWl3OEaAACgMbi7uuiNKf3Us02gsovKdeucdTpZWGZ2WUCrU+d25KczDENr167VV199pa+++kopKSkaNWqUJkyYoPHjxys8PLwxam0QtCMHAADNUWZBma5980cdzS5R33ZB+vCuQfJydzW7LKBZa5R25KezWCxKSkrS7NmztWvXLm3evFlDhw7V3Llz1bZtW73++uvnVTgAAADOLtzfU3Nvu1iB3u7anJKrB+dvlrWq3n//DeA8ndeIkyMnT55Udna2EhISGvK0DYYRJwAA0JytO5Stm//5s8qtVbp9SAc9Nr6b2SUBzVajjzg5Ehoa6rShCQAAoLm7uEOIXryxtyTpvR8P6b3Vh0yuCGgduI8TAABAMzO+d4z+dGUXSdJT3+7S9zvSTK4IaPkITgAAAM3QPcM66uZB7WQY0oPzN2tTSo7ZJQEtGsEJ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zkuj3scpNTVVSUlJZ2xPSkqyGx0CAABAyxTq56nfXFw96vTmsgMmVwM0jXoHp/j4eH388cdnbP/oo4+UkJDQIEUBAADAud05tKM8XF207nC21h/ONrscoNHVqR356Z544glNmjRJK1eu1JAhQyRJP/74o5YuXXrWQAUAAICWJyrQS9f1b6MP1x3VG8v2a85tF5tdEtCo6jzitGPHDknSddddp59//llhYWFasGCBFixYoLCwMK1bt07XXHNNoxUKAAAA53LPsE5ysUjLkjO180Se2eUAjarOzSFcXFx00UUX6c4779RNN90kf//mecMzmkMAAAA0nN99uFlfbz2hq3pF6x+/6Wd2OUC9NEpziBUrVqh79+56+OGHFR0drWnTpmnVqlUXXCwAAACar3uHd5IkLdyeqkNZRSZXAzSeOgenoUOH6r333lNqaqpee+01HTp0SMOHD1fnzp317LPPKi0trTHrBAAAgBPqFhOgSxPDVWVIH6w9bHY5QKOpd1c9X19f3XbbbVqxYoX27t2rG264Qa+//rratWunCRMmNEaNAAAAcGK3JsVJkj7beEylFVZziwEaSb2D0+ni4+P15z//WX/961/l7++vb7/9tqHqAgAAQDMxLCFcbYK8lV9aqW+3cV9PtEznHZxWrlypadOmKSoqSr///e917bXX6scff2zI2gAAANAMuLhYNPniWEnSh+tSTK4GaBz1Ck4nTpzQM888o86dO2vEiBHav3+/Xn31VZ04cULvvvuuBg0a1Fh1AgAAwIndOCBWri4WbTiSo73pBWaXAzS4OgenK6+8Uu3bt9drr72ma665Rrt379bq1at12223ydfXtzFrBAAAgJOLCPDSqK4RkqR5PzPqhJanzsHJ3d1dn376qY4dO6Znn31WiYmJjVkXAAAAmpnfDGwvSfp8E00i0PK41fXAr776qjHrAAAAQDM3ND5MbYO9dSynRN9uS9V1/duaXRLQYC6oqx4AAABQo7pJRDtJ0jyaRKCFITgBAACgwdzQv61cLNLGIzk6ml1sdjlAgyE4AQAAoMFEBHhpYIdQSdLC7dzTCS0HwQkAAAANalyvaEkEJ7QsBCcAAAA0qDE9ouRikbYey2O6HloMghMAAAAaVJifpwZ1rJ6u9y2jTmghCE4AAABocDXT9b7dRnBCy0BwAgAAQIMb0716ut7243k6crLI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BAUF2XXUQvNw7733GoGBgcby5cuN1NRU26O4uNh2zG9/+1ujXbt2xg8//GBs2LDBGDx4sDF48GDb/ppW1FdccYWxZcsW4/vvvzfCw8PP2or697//vbF7927j9ddfpxW1Ezu9q55hcA20dOvWrTPc3NyMp59+2ti3b5/x3//+1/Dx8TH+85//2I6ZPXu2ERQUZHz55ZfGtm3bjKuvvvqsbYn79u1r/Pzzz8bq1auNhIQEu7bEubm5RmRkpHHLLbcYO3bsMObPn2/4+PjQhtpJ3HrrrUabNm1s7cg///xzIywszPjDH/5gO4broGUpKCgwNm/ebGzevNmQZLz00kvG5s2bjSNHjhiG0XQ/7x9//NFwc3MzXnjhBWP37t3G3/72N9qRNwKCk4lee+01o127doaHh4dx8cUXGz/99JPZJeE8SDrrY86cObZjSkpKjPvuu88IDg42fHx8jGuuucZITU21O8/hw4eNK6+80vD29jbCwsKMhx9+2KioqLA7ZtmyZUafPn0MDw8Po2PHjnbvAefy6+DENdDyff3110aPHj0MT09Po0uXLsY777xjt7+qqsp49NFHjcjISMPT09MYOXKkkZycbHfMyZMnjcmTJxt+fn5GQECAcdtttxkFBQV2x2zdutW45JJLDE9PT6NNmzbG7NmzG/2zoW7y8/ONBx980GjXrp3h5eVldOzY0fjLX/5i10aa66BlWbZs2Vl/B7j11lsNw2jan/fHH39sdO7c2fDw8DC6d+9ufPvtt432uVsri2GcdjtrAAAAAMAZWOMEAAAAALUgOAEAAABALQhOAAAAAFALghMAAAAA1ILgBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANSC4AQAaFamTZumiRMnml0GAKCVcTO7AAAAalgsFof7//a3v+mVV16RYRhNVNGZVqxYoZtvvllHjx41rQYAQNMjOAEAnEZqaqrtzx999JEee+wxJScn27b5+fnJz8/PjNJsvvzyS40fP97UGgAATY+pegAApxEVFWV7BAYGymKx2G3z8/M7Y6reiBEj9Lvf/U4zZsxQcHCwIiMj9e6776qoqEi33Xab/P39FR8fr++++87uvXbs2KErr7xSfn5+ioyM1C233KKsrKxaa/zqq680YcKEs+47cuSIxo8fr+DgYPn6+qp79+5auHDhBX0nAADnQHACADR777//vsLCwrRu3Tr97ne/07333qsbbrhBSUlJ2rRpk6644grdcsstKi4uliTl5ubqsssuU9++fbVhwwZ9//33Sk9P14033ujwfXbu3KmMjAxddtllZ90/ffp0lZWVaeXKldq+fbueffZZ00fIAAANg6l6AIBmr3fv3vrrX/8qSZo5c6Zmz56tsLAw3XXXXZKkxx57TG+++aa2bdumQYMG6R//+If69u2rZ555xnaO9957T7Gxsdq7d686d+581vf58ssvNXr0aHl4eJx1f0pKiq677jr17NlTktSxY8eG/JgAABMx4gQAaPZ69epl+7Orq6tCQ0Nt4UWSIiMjJUkZGRmSpK1bt2rZsmW2NVN+fn7q0qWLJOnAgQPnfJ8vv/zynNP0JOmBBx7Q3//+dw0ZMkR/+9vftG3btgv6XAAA50FwAgA0e+7u7nbPLRaL3baabn1VVVWSpMLCQo0fP15btmyxe+zbt0/Dhg0763ukpqZq8+bNGjdu3DnruPPOO3Xw4EHdcsst2r59uwYMGKDXXnvtQj8eAMAJEJwAAK1Ov379tHPnTsXFxSk+Pt7u4evre9bXfP3110pKSlJISIjDc8fGxuq3v/2tPv/8cz388MN69913G+MjAACaGMEJANDqTJ8+XdnZ2Zo8ebLWr1+vAwcOaNGiRbrttttktVrP+hpH3fRqzJgxQ4sWLdKhQ4e0adMmLVu2TF27dm2MjwAAaGIEJwBAqxMTE6Mff/xRVqtVV1xxhXr27KkZM2YoKChILi5n/q+xqKhIS5curTU4Wa1WTZ8+XV27dtWYMWPUuXNnvfHGG431MQAATchimHn7dQAAmoHPP/9cf/3rX7Vr1y6zSwEAmIQRJwAAauHn56dnn33W7DIAACZixAkAAAAAasGIEwAAAADUguAEAAAAALUgOAEAAABALQhOAAAAAFALghMAAAAA1ILgBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANTi/wMPiSjEF+6LlQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Extract column names for 'Time' and 'CellVoltage' based on propertyUrl\n", "time_column = None\n", @@ -387,28 +407,21 @@ " plt.show()\n", "else:\n", " print(\"Required columns not found in metadata.\")\n" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 564 - }, - "id": "YgHzwFzwn1TB", - "outputId": "b5436c51-7d2a-441d-88ff-763bc550198b" - }, - "execution_count": 69, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "
" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA04AAAIjCAYAAAA0vUuxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABoX0lEQVR4nO3dd3hUZf7+8XvSe+8QCJAQelcgSFFQEASxIosi9lVc5aduYXd1Latg/VrWvivo7iJ2bCgLSBWU3iF0QkklvSeT8/sjZGQEJgkkOZPk/bquuWTOOXPmM5Oj5uZ5ns+xGIZhCAAAAABwTi5mFwAAAAAAzo7gBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANSC4AQAAAAAtSA4AQAAAEAtCE4AAAAAUAuCEwAAAADUguAEAGgQhw8flsVi0dy5c80updlavny5LBaLli9fbnYpAIBfITgBQCs0YcIE+fj4qKCg4JzHTJkyRR4eHjp58uR5v8/ChQv1+OOPn/frW4Jp06bJYrHU+pg2bZrZpQIAHHAzuwAAQNObMmWKvv76a33xxReaOnXqGfuLi4v15ZdfasyYMQoNDT3v91m4cKFef/31Vh2e7rnnHo0aNcr2/NChQ3rsscd09913a+jQobbtnTp10sCBA1VSUiIPDw8zSgUAOEBwAoBWaMKECfL399e8efPOGpy+/PJLFRUVacqUKSZU17IMHjxYgwcPtj3fsGGDHnvsMQ0ePFg333zzGcd7eXk1ZXkAgDpiqh4AtELe3t669tprtXTpUmVkZJyxf968efL399eECRMkSQcPHtQNN9ygkJAQ+fj4aNCgQfr2228dvse0adP0+uuvS5LdlLQaL7zwgpKSkhQaGipvb2/1799fn3766RnnKSkp0QMPPKCwsDBbTcePH5fFYjljJOv48eO6/fbbFRkZKU9PT3Xv3l3vvfderd9Hjx49dOmll56xvaqqSm3atNH1119v2zZ//nz1799f/v7+CggIUM+ePfXKK6/U+h51cbY1TiNGjFCPHj20bds2DR8+XD4+PoqPj7d9VytWrNDAgQPl7e2txMRELVmy5Izznu/3AgD4BcEJAFqpKVOmqLKyUh9//LHd9uzsbC1atEjXXHONvL29lZ6erqSkJC1atEj33Xefnn76aZWWlmrChAn64osvznn+e+65R5dffrkk6d///rftUeOVV15R37599eSTT+qZZ56Rm5ubbrjhhjMC2bRp0/Taa69p7NixevbZZ+Xt7a1x48ad8X7p6ekaNGiQlixZovvvv1+vvPKK4uPjdccdd+jll192+F1MmjRJK1euVFpamt321atX68SJE7rpppskSYsXL9bkyZMVHBysZ599VrNnz9aIESP0448/Ojz/hcrJydFVV12lgQMH6rnnnpOnp6duuukmffTRR7rppps0duxYzZ49W0VFRbr++uvt1q5dyPcCADiNAQBolSorK43o6Ghj8ODBdtvfeustQ5KxaNEiwzAMY8aMGYYkY9WqVbZjCgoKjA4dOhhxcXGG1Wo1DMMwDh06ZEgy5syZYztu+vTpxrn+V1NcXGz3vLy83OjRo4dx2WWX2bZt3LjRkGTMmDHD7thp06YZkoy//e1vtm133HGHER0dbWRlZdkde9NNNxmBgYFnvN/pkpOTDUnGa6+9Zrf9vvvuM/z8/GyvffDBB42AgACjsrLynOeqzfr168/4nmosW7bMkGQsW7bMtm348OGGJGPevHm2bXv27DEkGS4uLsZPP/1k275o0aIzzn0h3wsA4BeMOAFAK+Xq6qqbbrpJa9eu1eHDh23b582bp8jISI0cOVJSdYOHiy++WJdccontGD8/P9199906fPiwdu3adV7v7+3tbftzTk6O8vLyNHToUG3atMm2/fvvv5ck3XfffXav/d3vfmf33DAMffbZZxo/frwMw1BWVpbtMXr0aOXl5dmd99c6d+6sPn366KOPPrJts1qt+vTTTzV+/HhbrUFBQSoqKtLixYvP6zOfLz8/P9uolyQlJiYqKChIXbt21cCBA23ba/588OBBSRf+vQAAfkFwAoBWrKb5w7x58yRJx44d06pVq3TTTTfJ1dVVknTkyBElJiae8dquXbva9p+Pb775RoMGDZKXl5dCQkIUHh6uN998U3l5ebZjjhw5IhcXF3Xo0MHutfHx8XbPMzMzlZubq3feeUfh4eF2j9tuu02SzrqW63STJk3Sjz/+qOPHj0uqXm+UkZGhSZMm2Y6577771LlzZ1155ZVq27atbr/9dlu4a0xt27a1Wx8mSYGBgYqNjT1jm1QdRKWG+V4AANXoqgcArVj//v3VpUsXffjhh/rzn/+sDz/8UIZhNHo3vVWrVmnChAkaNmyY3njjDUVHR8vd3V1z5syxhbj6qKqqkiTdfPPNuvXWW896TK9evRyeY9KkSZo5c6Y++eQTzZgxQx9//LECAwM1ZswY2zERERHasmWLFi1apO+++07fffed5syZo6lTp+r999+vd911VRNi67rdMAxJDfO9AACqEZwAoJWbMmWKHn30UW3btk3z5s1TQkKCLrroItv+9u3bKzk5+YzX7dmzx7b/XH49SlLjs88+k5eXlxYtWiRPT0/b9jlz5tgd1759e1VVVenQoUNKSEiwbd+/f7/dceHh4fL395fVarW7Z1J9dOjQQRdffLE++ugj3X///fr88881ceJEu/okycPDQ+PHj9f48eNVVVWl++67T2+//bYeffTRM0bCzNYQ3wsAoBpT9QCglasZXXrssce0ZcuWM0abxo4dq3Xr1mnt2rW2bUVFRXrnnXcUFxenbt26nfPcvr6+kqTc3Fy77a6urrJYLLJarbZthw8f1oIFC+yOGz16tCTpjTfesNv+2muvnXG+6667Tp999pl27NhxRh2ZmZnnrPF0kyZN0k8//aT33ntPWVlZdtP0JOnkyZN2z11cXGwjNmVlZXV6j6bUUN8LAIARJwBo9Tp06KCkpCR9+eWXknRGcPrTn/6kDz/8UFdeeaUeeOABhYSE6P3339ehQ4f02WefycXl3H8H179/f0nSAw88oNGjR9saUowbN04vvfSSxowZo9/85jfKyMjQ66+/rvj4eG3bts3u9dddd51efvllnTx5UoMGDdKKFSu0d+9eSfYjWrNnz9ayZcs0cOBA3XXXXerWrZuys7O1adMmLVmyRNnZ2bV+FzfeeKMeeeQRPfLIIwoJCTljlObOO+9Udna2LrvsMrVt21ZHjhzRa6+9pj59+tjWfDmbhvheAACMOAEA9EtYuvjii8+YbhYZGak1a9bo8ssv12uvvaaZM2fKw8NDX3/9ta655hqH57322mv1u9/9Tt9//71uueUWTZ48WZJ02WWX6V//+pfS0tI0Y8YMffjhh3r22WfPer4PPvhA06dP17fffqs//vGPKi8vt3W/8/Lysqtz3bp1uu222/T555/b7lmUnZ2tZ599tk7fQ9u2bZWUlKSCggJde+21cnd3t9t/8803y8vLS2+88Ybuu+8+vf/++5o0aZK+++47hwHSTA3xvQAAJItRs4IUAIBmYsuWLerbt6/+85//NHojCwAAJEacAABOrqSk5IxtL7/8slxcXDRs2DATKgIAtEascQIAOLXnnntOGzdu1KWXXio3NzdbG/C77777jPsYAQDQWJiqBwBwaosXL9YTTzyhXbt2qbCwUO3atdMtt9yiv/zlL3Jz4+//AABNg+AEAAAAALVgjRMAAAAA1ILgBAAAAAC1aHWTw6uqqnTixAn5+/vb3TgRAAAAQOtiGIYKCgoUExNT6/34Wl1wOnHiBF2YAAAAANgcPXpUbdu2dXhMqwtO/v7+kqq/nICAAJOrAQAAAGCW/Px8xcbG2jKCI60uONVMzwsICCA4AQAAAKjTEh6aQwAAAABALQhOAAAAAFALghMAAAAA1KLVrXECAACAOQzDUGVlpaxWq9mloJVwdXWVm5tbg9yGiOAEAACARldeXq7U1FQVFxebXQpaGR8fH0VHR8vDw+OCzkNwAgAAQKOqqqrSoUOH5OrqqpiYGHl4eDTICADgiGEYKi8vV2Zmpg4dOqSEhIRab3LrCMEJAAAAjaq8vFxVVVWKjY2Vj4+P2eWgFfH29pa7u7uOHDmi8vJyeXl5nfe5aA4BAACAJnEhf9sPnK+Guu64egEAAACgFgQnAAAAAKgFwQkAAABoJHFxcXr55ZfNLsMpLF++XBaLRbm5uWaXcl4ITgAAAMCvjB8/XmPGjDnrvlWrVslisWjbtm31Pq/FYtGCBQsusDrnM23aNFkslnM+4uLilJSUpNTUVAUGBppd7nkhOAEAAAC/cscdd2jx4sU6duzYGfvmzJmjAQMGqFevXiZU5pxeeeUVpaam2h5S9fdU83z9+vXy8PBQVFRUs21FT3ACAABAkzIMQ8XllaY8DMOoU41XXXWVwsPDNXfuXLvthYWF+uSTT3THHXdIkj777DN1795dnp6eiouL04svvnjOc8bFxUmSrrnmGtsojCQdOHBAV199tSIjI+Xn56eLLrpIS5YssXttamqqxo0bJ29vb3Xo0EHz5s07Yxpgbm6u7rzzToWHhysgIECXXXaZtm7des56kpKS9Mc//tFuW2Zmptzd3bVy5UpJ0htvvKGEhAR5eXkpMjJS119//VnPFRgYqKioKNtDkoKCgmzPw8PDz5iqN3fuXAUFBembb75RYmKifHx8dP3116u4uFjvv/++4uLiFBwcrAceeEBWq9X2XmVlZXrkkUfUpk0b+fr6auDAgVq+fPk5P2dD4T5OAAAAaFIlFVZ1e2yRKe+968nR8vGo/VdgNzc3TZ06VXPnztVf/vIX2yjJJ598IqvVqsmTJ2vjxo268cYb9fjjj2vSpElas2aN7rvvPoWGhmratGlnnHP9+vWKiIjQnDlzNGbMGLm6ukqqDmNjx47V008/LU9PT33wwQcaP368kpOT1a5dO0nS1KlTlZWVpeXLl8vd3V0PPfSQMjIy7M5/ww03yNvbW999950CAwP19ttva+TIkdq7d69CQkLOqGfKlCl67rnnNHv2bNvn++ijjxQTE6OhQ4dqw4YNeuCBB/Tvf/9bSUlJys7O1qpVq+r1fdemuLhYr776qubPn6+CggJde+21uuaaaxQUFKSFCxfq4MGDuu666zRkyBBNmjRJknT//fdr165dmj9/vmJiYvTFF19ozJgx2r59uxISEhq0vtMRnAAAAICzuP322/X8889rxYoVGjFihKTq6WfXXXedAgMD9dJLL2nkyJF69NFHJUmdO3fWrl279Pzzz581OIWHh0v6ZSSmRu/evdW7d2/b86eeekpffPGFvvrqK91///3as2ePlixZovXr12vAgAGSpH/+8592IWH16tVat26dMjIy5OnpKUl64YUXtGDBAn366ae6++67z6jnxhtv1IwZM7R69WoNHTpUkjRv3jxNnjxZFotFKSkp8vX11VVXXSV/f3+1b99effv2vYBv9EwVFRV688031alTJ0nS9ddfr3//+99KT0+Xn5+funXrpksvvVTLli3TpEmTlJKSojlz5iglJUUxMTGSpEceeUTff/+95syZo2eeeaZB6zsdwclEm1NylJZXqm4xAWof6mt2OQAAAE3C291Vu54cbdp711WXLl2UlJSk9957TyNGjND+/fu1atUqPfnkk5Kk3bt36+qrr7Z7zZAhQ/Tyyy/LarXaRpRqU1hYqMcff1zffvutUlNTVVlZqZKSEqWkpEiSkpOT5ebmpn79+tleEx8fr+DgYNvzrVu3qrCwUKGhoXbnLikp0YEDB876vuHh4briiiv03//+V0OHDtWhQ4e0du1avf3225Kkyy+/XO3bt1fHjh01ZswYjRkzRtdcc418fHzq9LnqwsfHxxaaJCkyMlJxcXHy8/Oz21YzurZ9+3ZZrVZ17tzZ7jxlZWVnfPaGRnAy0burDmrh9jQ9eXV3TR1McAIAAK2DxWKp03Q5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7LPPdM899yg3N1dWq7WhamsU+fn5CgwMVF5engICAswuBwAAtGKpeSWa8u7POphVpDZB3vr4t4PVJsjb7LKAVqM+2eCCuuotX75c06ZN07Rp02S1WnXXXXddyOkAAABalehAb310z2B1DPfV8dwSTXn3J2Ww5glwSvUOTseOHdPf//53xcfH67LLLtPhw4f1xhtvKDU1VW+99VZj1AgAANBihft76r93DlTbYG8dPlmsm//1s7KLys0uC8Cv1Dk4ffzxxxozZow6dOigN998UzfeeKP27t2rFStWaOrUqfL2ZlgZAADgfEQHemvenYMUFeClvemFmvrezyrkPk+AU6lzcLr55pvl7e2tL774QkePHtUzzzyj+Pj4xqwNAACg1WgX6qP/3DlQob4e2nE8X/f+Z6MqrFVmlwXglDo3h8jIyFBERERj19PoaA4BAACc2bZjuZr09k8qqbDqun5t9cINvWSxWMwuC2iRGqU5REsITQAAAM6uV9sgvTGln1xdLPps0zG9tHiv2SUB0AV21QMAAEDDu7RLhJ65pock6bUf9uu/Px8xuSIABCcAAAAnNOmidnpwZIIk6dEFO7R0d7rJFQGtW52D08GDBxuzDgAAAPzKjFEJunFAW1UZ0v3zNmvL0VyzSwJarToHp169eqlHjx7685//rJ9//rkxawIAAIAki8Wip6/pqeGdw1VSYdXtc9frcFaR2WUBrVKdg1NWVpZmzZqljIwMXX311YqOjtZdd92lr7/+WqWl3OEaAACgMbi7uuiNKf3Us02gsovKdeucdTpZWGZ2WUCrU+d25KczDENr167VV199pa+++kopKSkaNWqUJkyYoPHjxys8PLwxam0QtCMHAADNUWZBma5980cdzS5R33ZB+vCuQfJydzW7LKBZa5R25KezWCxKSkrS7NmztWvXLm3evFlDhw7V3Llz1bZtW73++uvnVTgAAADOLtzfU3Nvu1iB3u7anJKrB+dvlrWq3n//DeA8ndeIkyMnT55Udna2EhISGvK0DYYRJwAA0JytO5Stm//5s8qtVbp9SAc9Nr6b2SUBzVajjzg5Ehoa6rShCQAAoLm7uEOIXryxtyTpvR8P6b3Vh0yuCGgduI8TAABAMzO+d4z+dGUXSdJT3+7S9zvSTK4IaPkITgAAAM3QPcM66uZB7WQY0oPzN2tTSo7ZJQEtGsEJ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zkuj3scpNTVVSUlJZ2xPSkqyGx0CAABAyxTq56nfXFw96vTmsgMmVwM0jXoHp/j4eH388cdnbP/oo4+UkJDQIEUBAADAud05tKM8XF207nC21h/ONrscoNHVqR356Z544glNmjRJK1eu1JAhQyRJP/74o5YuXXrWQAUAAICWJyrQS9f1b6MP1x3VG8v2a85tF5tdEtCo6jzitGPHDknSddddp59//llhYWFasGCBFixYoLCwMK1bt07XXHNNoxUKAAAA53LPsE5ysUjLkjO180Se2eUAjarOzSFcXFx00UUX6c4779RNN90kf//mecMzmkMAAAA0nN99uFlfbz2hq3pF6x+/6Wd2OUC9NEpziBUrVqh79+56+OGHFR0drWnTpmnVqlUXXCwAAACar3uHd5IkLdyeqkNZRSZXAzSeOgenoUOH6r333lNqaqpee+01HTp0SMOHD1fnzp317LPPKi0trTHrBAAAgBPqFhOgSxPDVWVIH6w9bHY5QKOpd1c9X19f3XbbbVqxYoX27t2rG264Qa+//rratWunCRMmNEaNAAAAcGK3JsVJkj7beEylFVZziwEaSb2D0+ni4+P15z//WX/961/l7++vb7/9tqHqAgAAQDMxLCFcbYK8lV9aqW+3cV9PtEznHZxWrlypadOmKSoqSr///e917bXX6scff2zI2gAAANAMuLhYNPniWEnSh+tSTK4GaBz1Ck4nTpzQM888o86dO2vEiBHav3+/Xn31VZ04cULvvvuuBg0a1Fh1AgAAwIndOCBWri4WbTiSo73pBWaXAzS4OgenK6+8Uu3bt9drr72ma665Rrt379bq1at12223ydfXtzFrBAAAgJOLCPDSqK4RkqR5PzPqhJanzsHJ3d1dn376qY4dO6Znn31WiYmJjVkXAAAAmpnfDGwvSfp8E00i0PK41fXAr776qjHrAAAAQDM3ND5MbYO9dSynRN9uS9V1/duaXRLQYC6oqx4AAABQo7pJRDtJ0jyaRKCFITgBAACgwdzQv61cLNLGIzk6ml1sdjlAgyE4AQAAoMFEBHhpYIdQSdLC7dzTCS0HwQkAAAANalyvaEkEJ7QsBCcAAAA0qDE9ouRikbYey2O6HloMghMAAAAaVJifpwZ1rJ6u9y2jTmghCE4AAABocDXT9b7dRnBCy0BwAgAAQIMb0716ut7243k6crLI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BAUF2XXUQvNw7733GoGBgcby5cuN1NRU26O4uNh2zG9/+1ujXbt2xg8//GBs2LDBGDx4sDF48GDb/ppW1FdccYWxZcsW4/vvvzfCw8PP2or697//vbF7927j9ddfpxW1Ezu9q55hcA20dOvWrTPc3NyMp59+2ti3b5/x3//+1/Dx8TH+85//2I6ZPXu2ERQUZHz55ZfGtm3bjKuvvvqsbYn79u1r/Pzzz8bq1auNhIQEu7bEubm5RmRkpHHLLbcYO3bsMObPn2/4+PjQhtpJ3HrrrUabNm1s7cg///xzIywszPjDH/5gO4broGUpKCgwNm/ebGzevNmQZLz00kvG5s2bjSNHjhiG0XQ/7x9//NFwc3MzXnjhBWP37t3G3/72N9qRNwKCk4lee+01o127doaHh4dx8cUXGz/99JPZJeE8SDrrY86cObZjSkpKjPvuu88IDg42fHx8jGuuucZITU21O8/hw4eNK6+80vD29jbCwsKMhx9+2KioqLA7ZtmyZUafPn0MDw8Po2PHjnbvAefy6+DENdDyff3110aPHj0MT09Po0uXLsY777xjt7+qqsp49NFHjcjISMPT09MYOXKkkZycbHfMyZMnjcmTJxt+fn5GQECAcdtttxkFBQV2x2zdutW45JJLDE9PT6NNmzbG7NmzG/2zoW7y8/ONBx980GjXrp3h5eVldOzY0fjLX/5i10aa66BlWbZs2Vl/B7j11lsNw2jan/fHH39sdO7c2fDw8DC6d+9ufPvtt432uVsri2GcdjtrAAAAAMAZWOMEAAAAALUgOAEAAABALQhOAAAAAFALghMAAAAA1ILgBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANSC4AQAaFamTZumiRMnml0GAKCVcTO7AAAAalgsFof7//a3v+mVV16RYRhNVNGZVqxYoZtvvllHjx41rQYAQNMjOAEAnEZqaqrtzx999JEee+wxJScn27b5+fnJz8/PjNJsvvzyS40fP97UGgAATY+pegAApxEVFWV7BAYGymKx2G3z8/M7Y6reiBEj9Lvf/U4zZsxQcHCwIiMj9e6776qoqEi33Xab/P39FR8fr++++87uvXbs2KErr7xSfn5+ioyM1C233KKsrKxaa/zqq680YcKEs+47cuSIxo8fr+DgYPn6+qp79+5auHDhBX0nAADnQHACADR777//vsLCwrRu3Tr97ne/07333qsbbrhBSUlJ2rRpk6644grdcsstKi4uliTl5ubqsssuU9++fbVhwwZ9//33Sk9P14033ujwfXbu3KmMjAxddtllZ90/ffp0lZWVaeXKldq+fbueffZZ00fIAAANg6l6AIBmr3fv3vrrX/8qSZo5c6Zmz56tsLAw3XXXXZKkxx57TG+++aa2bdumQYMG6R//+If69u2rZ555xnaO9957T7Gxsdq7d686d+581vf58ssvNXr0aHl4eJx1f0pKiq677jr17NlTktSxY8eG/JgAABMx4gQAaPZ69epl+7Orq6tCQ0Nt4UWSIiMjJUkZGRmSpK1bt2rZsmW2NVN+fn7q0qWLJOnAgQPnfJ8vv/zynNP0JOmBBx7Q3//+dw0ZMkR/+9vftG3btgv6XAAA50FwAgA0e+7u7nbPLRaL3baabn1VVVWSpMLCQo0fP15btmyxe+zbt0/Dhg0763ukpqZq8+bNGjdu3DnruPPOO3Xw4EHdcsst2r59uwYMGKDXXnvtQj8eAMAJEJwAAK1Ov379tHPnTsXFxSk+Pt7u4evre9bXfP3110pKSlJISIjDc8fGxuq3v/2tPv/8cz388MN69913G+MjAACaGMEJANDqTJ8+XdnZ2Zo8ebLWr1+vAwcOaNGiRbrttttktVrP+hpH3fRqzJgxQ4sWLdKhQ4e0adMmLVu2TF27dm2MjwAAaGIEJwBAqxMTE6Mff/xRVqtVV1xxhXr27KkZM2YoKChILi5n/q+xqKhIS5curTU4Wa1WTZ8+XV27dtWYMWPUuXNnvfHGG431MQAATchimHn7dQAAmoHPP/9cf/3rX7Vr1y6zSwEAmIQRJwAAauHn56dnn33W7DIAACZixAkAAAAAasGIEwAAAADUguAEAAAAALUgOAEAAABALQhOAAAAAFALghMAAAAA1ILgBAAAAAC1IDgBAAAAQC0ITgAAAABQC4ITAAAAANTi/wMPiSjEF+6LlQAAAABJRU5ErkJggg==\n" - }, - "metadata": {} - } ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/sphinx/example_linked_data_zinc_powder.ipynb b/sphinx/example_linked_data_zinc_powder.ipynb index 9b8fe83..356b650 100644 --- a/sphinx/example_linked_data_zinc_powder.ipynb +++ b/sphinx/example_linked_data_zinc_powder.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "1wseTQGaB4x9" + }, "source": [ "# Example: Zinc Powder from a Supplier\n", "\n", @@ -30,23 +19,25 @@ "- How to use the ontology to fetch more information from other sources **[Advanced]** \n", "\n", "A live version of this notebook is available on Google Colab [here](https://colab.research.google.com/drive/19PxdZDPcKda8Ji6Nyzsz-_8KJFgNkmCa?usp=sharing)\n" - ], - "metadata": { - "id": "1wseTQGaB4x9" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "jcTVz9-DEh3m" + }, "source": [ "## Describe the powder using ontology terms in JSON-LD format\n", "The JSON-LD data that we will use is:" - ], - "metadata": { - "id": "jcTVz9-DEh3m" - } + ] }, { "cell_type": "code", + "execution_count": 104, + "metadata": { + "id": "gohQKEBrF2QP" + }, + "outputs": [], "source": [ "jsonld = {\n", " \"@context\": \"https://raw.githubusercontent.com/emmo-repo/domain-electrochemistry/master/context.json\",\n", @@ -69,77 +60,63 @@ " }\n", " ]\n", "}" - ], - "metadata": { - "id": "gohQKEBrF2QP" - }, - "execution_count": 104, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "in30p-x4H91Y" + }, "source": [ "## Parse this description into a graph\n", "Now let's see how a machine would process this data by reading it into a Graph!\n", "\n", - "First, we install and import the python dependencies that we need for this example." - ], + "First, we install and import the python dependencies that we need for this example.\n", + "\n", + "Note, the `pip install` statement is to be run in a shell/terminal." + ] + }, + { + "cell_type": "code", + "execution_count": null, "metadata": { - "id": "in30p-x4H91Y" - } + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "# Install dependencies\n", + "pip install jsonschema rdflib requests matplotlib > /dev/null" + ] }, { "cell_type": "code", + "execution_count": 105, + "metadata": { + "id": "wk4sFl_eA2ML" + }, + "outputs": [], "source": [ - "# Install and import dependencies\n", - "!pip install jsonschema rdflib requests matplotlib > /dev/null\n", - "\n", + "# Import dependencies\n", "import json\n", "import rdflib\n", "import requests\n", - "import sys\n", - "from IPython.display import Image, display\n", - "import matplotlib.pyplot as plt" - ], - "metadata": { - "id": "wk4sFl_eA2ML" - }, - "execution_count": 105, - "outputs": [] + "from IPython.display import Image, display" + ] }, { "cell_type": "markdown", - "source": [ - "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." - ], "metadata": { "id": "lotp-0QABV-2" - } + }, + "source": [ + "We create the graph using a very handy python package called [rdflib](https://rdflib.readthedocs.io/en/stable/), which provides us a way to parse our json-ld data, run some queries using the language [SPARQL](https://en.wikipedia.org/wiki/SPARQL), and serialize the graph in any RDF compatible format (e.g. JSON-LD, Turtle, etc.)." + ] }, { "cell_type": "code", - "source": [ - "# Create a new graph\n", - "g = rdflib.Graph()\n", - "\n", - "# Parse our json-ld data into the graph\n", - "g.parse(data=json.dumps(jsonld), format=\"json-ld\")\n", - "\n", - "# Create a SPARQL query to return all the triples in the graph\n", - "query_all = \"\"\"\n", - "SELECT ?subject ?predicate ?object\n", - "WHERE {\n", - " ?subject ?predicate ?object\n", - "}\n", - "\"\"\"\n", - "\n", - "# Execute the SPARQL query\n", - "all_the_things = g.query(query_all)\n", - "\n", - "# Print the results\n", - "for row in all_the_things:\n", - " print(row)\n" - ], + "execution_count": 106, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -147,11 +124,10 @@ "id": "zWibLw6NIrrq", "outputId": "2b87d0a0-06b4-4093-f44b-4add7f9651e0" }, - "execution_count": 106, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "(rdflib.term.BNode('Nba3653d5211a479faa84120717afec04'), rdflib.term.URIRef('https://schema.org/manufacturer'), rdflib.term.URIRef('https://www.wikidata.org/wiki/Q680841'))\n", "(rdflib.term.BNode('Nbad48dcf37014f5989126dde499c31e7'), rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), rdflib.term.URIRef('http://emmo.info/emmo#EMMO_d8aa8e1f_b650_416d_88a0_5118de945456'))\n", @@ -169,10 +145,35 @@ "(rdflib.term.BNode('Nba3653d5211a479faa84120717afec04'), rdflib.term.URIRef('http://emmo.info/emmo#EMMO_e1097637_70d2_4895_973f_2396f04fa204'), rdflib.term.BNode('Nbad48dcf37014f5989126dde499c31e7'))\n" ] } + ], + "source": [ + "# Create a new graph\n", + "g = rdflib.Graph()\n", + "\n", + "# Parse our json-ld data into the graph\n", + "g.parse(data=json.dumps(jsonld), format=\"json-ld\")\n", + "\n", + "# Create a SPARQL query to return all the triples in the graph\n", + "query_all = \"\"\"\n", + "SELECT ?subject ?predicate ?object\n", + "WHERE {\n", + " ?subject ?predicate ?object\n", + "}\n", + "\"\"\"\n", + "\n", + "# Execute the SPARQL query\n", + "all_the_things = g.query(query_all)\n", + "\n", + "# Print the results\n", + "for row in all_the_things:\n", + " print(row)\n" ] }, { "cell_type": "markdown", + "metadata": { + "id": "C-w1TbxkI4W5" + }, "source": [ "You can see that our human-readable JSON-LD file has been transformed into some nasty looking (but machine-readable!) triples. Let's look at a couple in more detail to understand what's going on.

\n", "\n", @@ -208,13 +209,27 @@ "## Query the graph using SPARQL [Moderate]\n", "\n", "Now, let's write a SPARQL query to get back some specific thing...like what is the name of the manufacturer?" - ], - "metadata": { - "id": "C-w1TbxkI4W5" - } + ] }, { "cell_type": "code", + "execution_count": 107, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6bXHGG4cI-kr", + "outputId": "c1a5fef2-f4bc-4e63-dc87-617f6bb9cecd" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(rdflib.term.Literal('Sigma-Aldrich'),)\n" + ] + } + ], "source": [ "query = \"\"\"\n", "PREFIX schema: \n", @@ -232,39 +247,39 @@ "# Print the results\n", "for row in results:\n", " print(row)\n" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "6bXHGG4cI-kr", - "outputId": "c1a5fef2-f4bc-4e63-dc87-617f6bb9cecd" - }, - "execution_count": 107, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "(rdflib.term.Literal('Sigma-Aldrich'),)\n" - ] - } ] }, { "cell_type": "markdown", + "metadata": { + "id": "b7LJC8BubFce" + }, "source": [ "## Fetch additional information from other sources [Advanced]\n", "Ontologies contain a lot of information about the meaning of things, but they don't always contain an exhaustive list of all the properties. Instead, they often point to other sources where that information exists rather than duplicating it. Let's see how you can use the ontology to fetch additional information from other sources.\n", "\n", "First, we parse the ontology into the knowledge graph and retrieve the IRIs for the terms that we are interested in. In this case, we want to retrieve more information about Zinc from Wikidata, so we query the ontology to find Zinc's Wikidata ID." - ], - "metadata": { - "id": "b7LJC8BubFce" - } + ] }, { "cell_type": "code", + "execution_count": 108, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ntT1Rf_yM6sZ", + "outputId": "dbd2e4a6-6a4e-4e85-f221-ee240e79c9af" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Wikidata ID of Zinc: Q758\n" + ] + } + ], "source": [ "# Parse the ontology into the knowledge graph\n", "ontology = \"https://raw.githubusercontent.com/emmo-repo/domain-electrochemistry/master/electrochemistry-inferred.ttl\"\n", @@ -292,36 +307,36 @@ " wikidata_id = row.wikidataId.split('/')[-1]\n", "\n", "print(f\"The Wikidata ID of Zinc: {wikidata_id}\")" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XGXFrNa5dKSr" + }, + "source": [ + "Now that we have the Wikidata ID for Zinc, we can query their SPARQL endpoint to retrieve some property. Let's ask it for the atomic mass." + ] + }, + { + "cell_type": "code", + "execution_count": 109, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, - "id": "ntT1Rf_yM6sZ", - "outputId": "dbd2e4a6-6a4e-4e85-f221-ee240e79c9af" + "id": "zTBOZAf-dWQQ", + "outputId": "e894b2c6-e2fc-4564-b77f-3e623afeecdb" }, - "execution_count": 108, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ - "The Wikidata ID of Zinc: Q758\n" + "Wikidata says the atomic mass of zinc is: 65.38\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "Now that we have the Wikidata ID for Zinc, we can query their SPARQL endpoint to retrieve some property. Let's ask it for the atomic mass." ], - "metadata": { - "id": "XGXFrNa5dKSr" - } - }, - { - "cell_type": "code", "source": [ "# Query the Wikidata knowledge graph for more information about zinc\n", "wikidata_endpoint = \"https://query.wikidata.org/sparql\"\n", @@ -340,57 +355,20 @@ "# Extract and print the mass value\n", "mass = data['results']['bindings'][0]['mass']['value']\n", "print(f\"Wikidata says the atomic mass of zinc is: {mass}\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "zTBOZAf-dWQQ", - "outputId": "e894b2c6-e2fc-4564-b77f-3e623afeecdb" - }, - "execution_count": 109, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Wikidata says the atomic mass of zinc is: 65.38\n" - ] - } ] }, { "cell_type": "markdown", - "source": [ - "We can also retrieve more complex data. For example, let's ask Wikidata to show us an image of zinc." - ], "metadata": { "id": "-xdSIS6Idy5m" - } + }, + "source": [ + "We can also retrieve more complex data. For example, let's ask Wikidata to show us an image of zinc." + ] }, { "cell_type": "code", - "source": [ - "# SPARQL query to get the image of zinc (Q758)\n", - "query = \"\"\"\n", - "SELECT ?image WHERE {\n", - " wd:%s wdt:P18 ?image .\n", - "}\n", - "\"\"\" % wikidata_id\n", - "\n", - "# Execute the request\n", - "response = requests.get(wikidata_endpoint, params={'query': query, 'format': 'json'})\n", - "data = response.json()\n", - "\n", - "# Extract and display the image URL\n", - "if data['results']['bindings']:\n", - " image_url = data['results']['bindings'][0]['image']['value']\n", - " print(f\"Image of Zinc: {image_url}\")\n", - " display(Image(url=image_url, width=300)) # Adjust width and height as needed\n", - "\n", - "else:\n", - " print(\"No image found for Zinc.\")" - ], + "execution_count": 110, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -399,17 +377,15 @@ "id": "T7bkBY0sNqNY", "outputId": "a5cad6b9-84be-43b2-9411-569f938a09fc" }, - "execution_count": 110, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Image of Zinc: http://commons.wikimedia.org/wiki/Special:FilePath/Zinc%20fragment%20sublimed%20and%201cm3%20cube.jpg\n" ] }, { - "output_type": "display_data", "data": { "text/html": [ "" @@ -418,18 +394,54 @@ "" ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "# SPARQL query to get the image of zinc (Q758)\n", + "query = \"\"\"\n", + "SELECT ?image WHERE {\n", + " wd:%s wdt:P18 ?image .\n", + "}\n", + "\"\"\" % wikidata_id\n", + "\n", + "# Execute the request\n", + "response = requests.get(wikidata_endpoint, params={'query': query, 'format': 'json'})\n", + "data = response.json()\n", + "\n", + "# Extract and display the image URL\n", + "if data['results']['bindings']:\n", + " image_url = data['results']['bindings'][0]['image']['value']\n", + " print(f\"Image of Zinc: {image_url}\")\n", + " display(Image(url=image_url, width=300)) # Adjust width and height as needed\n", + "\n", + "else:\n", + " print(\"No image found for Zinc.\")" ] }, { "cell_type": "code", - "source": [], + "execution_count": 110, "metadata": { "id": "T1qUAeCDVNq3" }, - "execution_count": 110, - "outputs": [] + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/sphinx/example_person_jsonld_nb.ipynb b/sphinx/example_person_jsonld_nb.ipynb index 75a7cb3..8c2fed3 100644 --- a/sphinx/example_person_jsonld_nb.ipynb +++ b/sphinx/example_person_jsonld_nb.ipynb @@ -10,7 +10,9 @@ "\n", "In this notebook, we will explore the principles of JSON-LD using the example of a person. JSON-LD stands for \"JSON for Linking Data\" and it provides a method to enrich your JSON data with semantics.\n", "\n", - "An operational version of this notebook can be accessed [here](https://colab.research.google.com/drive/14XqRJPWs07RUQgZmDZEu3yb2m1xGvxEQ?usp=sharing)." + "An operational version of this notebook can be accessed [here](https://colab.research.google.com/drive/14XqRJPWs07RUQgZmDZEu3yb2m1xGvxEQ?usp=sharing).\n", + "\n", + "Note, the `pip install` statements are to be run in a shell/terminal." ] }, { @@ -21,7 +23,10 @@ "base_uri": "https://localhost:8080/" }, "id": "y-aalpcNb223", - "outputId": "565a219c-1d10-4b55-fd75-a1fcb2257022" + "outputId": "565a219c-1d10-4b55-fd75-a1fcb2257022", + "vscode": { + "languageId": "shellscript" + } }, "outputs": [ { @@ -48,8 +53,8 @@ ], "source": [ "# Install the required library for JSON schema validation\n", - "!pip install jsonschema\n", - "!pip install rdflib" + "pip install jsonschema\n", + "pip install rdflib" ] }, { diff --git a/sphinx/examples.rst b/sphinx/examples.rst index 8e214f1..14eaf4c 100644 --- a/sphinx/examples.rst +++ b/sphinx/examples.rst @@ -1,10 +1,19 @@ .. toctree:: :hidden: - example_linked_data_battery_cell_metadata.ipynb - example_linked_data_custom_battery_cell_metadata.ipynb - example_linked_data_timeseries_battery_data.ipynb - example_linked_data_zinc_powder.ipynb + example_linked_data_battery_cell_metadata + example_linked_data_custom_battery_cell_metadata + example_linked_data_timeseries_battery_data + example_linked_data_zinc_powder + example_aqueous_electrolyte_KOH + example_alkaline_electrochemical_cell + example_cyclic_voltammetry + example_eis_nyquist + + example_zinc_electrode + example_zinc_powder + + example_person_jsonld_nb Examples ======== diff --git a/sphinx/img/protege_config_contribute.png b/sphinx/img/protege_config_contribute.png new file mode 100644 index 0000000000000000000000000000000000000000..3b58a25dfa2aeefc7c184a20782a56edf140b7d5 GIT binary patch literal 17789 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 FAQ + Contribute + tools + resources + Battery Interface Ontology ================================