Example: Zinc Oxide Active Material#
This is an example demonstrating how to describe a zinc oxide that fulfills the role of active material in an electrode. We will see how to:
describe the material in JSON-LD,
load the JSON-LD description into a graph, and
query the graph to retrieve some properties.
Load the ontology and instantiate an empty graph#
Fist, we import the necessary libraries, load the pre-inferred version of the electrochemistry ontology and instantiate an empty RDF graph.
[1]:
# Import necessary libraries
from rdflib import Graph
from ontopy import get_ontology
import json
# Load the ontology
echo = get_ontology('https://w3id.org/emmo/domain/electrochemistry/inferred').load()
# Create an empty RDF graph
g = Graph()
Write a JSON-LD description of the resource#
We can now write a JSON-LD description of our zinc oxide. This can be done either directly in python (like this example) or it can be loaded from an existing .json or .jsonld file.
The use of multiple inheretence to describe the resource highlights that it is something with the chemical substance of zinc oxide and playing the role of an active material. The statement that it is an active material, implies that it is part of an electrode. From a semantic perspective, this is only true when then material is actually integrated into the electrode.
Quantitative properties in EMMO are defined using the hasProperty relationship and adhere to the SI recommendations that a quantity is the product of a numerical part and a measurement unit. EMMO also provides the option to distinguish the source of the property. A property that comes from a known measurement is a MeasuredProperty, while a property that is assumed by convention (for example, taken from a data sheet) is a ConventionalProperty.
[2]:
# Load the JSON-LD data
json_ld_data = {
"@context": "https://w3id.org/emmo/domain/electrochemistry/context",
"@type": ["ZincOxide", "ActiveMaterial"],
"schema:manufacturer": {
"@type": "schema:ResearchOrganization",
"@id": "https://www.wikidata.org/wiki/Q3041255",
"schema:name": "SINTEF"
},
"hasProperty": [
{
"@type": ["SpecificCapacity", "MeasuredProperty"],
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 650
},
"hasMeasurementUnit": "emmo:MilliAmpereHourPerGram"
},
{
"@type": ["D50ParticleSize", "ConventionalProperty"],
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 20
},
"hasMeasurementUnit": "emmo:MicroMetre"
},
{
"@type": ["5.61", "ConventionalProperty"],
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 2.5
},
"hasMeasurementUnit": "emmo:GramPerCubicCentiMetre"
}
]
}
Load into a graph and query#
Now we can load the JSON-LD description of the resource into an RDF graph that will convert it to a set of triples. We can then query the grpah using the query language SPARQL. Because EMMO ontology class IRIs are not human-readable, we can use the ontopy description of the ontology to make queries using the human-readable labels instead.
In the example below, we query the graph to return the value for the specific capacity of the active material.
[3]:
# Convert JSON-LD data to RDF and add to the graph
g.parse(data=json.dumps(json_ld_data), format='json-ld')
# Query the graph to get the diameter
query = f"""
SELECT ?propertyValue ?measurementUnit
WHERE {{
?material a <{echo.ActiveMaterial.iri}> ;
<{echo.hasProperty.iri}> ?property .
?property a <{echo.SpecificCapacity.iri}> ;
<{echo.hasNumericalPart.iri}> ?numericalPart ;
<{echo.hasMeasurementUnit.iri}> ?measurementUnit .
?numericalPart <{echo.hasNumberValue.iri}> ?propertyValue .
}}
"""
# Run the query
results = g.query(query)
# Print results
for row in results:
unit = row.measurementUnit
print(f"Specific Capacity: {row.propertyValue} {row.measurementUnit}")
Specific Capacity: 650 emmo:MilliAmpereHourPerGram