Python API#
- orphan:
True
How the Python surface is organized — the generated symbol-by-symbol reference follows below; for the layered architecture, see How BattINFO is built.
Where to start#
Goal |
Surface to use |
|---|---|
Turn lab data into published, linked records |
|
Describe a battery product (a datasheet as data) |
The |
Author research-grade composition (materials, electrodes, electrolyte) |
|
Load, query, save, or resolver-publish canonical records |
|
Turn a folder of photos and CSVs into a linked submission |
|
Drive everything from the shell |
The |
If you are new here, start with the tutorials — six notebooks that walk the whole story end to end.
The curated top-level namespace (import battinfo) exposes the record classes, the
workspace, publishing, and validation — everything else lives in its home
module (battinfo.api, battinfo.authoring, battinfo.materials, …) and
is documented there.
The workspace#
battinfo.workspace(root) is the data-first surface: convert raw cycler
files, register cells, link tests and data, save validated records with
stable IRIs, and publish — to the registry review queue and, with
zenodo=True, to a citable DOI.
import battinfo
ws = battinfo.workspace(".")
ws.convert() # raw cycler files → tidy BDF tables
spec = ws.search("samsung inr21700 50e")[0] # reuse the registry's identity
ws.add("cell", spec=spec, serial_numbers=["S1", "S2"])
ws.add("test", type="cycling", cell="S1", data="bdf/S1.bdf.csv")
ws.save()
ws.publish(note="My cycling campaign, 2026")
ws.quickstart() prints the full recipe, including login and funding
attribution (ws.project(...), ws.contributor(...)).
Tutorial 3 builds the chain step by step;
Tutorial 6 runs it from a raw cycler
export.
Drafts and templates: ws.template("cell-spec", ...) /
ws.template("test-spec", ...) write skeleton draft files; ws.load(path)
authors them into the session. ws.load(ws.search(...)[0]) references an
existing registry record instead (reused, never re-published).
Record classes#
CellSpec, Cell, TestSpec, Test, and Dataset are the record types as
pydantic classes — the single source of truth for authoring and for what is on
disk. For a standalone cell-spec record, publish is the shortcut:
from battinfo import CellSpec, publish
cell_spec = CellSpec(
manufacturer="Google",
model="G20M7",
format="pouch",
chemistry="Li-ion",
)
local_result = publish(cell_spec, destination="local")
registry_result = publish(
cell_spec,
destination="registry",
registry_base_url="https://registry.example.org",
api_key="...",
workspace_id="hello-world",
publisher_id="demo-lab",
)
destination="local"writes the canonical BattINFO record and returns its path indebug_paths.destination="registry"also generates the submission package and submits it tobattinfo-registry.destination="battery-genome"additionally returns the expected Battery Genome page URL whenplatform_base_urlis configured.
Publication package (record-classes path)#
When you hold the four core record objects in Python and want the local publication artifacts without a workspace, build the package directly:
from pathlib import Path
from battinfo import Cell, CellSpec, Dataset, Test, build_publication_package, load_publication_package
dataset_dir = Path("data/cr2032-run")
dataset_dir.mkdir(parents=True, exist_ok=True)
(dataset_dir / "capacity.csv").write_text("cycle,capacity_ah\n1,0.225\n")
cell_spec = CellSpec(manufacturer="Energizer", model="CR2032", format="coin", chemistry="Li-primary")
cell = Cell(cell_spec=cell_spec, serial_number="energizer-cr2032-202602-dtjrga")
test = Test(cell=cell, kind="capacity_check", protocol="constant current discharging", status="completed")
dataset = Dataset(path=str(dataset_dir), cell=cell, test=test, name="Energizer CR2032 dataset")
report = build_publication_package(
cell_spec=cell_spec, cell_instance=cell, test=test, dataset=dataset,
)
bundle = load_publication_package(dataset_dir / "battinfo.publish.jsonld")
Notes:
battinfo.publish.jsonldis the foundational Schema.org JSON-LD artifact.ro-crate-metadata.jsonanddatacite-metadata.jsonare emitted alongside it.battinfo.dcat.jsonldis available as an optional export.
Query and save (battinfo.api)#
Canonical-record helpers for scripted workflows:
from battinfo import query_cell_specs, save_cell_instance
from battinfo.api import template_cell_instance
rows = query_cell_specs(manufacturer="A123", chemistry="LFP", limit=5)
draft = template_cell_instance(cell_spec_id="https://w3id.org/battinfo/spec/3m6k-9t2p-7x4h-9nq8")
draft["cell_instance"]["serial_number"] = "LAB-001"
result = save_cell_instance(draft, source_root="examples", resolve_references=False)
Draft inputs omit canonical fields like id, short_id, and identifier —
saving canonizes them and fills default provenance.
Index and resolver publishing (battinfo.api)#
from battinfo.api import build_index, index_stats, publish_record
publish_record(
"examples/cell-instance/cell-3m6k-9t2p-7x4h-9nq8.json",
target_root=".battinfo/resolver-site",
)
index = build_index(source_root="examples", out_path=".battinfo/index.json")
stats = index_stats(".battinfo/index.json")
Ingest-first intake (battinfo.ingest)#
One-command registration for a typed resource instance plus its evidence
files (photos become photo datasets; CSVs become a Test plus a Dataset):
from battinfo.ingest import build_ingest_workspace, publish_ingest_workspace, write_ingest_manifest
The folder-local battinfo.ingest.json manifest carries stable ingest
metadata; its shape is defined by
the ingest manifest contract and validated
against assets/schemas/ingest-manifest.schema.json.
resource_type="cell-instance" is the currently implemented subject.
Advanced: the internal engine#
battinfo.workspace(...) and the record classes are facades over an internal
authoring engine (battinfo._workspace.Workspace) that also powers
submission-package export and release workflows. New code should not build on
the engine directly — its surface is large, uncurated, and free to change;
everything the tutorials and this page show goes through the stable facades.
If you maintain older code that imports Workspace from battinfo, you will
see a deprecation message pointing at the replacement for each call.
Guidance#
Prefer
battinfo.workspace(...)for anything that ends in publishing.Prefer opaque BattINFO IRIs under
https://w3id.org/battinfo/.For validation policy and machine-readable issue output, see the validation contract.
For submission-envelope internals, see the contract explanation page.
Generated reference#
Everything below is generated from the source docstrings and field descriptions — it cannot drift from the code. The authoring workspace has its own page at Workspace authoring.
The record classes#
The five record classes are both the canonical source of truth and the
authoring input: construct them with the flat field names you know from the
datasheet and hand them to publish or the matching save_* function.
Every field is documented below; quantity keys and unit symbols are
enumerated in Property & unit reference.
- pydantic model battinfo.CellSpec#
- Fields:
bibliography (dict[str, Any])cell_specification_id (str | None)chemistry (str)comment (list[str])construction (dict[str, Any])country_of_origin (str | None)datasheet_revision (str | None)electrolyte (battinfo.bundle.Electrolyte | None)electrolyte_spec_id (str | None)format (str)housing (battinfo.bundle.Housing | None)housing_spec_id (str | None)id (str | None)iec_code (str | None)kind (str)manufacturer (str)manufacturer_id (str | None)model (str)name (str | None)negative_electrode (battinfo.bundle.Electrode | None)negative_electrode_basis (str | None)negative_electrode_spec_id (str | None)positive_electrode (battinfo.bundle.Electrode | None)positive_electrode_basis (str | None)positive_electrode_spec_id (str | None)product_type (battinfo.bundle.CellProductType | None)properties (dict[str, Any])rechargeable (bool | None)separator (battinfo.bundle.Separator | None)separator_spec_id (str | None)size_code (str | None)source (battinfo.bundle.ProvenanceInfo)specification_comment (list[str])uid (str | None)year (int | None)
- pydantic model battinfo.Cell#
- Fields:
batch_id (str | None)cell_spec (battinfo.bundle.CellSpec | None)cell_spec_id (str | None)comment (list[str])conformance (battinfo.bundle.Conformance | None)dataset_ids (list[str])expires_at (int | str | None)grade (str | None)id (str | None)kind (str)manufactured_at (int | str | None)measured (dict[str, Any])name (str | None)serial_number (str | None)source (battinfo.bundle.ProvenanceInfo)uid (str | None)
- pydantic model battinfo.TestSpec#
- Fields:
artifacts (list[battinfo.bundle.Artifact])comment (list[str])conditions (dict[str, battinfo.testmethod.Quantity])description (str | None)id (str | None)kind (str)method (list[battinfo.testmethod.Step])name (str | None)protocol (battinfo.bundle.ProtocolInfo)record (dict[str, Any])safety (dict[str, Any])source (battinfo.bundle.ProvenanceInfo)test_type (battinfo.bundle.BatteryTestType)uid (str | None)version (str | None)
- pydantic model battinfo.Test#
- Fields:
artifacts (list[battinfo.bundle.Artifact])cell (battinfo.bundle.Cell | None)cell_instance_id (str | None)channel_id (str | None)comment (list[str])conformance (battinfo.bundle.Conformance | None)dataset_ids (list[str])description (str | None)ended_at (int | str | None)equipment_id (str | None)id (str | None)instrument (str | None)kind (str)name (str | None)protocol (battinfo.bundle.ProtocolInfo)protocol_entity (battinfo.bundle.TestSpec | None)protocol_id (str | None)source (battinfo.bundle.ProvenanceInfo)started_at (int | str | None)status (str | None)test_type (battinfo.bundle.BatteryTestType)uid (str | None)
- pydantic model battinfo.Dataset#
- Fields:
access_url (str | None)additional_type (list[str])cell (battinfo.bundle.Cell | None)cell_instance_id (str | None)checksum (battinfo.bundle.ChecksumInfo)citations (list[dict[str, Any]])comment (list[str])conditions_of_access (str | None)created_at (int | str | None)creators (list[dict[str, Any]])data_format (str | None)dataset_path (str | None)description (str | None)distributions (list[dict[str, Any]])download_url (str | None)funders (list[dict[str, Any]])id (str | None)identifier (Any)in_language (str | None)included_in_data_catalog (str | dict[str, Any] | None)is_accessible_for_free (bool | None)is_based_on (list[str])keywords (list[str])kind (str)license (str | None)main_entity (list[dict[str, Any]])measurement_methods (list[str])measurement_techniques (list[str])modified_at (int | str | None)name (str | None)published_at (int | str | None)publisher (dict[str, Any] | None)related_cell_ids (list[str])related_test_ids (list[str])same_as (list[str])source (battinfo.bundle.ProvenanceInfo)spatial_coverage (str | None)temporal_coverage (str | None)test (battinfo.bundle.Test | None)test_id (str | None)uid (str | None)variable_measured (list[dict[str, Any]])version (str | None)
- pydantic model battinfo.ProvenanceInfo#
- Fields:
battinfo_version (str | None)citation (str | None)comment (str | None)curated_by (str | None)file (str | None)file_hash (str | None)name (str | None)retrieved_at (int | str | None)type (str | None)url (str | None)workflow_version (str | None)
Publish and save#
- battinfo.publish(obj: Any = None, destination: str | None = None, **kwargs: Any) PublishResult | dict[str, Any]#
Publish a BattINFO object to a named destination.
The new product surface is publish(obj, destination=…). The legacy publication-package call shape is still accepted for backwards compatibility and delegated to battinfo.publication.publish(…).
- battinfo.save_record(record: dict[str, Any] | str | Path, *, source_root: str | Path = PosixPath('examples'), mode: str = 'create_only', duplicate_policy: str = 'error', resolve_references: bool = True, publish: bool = False, publish_root: str | Path = '.battinfo/resolver-site', build_jsonld: bool = True, build_html: bool = True, validate: bool = True, validation_policy: ValidationPolicy | str = ValidationPolicy(name='default', schema='error', references='error', semantic='warn', publication='error'), dry_run: bool = False) dict[str, Any]#
Save one canonical BattINFO resource into local source storage and optional resolver artifacts.
Minting policy: records that arrive without an
id/uidare minted deterministically from their natural identity key (see_identity_minted_uid), so re-running an identical ingest lands on the existing records — usemode="upsert"(no-op re-save reportscontent_changed: False) orduplicate_policy="return_existing"for idempotent pipelines. Records with no distinguishing identity fall back to a random uid and never silently dedup.
- battinfo.bulk_save_session(source_root: Path | str) Iterator[RecordLocationCache]#
Speed up a batch of
save_*calls against one source root.Loads the id→path map once (per entity type, lazily) instead of rescanning the source root on every save:
with battinfo.bulk_save_session("examples"): for draft in drafts: battinfo.save_cell_instance(draft, source_root="examples")
Nested sessions for the same root reuse the outer cache. The session assumes single-writer access to
source_rootfor its duration.
Query and validate#
- battinfo.query_cell_specs(*, id: str | None = None, manufacturer: str | None = None, chemistry: str | None = None, format: str | None = None, model_name_contains: str | None = None, nominal_capacity_min: float | None = None, nominal_capacity_max: float | None = None, nominal_voltage_min: float | None = None, nominal_voltage_max: float | None = None, spec_filters: Mapping[str, tuple[float | None, float | None]] | None = None, cell_specs_dir: str | Path = PosixPath('/home/runner/work/BattINFO/BattINFO/src/battinfo/data/examples/cell-spec'), limit: int = 50, offset: int = 0) list[dict[str, Any]]#
Query cell types using practical metadata/property filters.
- battinfo.validate_record_report(doc: dict[str, Any], *, source_root: str | Path | None = None, policy: ValidationPolicy | str = ValidationPolicy(name='default', schema='error', references='error', semantic='warn', publication='error')) ValidationReport#
- battinfo.record_to_jsonld(record: dict, record_type: str) dict#
Transform a BattINFO plain-JSON record to a JSON-LD document.
- Parameters:
record – The plain-JSON record dict (as loaded from
.battinfo/records/).record_type – One of
"cell-spec","cell-instance","test","dataset".
- Returns:
dict – A JSON-LD document with
@context,@id,@type, and semantically typed properties using EMMO/schema.org IRIs.Example:: – import json from battinfo.jsonld import record_to_jsonld
raw = json.loads(Path(“cell-spec-xyz.json”).read_text()) ld = record_to_jsonld(raw, “cell-spec”) print(json.dumps(ld, indent=2))
The workspace object#
- class battinfo.AuthoringWorkspace(root: str | Path = '.', records_repo: str | Path | None = None, registry_url: str | None = None)#
The blessed authoring surface: a simplified workspace for BattINFO records.
Create one with
battinfo.workspace()and callquickstart()for a copy-pasteable end-to-end example. Wraps the lower-level object-graph enginebattinfo.Workspace(defined inbattinfo._workspace) with a concise API designed for interactive / notebook use.
Every method is documented in Workspace authoring; run
ws.commands() for the live cheat sheet. (The internal object-graph engine
in battinfo._workspace is an implementation detail — the deprecated
top-level Workspace name points you back here.)