{ "cells": [ { "cell_type": "markdown", "id": "91fb9928", "metadata": {}, "source": [ "# ★★★★ Four-Star Battery Data\n", "\n", "In this notebook, you will learn how to describe a structured battery dataset using **ontology-annotated metadata**, corresponding to **four stars** in the Five-Star Battery Data framework.\n", "\n", "The goal of star four is to provide **explicit metadata** that describes:\n", "- The battery or material under test\n", "- The test procedure that was carried out\n", "- The meaning and units of data columns\n", "- The dataset itself (e.g. title, creator, license)\n", "\n", "We do this using **controlled vocabularies** and **semantic formats** like JSON-LD.\n", "\n", "## Watch\n", "\n", "
\n", " \n", "
\n", "\n", "---\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "36908a14", "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import json" ] }, { "cell_type": "markdown", "id": "43c54f10", "metadata": {}, "source": [ "## Step-by-Step Metadata Construction\n", "\n", "To make the process of creating ontology-annotated metadata more understandable, this notebook builds the JSON-LD metadata **incrementally**, reflecting how real-world metadata often evolves—from minimal structure to rich semantic context.\n", "\n", "---\n", "\n", "### Step 1: Start with a Skeleton\n", "\n", "We begin by creating a minimal JSON-LD structure with the `@context` and top-level type (`BatteryTest`). This gives us a valid but very basic semantic container for describing the battery test.\n", "\n", "At this point, both `hasTestObject` and `hasOutput` are empty placeholders—we’ll fill them in step-by-step.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "e5c5341f", "metadata": {}, "outputs": [], "source": [ "metadata = {\n", " \"@context\": \"https://w3id.org/emmo/domain/battery/context\",\n", " \"@graph\": [\n", " {\n", " \"@type\": \"BatteryTest\",\n", " \"hasTestObject\": {},\n", " \"hasOutput\": {}\n", " }\n", " ]\n", "}" ] }, { "cell_type": "markdown", "id": "9e177fd8", "metadata": {}, "source": [ "---\n", "\n", "### Step 2: Add Battery Cell Description\n", "\n", "We add a basic description of the test object—a `LithiumIonPolymerBattery`—by defining:\n", "- The positive electrode with `LithiumCobaltOxide`\n", "- The negative electrode with `Graphite`\n", "- The electrolyte as a `PolymerElectrolyte`\n", "\n", "This establishes the core battery structure, using terms from the domain battery ontology.\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "95253ea9", "metadata": {}, "outputs": [], "source": [ "metadata = {\n", " \"@context\": \"https://w3id.org/emmo/domain/battery/context\",\n", " \"@graph\": [\n", " {\n", " \"@type\": \"BatteryTest\",\n", " \"hasTestObject\": {\n", " \"@type\": \"LithiumIonPolymerBattery\",\n", " \"hasPositiveElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"LithiumCobaltOxide\"\n", " }\n", " },\n", " \"hasNegativeElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"Graphite\"\n", " }\n", " },\n", " \"hasElectrolyte\": {\n", " \"@type\": \"PolymerElectrolyte\"\n", " }\n", " },\n", " \"hasOutput\": {}\n", " }\n", " ]\n", "}" ] }, { "cell_type": "markdown", "id": "e0739d2f", "metadata": {}, "source": [ "---\n", "\n", "### Step 3: Add Key Properties\n", "\n", "We enrich the battery description by adding measurable properties:\n", "- `NominalCapacity` (e.g. 6500 mAh)\n", "- `NominalVoltage` (e.g. 3.8 V)\n", "\n", "Each property includes a value (`hasNumberValue`) and a formal unit from EMMO (e.g. `emmo:MilliAmpereHour`, `emmo:Volt`). This ensures both **semantic clarity** and **machine interpretability**.\n", "\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "f68ec112", "metadata": {}, "outputs": [], "source": [ "metadata = {\n", " \"@context\": \"https://w3id.org/emmo/domain/battery/context\",\n", " \"@graph\": [\n", " {\n", " \"@type\": \"BatteryTest\",\n", " \"hasTestObject\": {\n", " \"@type\": \"LithiumIonPolymerBattery\",\n", " \"hasPositiveElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"LithiumCobaltOxide\"\n", " }\n", " },\n", " \"hasNegativeElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"Graphite\"\n", " }\n", " },\n", " \"hasElectrolyte\": {\n", " \"@type\": \"PolymerElectrolyte\"\n", " },\n", " \"hasProperty\": [\n", " {\n", " \"@type\": \"NominalCapacity\",\n", " \"hasNumericalPart\": {\n", " \"@type\": \"RealData\",\n", " \"hasNumberValue\": 6500\n", " },\n", " \"hasMeasurementUnit\": \"emmo:MilliAmpereHour\"\n", " },\n", " {\n", " \"@type\": \"NominalVoltage\",\n", " \"hasNumericalPart\": {\n", " \"@type\": \"RealData\",\n", " \"hasNumberValue\": 3.8\n", " },\n", " \"hasMeasurementUnit\": \"emmo:Volt\"\n", " }\n", " ]\n", " },\n", " \"hasOutput\": {}\n", " }\n", " ]\n", "}" ] }, { "cell_type": "markdown", "id": "836340fd", "metadata": {}, "source": [ "---\n", "\n", "### Step 4: Add Test Output Description\n", "\n", "We then define the output of the test using:\n", "- `BatteryTestResult` as the output type\n", "- `dcat:Dataset` to allow integration with data catalogs\n", "- A `dcat:Distribution` block specifying:\n", " - The media type (`application/vnd.apache.parquet`)\n", " - The file URL on Zenodo\n", " - A link to the `csvw:tableSchema` that defines column-level meaning\n", "\n", "This step connects the metadata to the actual test data, bridging semantics and raw content.\n", "\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "288b31ef", "metadata": {}, "outputs": [], "source": [ "metadata = {\n", " \"@context\": \"https://w3id.org/emmo/domain/battery/context\",\n", " \"@graph\": [\n", " {\n", " \"@type\": \"BatteryTest\",\n", " \"hasTestObject\": {\n", " \"@type\": \"LithiumIonPolymerBattery\",\n", " \"hasPositiveElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"LithiumCobaltOxide\"\n", " }\n", " },\n", " \"hasNegativeElectrode\": {\n", " \"@type\": \"Electrode\",\n", " \"hasActiveMaterial\": {\n", " \"@type\": \"Graphite\"\n", " }\n", " },\n", " \"hasElectrolyte\": {\n", " \"@type\": \"PolymerElectrolyte\"\n", " },\n", " \"hasProperty\": [\n", " {\n", " \"@type\": \"NominalCapacity\",\n", " \"hasNumericalPart\": {\n", " \"@type\": \"RealData\",\n", " \"hasNumberValue\": 6500\n", " },\n", " \"hasMeasurementUnit\": \"emmo:MilliAmpereHour\"\n", " },\n", " {\n", " \"@type\": \"NominalVoltage\",\n", " \"hasNumericalPart\": {\n", " \"@type\": \"RealData\",\n", " \"hasNumberValue\": 3.8\n", " },\n", " \"hasMeasurementUnit\": \"emmo:Volt\"\n", " }\n", " ]\n", " },\n", " \"hasOutput\": {\n", " \"@type\": [\"BatteryTestResult\", \"dcat:Dataset\"],\n", " \"dcat:distribution\": {\n", " \"@type\": \"dcat:Distribution\",\n", " \"dcat:mediaType\": \"application/vnd.apache.parquet\",\n", " \"dcat:downloadURL\": \"https://zenodo.org/records/15127867/files/sintef__melasta-slpba842124hv-2024-10-23-15077312__rate-testing.bdf.parquet\",\n", " \"csvw:tableSchema\": \"https://w3id.org/battery-data-alliance/ontology/battery-data-format/schema\"\n", " }\n", " }\n", " }\n", " ]\n", "}" ] }, { "cell_type": "markdown", "id": "ed1482d5", "metadata": {}, "source": [ "---\n", "\n", "### Step 5: Serialize and Save\n", "\n", "Once the full metadata structure is assembled, we serialize it to a `metadata.jsonld` file, ready for validation and reuse." ] }, { "cell_type": "code", "execution_count": 6, "id": "bad0c06f", "metadata": {}, "outputs": [], "source": [ "# Save to file\n", "with open(\"metadata.jsonld\", \"w\") as f:\n", " json.dump(metadata, f, indent=2)" ] }, { "cell_type": "markdown", "id": "bfe79ae7", "metadata": {}, "source": [ "---\n", "\n", "## Validate Your JSON-LD\n", "\n", "You can copy-paste the contents of `metadata.jsonld` into an online validator like:\n", "- [JSON-LD Playground](https://json-ld.org/playground/)\n", "\n", "Check that your metadata resolves correctly and uses well-formed vocabularies.\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "3125a99b", "metadata": {}, "source": [ "### Why This Matters\n", "\n", "By building up the metadata one layer at a time:\n", "- You maintain clarity about what each part of the structure represents\n", "- You learn how to reuse ontology terms consistently\n", "- You prepare metadata that is valid, discoverable, and linked\n", "\n", "This modular approach helps demystify semantic metadata and prepares your dataset for **4-star battery data**—and sets the stage for the final star: linked data integration.\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "6e8e1841", "metadata": {}, "source": [ "## Summary\n", "\n", "In this notebook, you learned how to satisfy the requirements for **4-star battery data** by creating structured, ontology-annotated metadata in JSON-LD format.\n", "\n", "| Step | What You Did |\n", "|------------------------|------------------------------------------------------------------------------|\n", "| Define structure | Created a JSON-LD template with `@context` and `BatteryTest` type |\n", "| Describe the battery | Added a semantic description of the test object using EMMO and BattINFO terms|\n", "| Add properties | Included battery properties like nominal voltage and capacity with units |\n", "| Link to dataset output | Connected the test to a data file and schema using `dcat` and `csvw` terms |\n", "| Save metadata | Serialized the complete metadata to a `metadata.jsonld` file |\n", "\n", "By following this workflow, your dataset now includes:\n", "- **Machine-readable semantic metadata** describing both the battery and the test\n", "- **Ontology-backed terms** that promote clarity and interoperability\n", "- A structured foundation for **linked data integration** at the 5-star level\n", "\n", "This notebook provides a clear and extensible pattern for making battery datasets semantically rich and FAIR-compliant." ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.10" } }, "nbformat": 4, "nbformat_minor": 5 }