Guide 4 — The semantic layer#
This guide examines the JSON-LD that BattINFO produces, explains how it connects to EMMO, and shows how to work with it using RDF tools.
Estimated time: 20 minutes Prerequisites: Guide 2 or Guide 3
New words? The plain-language glossary decodes EMMO, IRI, JSON-LD, and the rest in two sentences each.
[1]:
import json
import warnings
from pathlib import Path
SCRATCH = Path("_scratch/guide-04")
SCRATCH.mkdir(parents=True, exist_ok=True)
from battinfo import CellSpec, publish
from battinfo.api import publish_record
cell_spec = CellSpec(
manufacturer="A123 Systems",
model="ANR26650M1-B",
format="cylindrical",
chemistry="Li-ion",
positive_electrode_basis="LFP",
negative_electrode_basis="graphite",
size_code="R26650",
properties={
"nominal_capacity": {"value": 2.5, "unit": "Ah"},
"nominal_voltage": {"value": 3.3, "unit": "V"},
"rated_energy": {"value": 8.25, "unit": "Wh"},
"mass": {"value": 76.0, "unit": "g"},
"diameter": {"value": 26.0, "unit": "mm"},
"height": {"value": 65.0, "unit": "mm"},
"internal_resistance":{"value": 6.0, "unit": "mΩ"},
"cycle_life": {"value_text": ">1000", "unit": "count"},
},
)
result = publish(cell_spec, destination="local", root=SCRATCH)
output = publish_record(
result.debug_paths["canonical_record_path"],
target_root=SCRATCH / "resolver",
)
jsonld_path = Path(output["output_dir"], "index.jsonld")
jsonld = json.loads(jsonld_path.read_text(encoding="utf-8"))
print("Ready. IRI:", result.canonical_iri)
C:\t\bi-v5\src\battinfo\transform\cell_spec_node.py:583: UserWarning: semantic.value_text_only: 'cycle_life' on https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd carries only value_text - the JSON-LD export emits no numeric quantity value for it.
property_nodes = cell_spec_property_nodes(
C:\t\bi-v5\src\battinfo\transform\cell_spec_node.py:583: UserWarning: semantic.value_text_only: 'cycle_life' on https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd carries only value_text - the JSON-LD export emits no numeric quantity value for it.
property_nodes = cell_spec_property_nodes(
C:\t\bi-v5\src\battinfo\transform\cell_spec_node.py:583: UserWarning: semantic.value_text_only: 'cycle_life' on https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd carries only value_text - the JSON-LD export emits no numeric quantity value for it.
property_nodes = cell_spec_property_nodes(
C:\t\bi-v5\src\battinfo\transform\cell_spec_node.py:583: UserWarning: semantic.value_text_only: 'cycle_life' on https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd carries only value_text - the JSON-LD export emits no numeric quantity value for it.
property_nodes = cell_spec_property_nodes(
Ready. IRI: https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd
The full resolver JSON-LD#
[2]:
print(json.dumps(jsonld, indent=2))
{
"@context": [
"https://w3id.org/emmo/domain/battery/context",
{
"schema": "https://schema.org/",
"csvw": "http://www.w3.org/ns/csvw#",
"battinfo": "https://w3id.org/battinfo/",
"skos": "http://www.w3.org/2004/02/skos/core#"
}
],
"@type": [
"BatteryCellSpecification",
"schema:ProductModel",
"schema:CreativeWork"
],
"@id": "https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd",
"schema:identifier": "wckm-y5a4-he0k-2scd",
"schema:name": "A123 Systems ANR26650M1-B",
"schema:model": "ANR26650M1-B",
"schema:manufacturer": {
"@type": "schema:Organization",
"schema:name": "A123 Systems"
},
"schema:url": "https://www.battery-genome.org/registry/spec/wckm-y5a4-he0k-2scd",
"isDescriptionFor": {
"@type": [
"BatteryCell",
"CylindricalBattery",
"LithiumIonBattery",
"LithiumIonIronPhosphateBattery",
"LithiumIonGraphiteBattery"
],
"@id": "https://w3id.org/battinfo/spec/wckm-y5a4-he0k-2scd#described",
"skos:prefLabel": "A123 Systems ANR26650M1-B",
"hasProperty": [
{
"@type": [
"NominalCapacity",
"ConventionalProperty"
],
"skos:prefLabel": "NominalCapacity",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 2.5
},
"hasMeasurementUnit": "https://w3id.org/emmo#AmpereHour"
},
{
"@type": [
"NominalVoltage",
"ConventionalProperty"
],
"skos:prefLabel": "NominalVoltage",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 3.3
},
"hasMeasurementUnit": "https://w3id.org/emmo#Volt"
},
{
"@type": [
"NominalEnergy",
"ConventionalProperty"
],
"skos:prefLabel": "NominalEnergy",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 8.25
},
"hasMeasurementUnit": "https://w3id.org/emmo#Watthour"
},
{
"@type": [
"Mass",
"ConventionalProperty"
],
"skos:prefLabel": "Mass",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 76.0
},
"hasMeasurementUnit": "https://w3id.org/emmo#Gram"
},
{
"@type": [
"Diameter",
"ConventionalProperty"
],
"skos:prefLabel": "Diameter",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 26.0
},
"hasMeasurementUnit": "https://w3id.org/emmo#MilliMetre"
},
{
"@type": [
"Height",
"ConventionalProperty"
],
"skos:prefLabel": "Height",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 65.0
},
"hasMeasurementUnit": "https://w3id.org/emmo#MilliMetre"
},
{
"@type": [
"InternalResistance",
"ConventionalProperty"
],
"skos:prefLabel": "InternalResistance",
"hasNumericalPart": {
"@type": "RealData",
"hasNumberValue": 6.0
},
"hasMeasurementUnit": "https://w3id.org/emmo#MilliOhm"
},
{
"@type": [
"CycleLife",
"ConventionalProperty"
],
"skos:prefLabel": "CycleLife",
"hasStringValue": ">1000",
"hasMeasurementUnit": "https://w3id.org/emmo#EMMO_5ebd5e01_0ed3_49a2_a30d_cd05cbe72978"
}
],
"hasPositiveElectrode": {
"@type": "LithiumIronPhosphateElectrode"
},
"hasNegativeElectrode": {
"@type": "GraphiteElectrode"
}
},
"schema:size": "R26650",
"schema:schemaVersion": "0.2.0",
"schema:weight": {
"@type": "schema:QuantitativeValue",
"schema:value": 76.0,
"schema:unitText": "g"
},
"schema:height": {
"@type": "schema:QuantitativeValue",
"schema:value": 65.0,
"schema:unitText": "mm"
},
"schema:width": {
"@type": "schema:QuantitativeValue",
"schema:value": 26.0,
"schema:unitText": "mm"
},
"schema:depth": {
"@type": "schema:QuantitativeValue",
"schema:value": 26.0,
"schema:unitText": "mm"
},
"dcterms:source": {
"@type": "prov:Entity",
"dcterms:type": "datasheet",
"prov:generatedAtTime": "2026-09-15T14:08:34+00:00"
}
}
@context#
Maps short names to full IRIs. Every term — BatteryCell, hasNumericalPart, NominalCapacity — resolves to a UUID-based IRI in the EMMO domain-battery ontology. BattINFO bundles a local copy so processing works offline.
@id#
The permanent IRI for this cell spec, resolvable at https://w3id.org/battinfo/spec/{uid}.
@type stacking#
[3]:
print("@type classes:")
for t in jsonld["@type"]:
print(f" {t}")
@type classes:
BatteryCellSpecification
schema:ProductModel
schema:CreativeWork
The specification node (BatteryCellSpecification) carries three types:
Vocabulary |
Type |
Rationale |
|---|---|---|
EMMO |
|
Information entity describing a class of cells |
schema.org |
|
The catalogue entry: name, manufacturer, brand, codes |
schema.org |
|
The specification document as a creative artifact |
The physical EMMO classes derived from cell-spec fields are placed on an isDescriptionFor anonymous node:
Source field |
Physical EMMO class (on |
|---|---|
|
|
|
|
|
|
|
|
(always) |
|
Placing physical types on isDescriptionFor is semantically correct: the specification is an information entity, not a physical cell. The old pattern (putting BatteryCell directly on the specification @type) implied the specification IS a physical cell, which is wrong.
No manual annotation — derived entirely from plain-text field values.
hasProperty — the canonical EMMO quantity pattern#
isDescriptionFor — where physical EMMO types live#
Both the resolver JSON-LD and the full descriptor JSON-LD (produced by to_jsonld) carry the described battery on an isDescriptionFor anonymous node: the physical EMMO classes plus the hasProperty quantities and composition. The spec node keeps only catalogue and record facts:
This placement is semantically correct: the specification is an information entity, not a physical cell. Putting BatteryCell on the specification @type would assert the specification IS a physical cell — which is wrong.
hasDescription — the reverse link from cell instance to specification#
Cell instances (physical objects with serial numbers) carry hasDescription pointing to the specification IRI, plus schema:isVariantOf for schema.org alignment:
The directionality reflects how data is created: the cell spec is registered first and given a stable IRI; individual cells with serial numbers are created later and reference it. Both hasDescription (EMMO) and schema:isVariantOf (schema.org) express the same relationship in their respective vocabularies.
[4]:
# Show isDescriptionFor from the full descriptor pipeline
from battinfo.transform.json_to_jsonld import _descriptor_specification_to_jsonld
spec = {
"format": "cylindrical",
"chemistry": "Li-ion",
"positive_electrode_basis": "LFP",
"negative_electrode_basis": "graphite",
}
node = _descriptor_specification_to_jsonld(spec)
print("Specification @type:", node["@type"])
print("isDescriptionFor @type:", node["isDescriptionFor"]["@type"])
Specification @type: ['BatteryCellSpecification', 'schema:ProductModel', 'schema:CreativeWork']
isDescriptionFor @type: ['BatteryCell', 'CylindricalBattery', 'LithiumIonBattery', 'LithiumIonIronPhosphateBattery', 'LithiumIonGraphiteBattery']
[5]:
# Quantities live on the described battery, not the specification node.
described = jsonld.get("isDescriptionFor", {})
print("Quantitative properties:")
for prop in described.get("hasProperty", []):
types = prop["@type"]
class_name = types[0] if isinstance(types, list) else types
value = prop.get("hasNumericalPart", {}).get("hasNumberValue")
unit = prop.get("hasMeasurementUnit", "").split("#")[-1]
print(f" {class_name}: {value} ({unit})")
Quantitative properties:
NominalCapacity: 2.5 (AmpereHour)
NominalVoltage: 3.3 (Volt)
NominalEnergy: 8.25 (Watthour)
Mass: 76.0 (Gram)
Diameter: 26.0 (MilliMetre)
Height: 65.0 (MilliMetre)
InternalResistance: 6.0 (MilliOhm)
CycleLife: None (EMMO_5ebd5e01_0ed3_49a2_a30d_cd05cbe72978)
The pattern is:
hasProperty → NominalCapacity, ConventionalProperty
├── hasNumericalPart → RealData → hasNumericalValue: 2.5
└── hasMeasurementUnit: <EMMO AmpereHour IRI>
This is the canonical EMMO quantity pattern — identical across all EMMO domain modules.
Validating JSON-LD#
[6]:
from battinfo.validate.jsonld import validate_jsonld_report
report = validate_jsonld_report(jsonld)
print("ok:", report.ok)
for issue in report.issues:
print(f" [{issue.severity}] {issue.code}: {issue.message}")
ok: True
Check |
What fails |
|---|---|
|
Bare |
RDF parse |
JSON-LD rdflib cannot parse into a valid RDF dataset |
URDNA2015 |
JSON-LD that cannot be canonically normalised |
Loading into an RDF graph#
[7]:
from rdflib import Graph
g = Graph()
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning, module="rdflib")
g.parse(str(jsonld_path), format="json-ld")
print(f"Triple count: {len(g)}")
Triple count: 105
[8]:
# All triples in the graph
for s, p, o in sorted(g):
s_l = str(s).split("/")[-1].split("#")[-1]
p_l = str(p).split("/")[-1].split("#")[-1]
o_l = str(o).split("/")[-1].split("#")[-1]
print(f" {s_l} → {p_l} → {o_l}")
N035a2b79d8a9401cb8bd447b3c31d220 → type → QuantitativeValue
N035a2b79d8a9401cb8bd447b3c31d220 → unitText → mm
N035a2b79d8a9401cb8bd447b3c31d220 → value → 26.0
N12ecfba392224a38b9eb33a42793a424 → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N12ecfba392224a38b9eb33a42793a424 → type → electrochemistry_19e27aa3_0970_43a6_86d3_e3cdd956134d
N12ecfba392224a38b9eb33a42793a424 → prefLabel → NominalEnergy
N12ecfba392224a38b9eb33a42793a424 → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → N1c3521fcc0d944a6bab386af8553bdb4
N12ecfba392224a38b9eb33a42793a424 → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → Watthour
N1c3521fcc0d944a6bab386af8553bdb4 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
N1c3521fcc0d944a6bab386af8553bdb4 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 8.25
N2b72064745a04e8582cf6624aff4e568 → type → EMMO_08bcf1d6_e719_46c8_bb21_24bc9bf34dba
N2b72064745a04e8582cf6624aff4e568 → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N2b72064745a04e8582cf6624aff4e568 → prefLabel → Height
N2b72064745a04e8582cf6624aff4e568 → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → Ne42e0301b0844dc6be47f09c3351de87
N2b72064745a04e8582cf6624aff4e568 → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → MilliMetre
N31280bdf35bd4995bee2cf86048e650f → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N31280bdf35bd4995bee2cf86048e650f → type → electrochemistry_ae782b14_88ce_4cdd_9418_12aca00be937
N31280bdf35bd4995bee2cf86048e650f → prefLabel → CycleLife
N31280bdf35bd4995bee2cf86048e650f → EMMO_02face50_43a1_40ce_a909_dfe54d5e186b → >1000
N31280bdf35bd4995bee2cf86048e650f → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → EMMO_5ebd5e01_0ed3_49a2_a30d_cd05cbe72978
N31a756347a20439084866840de8d5f1e → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N31a756347a20439084866840de8d5f1e → type → electrochemistry_8abde9d0_84f6_4b4f_a87e_86028a397100
N31a756347a20439084866840de8d5f1e → prefLabel → NominalCapacity
N31a756347a20439084866840de8d5f1e → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → N6ee211c2b8754db58f22b31c49134c94
N31a756347a20439084866840de8d5f1e → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → AmpereHour
N41d93455a3a94559bd4376c872767a3c → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N41d93455a3a94559bd4376c872767a3c → type → electrochemistry_9bf40017_3f58_4030_ada7_cb37a3dfda2d
N41d93455a3a94559bd4376c872767a3c → prefLabel → InternalResistance
N41d93455a3a94559bd4376c872767a3c → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → Na59130a49409487d8a572f0329bf2e11
N41d93455a3a94559bd4376c872767a3c → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → MilliOhm
N50b9dc0d1f43466bb9e7021a987f401c → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N50b9dc0d1f43466bb9e7021a987f401c → type → electrochemistry_639b844a_e801_436b_985d_28926129ead6
N50b9dc0d1f43466bb9e7021a987f401c → prefLabel → NominalVoltage
N50b9dc0d1f43466bb9e7021a987f401c → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → Nad3f681fa168492f91d7efd75a9d945f
N50b9dc0d1f43466bb9e7021a987f401c → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → Volt
N5f908c41a6c047d6bbbd82a9a6261f1d → type → QuantitativeValue
N5f908c41a6c047d6bbbd82a9a6261f1d → unitText → mm
N5f908c41a6c047d6bbbd82a9a6261f1d → value → 65.0
N65c6689ee02f474eafc5893525cd885b → type → QuantitativeValue
N65c6689ee02f474eafc5893525cd885b → unitText → g
N65c6689ee02f474eafc5893525cd885b → value → 76.0
N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9 → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9 → type → EMMO_ed4af7ae_63a2_497e_bb88_2309619ea405
N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9 → prefLabel → Mass
N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9 → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → Ne149892ece8b43c0a548f1d6855e6d21
N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9 → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → Gram
N6c748f92d0f7473a8239f20f916db1e0 → type → QuantitativeValue
N6c748f92d0f7473a8239f20f916db1e0 → unitText → mm
N6c748f92d0f7473a8239f20f916db1e0 → value → 26.0
N6ee211c2b8754db58f22b31c49134c94 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
N6ee211c2b8754db58f22b31c49134c94 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 2.5
N8eccc37a8f3c4796a5da751996640a5a → type → electrochemistry_c831d963_629a_41ab_850f_97fb6841b739
Na164114e26534709a463badb0412db73 → type → Organization
Na164114e26534709a463badb0412db73 → name → A123 Systems
Na16a57b34dc148979772cddf397b992e → type → EMMO_c1c8ac3c_8a1c_4777_8e0b_14c1f9f9b0c6
Na16a57b34dc148979772cddf397b992e → type → EMMO_d8aa8e1f_b650_416d_88a0_5118de945456
Na16a57b34dc148979772cddf397b992e → prefLabel → Diameter
Na16a57b34dc148979772cddf397b992e → EMMO_8ef3cd6d_ae58_4a8d_9fc0_ad8f49015cd0 → Nf2dea97416874d93940f496ac3b0d155
Na16a57b34dc148979772cddf397b992e → EMMO_bed1d005_b04e_4a90_94cf_02bc678a8569 → MilliMetre
Na59130a49409487d8a572f0329bf2e11 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
Na59130a49409487d8a572f0329bf2e11 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 6.0
Nad3f681fa168492f91d7efd75a9d945f → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
Nad3f681fa168492f91d7efd75a9d945f → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 3.3
Ne149892ece8b43c0a548f1d6855e6d21 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
Ne149892ece8b43c0a548f1d6855e6d21 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 76.0
Ne347b88e04e04438a6e654557e309dfa → type → datasheet
Ne347b88e04e04438a6e654557e309dfa → type → Entity
Ne347b88e04e04438a6e654557e309dfa → generatedAtTime → 2026-09-15T14:08:34+00:00
Ne42e0301b0844dc6be47f09c3351de87 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
Ne42e0301b0844dc6be47f09c3351de87 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 65.0
Nf272fe8d46404e4fb911748e7723899c → type → electrochemistry_1d0f15cb_d6b5_4c27_89ca_fe78adc1ce5b
Nf2dea97416874d93940f496ac3b0d155 → type → EMMO_18d180e4_5e3e_42f7_820c_e08951223486
Nf2dea97416874d93940f496ac3b0d155 → EMMO_faf79f53_749d_40b2_807c_d34244c192f4 → 26.0
wckm-y5a4-he0k-2scd → source → Ne347b88e04e04438a6e654557e309dfa
wckm-y5a4-he0k-2scd → type → CreativeWork
wckm-y5a4-he0k-2scd → type → ProductModel
wckm-y5a4-he0k-2scd → type → battery_1cfbba6c_8824_4932_a23e_2141483acef7
wckm-y5a4-he0k-2scd → depth → N6c748f92d0f7473a8239f20f916db1e0
wckm-y5a4-he0k-2scd → height → N5f908c41a6c047d6bbbd82a9a6261f1d
wckm-y5a4-he0k-2scd → identifier → wckm-y5a4-he0k-2scd
wckm-y5a4-he0k-2scd → manufacturer → Na164114e26534709a463badb0412db73
wckm-y5a4-he0k-2scd → model → ANR26650M1-B
wckm-y5a4-he0k-2scd → name → A123 Systems ANR26650M1-B
wckm-y5a4-he0k-2scd → schemaVersion → 0.2.0
wckm-y5a4-he0k-2scd → size → R26650
wckm-y5a4-he0k-2scd → url → wckm-y5a4-he0k-2scd
wckm-y5a4-he0k-2scd → weight → N65c6689ee02f474eafc5893525cd885b
wckm-y5a4-he0k-2scd → width → N035a2b79d8a9401cb8bd447b3c31d220
wckm-y5a4-he0k-2scd → EMMO_f702bad4_fc77_41f0_a26d_79f6444fd4f3 → described
described → type → battery_04a4e5a4_e6fd_43af_b1ca_4a16d5f8886c
described → type → battery_2018e0da_4c25_46e9_83db_38431fc81ce0
described → type → battery_68ed592a_7924_45d0_a108_94d6275d57f0
described → type → battery_96addc62_ea04_449a_8237_4cd541dd8e5f
described → type → battery_ac604ecd_cc60_4b98_b57c_74cd5d3ccd40
described → prefLabel → A123 Systems ANR26650M1-B
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N12ecfba392224a38b9eb33a42793a424
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N2b72064745a04e8582cf6624aff4e568
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N31280bdf35bd4995bee2cf86048e650f
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N31a756347a20439084866840de8d5f1e
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N41d93455a3a94559bd4376c872767a3c
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N50b9dc0d1f43466bb9e7021a987f401c
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → N6a8dcca5ff7e4cb2a9f4a17a94a2a3f9
described → EMMO_e1097637_70d2_4895_973f_2396f04fa204 → Na16a57b34dc148979772cddf397b992e
described → electrochemistry_5d299271_3f68_494f_ab96_3db9acdd3138 → N8eccc37a8f3c4796a5da751996640a5a
described → electrochemistry_8e9cf965_9f92_46e8_b678_b50410ce3616 → Nf272fe8d46404e4fb911748e7723899c
Combining multiple records in one graph#
[9]:
import battinfo
ws = battinfo.workspace(root=SCRATCH / "multi")
multi_spec = battinfo.CellSpec(
manufacturer="A123 Systems", model="ANR26650M1-B",
format="cylindrical", chemistry="Li-ion",
positive_electrode_basis="LFP", negative_electrode_basis="graphite",
properties={"nominal_capacity": {"value": 2.5, "unit": "Ah"}},
)
ws.add("cell", spec=multi_spec, serial_numbers=["a123-demo-multi-001"])
ws.save()
# Publish each saved record as a resolver artifact
from battinfo.api import publish_record as _publish_one
multi_records = SCRATCH / "multi" / ".battinfo" / "records" / "examples"
multi_resolver = SCRATCH / "multi-resolver"
for record_file in sorted(multi_records.rglob("*.json")):
_publish_one(record_file, target_root=multi_resolver)
jsonld_files = list(multi_resolver.rglob("index.jsonld"))
g2 = Graph()
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning, module="rdflib")
for jf in jsonld_files:
g2.parse(str(jf), format="json-ld")
print(f"Combined graph: {len(g2)} triples from {len(jsonld_files)} files")
cell: a123-demo-multi-001 (IRI auto-assigned)
Saved 2 record(s) under C:\t\bi-v5\docs\guides\_scratch\guide-04\multi\.battinfo\records:
cell spec A123 Systems ANR26650M1-B [unchanged] .battinfo\records\cell-spec\cell-spec-e4t5-w9re-mpq6-8g7e.json
cell a123-demo-multi-001 [unchanged] .battinfo\records\cell-instance\cell-aaqe-rvbd-c0b6-p1k3.json
Next: ws.list(verbose=True) to inspect, or ws.publish() to publish.
Combined graph: 0 triples from 0 files
Mapping tables#
BattINFO’s semantic output is driven by three curated files:
File |
Role |
|---|---|
|
JSON key → EMMO class IRI |
|
Unit string → EMMO/QUDT IRI |
|
format/chemistry/electrode → @type array |
[10]:
prop_map = json.loads(
# Repo files sit two levels up from this notebook.
Path("../../assets/mappings/domain-battery/property_map.curated.json").read_text(encoding="utf-8")
)
print(f"Property map version: {prop_map['version']}")
print(f"Curated entries: {len(prop_map['mappings'])}")
print()
for entry in prop_map["mappings"][:8]:
print(f" {entry['key']:42s} → {entry['class_pref_label']}")
print(" ...")
Property map version: 0.4.0
Curated entries: 81
ac_internal_resistance → ACInternalResistance
available_volume → Volume
calendar_life → CalendarLife
cap_assembly_weight → Mass
capacity_fade → CapacityFadeRate
capacity_threshold_exhaustion → EndOfLifeCapacityThreshold
certified_usable_energy → NominalEnergy
charging_capacity → ChargingCapacity
...
Next#
Guide 5 — Descriptors: author research-grade cell descriptors and see richer electrode-level JSON-LD