Python client for interacting with the Ionworks API
Project description
Ionworks API Client
⚠️ Warning: This client is under active development and the API may change without notice.
A Python client for interacting with the Ionworks API.
Installation
pip install ionworks-api
Then copy the example environment file and fill in your credentials:
cp .env.example .env
Get your API key from the Ionworks account settings and your project ID from your project settings page. See Environment Setup for details.
Usage
Basic usage example:
from ionworks import Ionworks
# Initialize client (uses IONWORKS_API_KEY from environment/.env file)
client = Ionworks()
# or provide credentials directly
client = Ionworks(api_key="your_key")
# Customize timeout and retry behavior
# By default, the client uses a 10 second request timeout and will retry failed requests up to 5 times.
# You can override these defaults as shown below:
client = Ionworks(timeout=30, max_retries=3) # 30s timeout, max 3 retries
# Check API health
health = client.health_check()
print(health)
Uploading data to the Ionworks app
Uploading data to the Ionworks app follows a three-step process:
- Create a cell spec (or get an existing one)
- Create a cell instance with the spec id
- Upload measurement(s) with time series data using the instance id
Given time series data, the data can be uploaded as follows:
from ionworks import Ionworks
import pandas as pd
client = Ionworks()
# Step 1: Create or get a cell specification
cell_spec = client.cell_spec.create_or_get(
{
"name": "NCM622/Graphite Coin Cell",
"form_factor": "R2032",
"manufacturer": "Custom Cells",
"ratings": {
"capacity": {"value": 0.002, "unit": "A*h"},
"voltage_min": {"value": 2.5, "unit": "V"},
"voltage_max": {"value": 4.2, "unit": "V"},
},
"cathode": {
"properties": {"loading": {"value": 12.3, "unit": "mg/cm**2"}},
"material": {"name": "NCM622", "manufacturer": "BASF"},
},
"anode": {
"properties": {"loading": {"value": 6.5, "unit": "mg/cm**2"}},
"material": {"name": "Graphite", "manufacturer": "Customcells"},
},
}
)
# Step 2: Create or get a cell instance
cell_instance = client.cell_instance.create_or_get(
cell_spec.id,
{
"name": "NCM622-GR-001",
"batch": "BATCH-2024-001",
"date_manufactured": "2024-01-20",
"measured_properties": {
"cathode": {"loading": {"value": 12.1, "unit": "mg/cm**2"}},
"anode": {"loading": {"value": 6.4, "unit": "mg/cm**2"}},
},
},
)
# Step 3: Upload measurement with time series data
time_series = pd.DataFrame(
{
"Time [s]": [0, 1, 2, 3, 4, 5],
"Voltage [V]": [3.0, 3.2, 3.5, 3.8, 4.0, 4.2],
"Current [A]": [0.002, 0.002, 0.002, 0.002, 0.002, 0.002],
"Step count": [0, 0, 0, 1, 1, 1],
"Cycle count": [0, 0, 0, 0, 0, 0],
"Step from cycler": [1, 1, 1, 2, 2, 2],
"Cycle from cycler": [0, 0, 0, 0, 0, 0],
}
)
measurement_data = {
"measurement": {
"name": "Formation Cycle 1",
"protocol": {
"name": "CC-CV charge at C/10 to 4.2V",
"ambient_temperature_degc": 25,
},
"test_setup": {
"cycler": "Biologic VMP3",
"operator": "Jane Smith",
},
"notes": "Formation cycle - first charge",
},
"time_series": time_series,
}
measurement_bundle = client.cell_measurement.create(
cell_instance.id, measurement_data
)
print(f"Created measurement: {measurement_bundle.measurement.name}")
print(f"Steps created: {measurement_bundle.steps_created}")
Reading cell data
from ionworks import Ionworks
client = Ionworks()
# List all cell specifications
specs = client.cell_spec.list()
for spec in specs[:5]:
print(f" - {spec.name} (form_factor: {spec.form_factor})")
# Get a specific cell spec with full nested data
full_spec = client.cell_spec.get(spec_id)
print(f"Capacity: {full_spec.ratings['capacity']['value']} "
f"{full_spec.ratings['capacity']['unit']}")
# List instances for a spec and pick the first
instances = client.cell_instance.list(spec_id)
instance_id = instances[0].id
# List measurements for an instance
measurements = client.cell_measurement.list(instance_id)
# Get measurement detail with time series
measurement_detail = client.cell_measurement.detail(measurement_id)
print(f"Time series shape: {measurement_detail.time_series.shape}")
Running pipelines
Pipelines allow you to run complex workflows combining data fitting, calculations, and validations. A pipeline consists of named elements, where each element has an element_type and configuration specific to that type.
Recommended workflow: First upload your experimental data using the cell measurement API (see "Uploading data to the Ionworks app" above), then reference it in your pipeline using the db:<measurement_id> format. This ensures your data is stored and versioned in the database.
Available element types:
entry: Provide initial parameter valuesdata_fit: Fit model parameters to experimental datacalculation: Run calculations (e.g., OCP fitting)validation: Validate model against data
from ionworks import Ionworks
client = Ionworks()
# First, upload your data (see "Uploading data to the Ionworks app" section)
# Then get the measurement ID to reference in the pipeline
measurements = client.cell_measurement.list(cell_instance_id)
measurement_id = measurements[0].id # or find the specific measurement you need
# Define entry configuration with initial parameter values
entry_config = {
"values": {
"Negative particle diffusivity [m2.s-1]": 3.3e-14,
"Positive particle diffusivity [m2.s-1]": 4e-15,
# ... other parameters
}
}
# Define datafit configuration - reference uploaded data with db:<measurement_id>
datafit_config = {
"objectives": {
"test_1C": {
"objective": "CurrentDriven",
"model": {"type": "SPMe"},
"data": f"db:{measurement_id}", # Reference data from database
"parameters": {"Ambient temperature [K]": 298.15},
},
},
"parameters": {
"Negative particle diffusivity [m2.s-1]": {
"bounds": [1e-14, 1e-13],
"initial_value": 2e-14,
},
"Positive particle diffusivity [m2.s-1]": {
"bounds": [1e-15, 1e-14],
"initial_value": 2e-15,
},
},
"cost": {"type": "RMSE"},
"optimizer": {"type": "ScipyDifferentialEvolution"},
}
# Create pipeline config with named elements
pipeline_config = {
"elements": {
"entry": {**entry_config, "element_type": "entry"},
"fit data": {**datafit_config, "element_type": "data_fit"},
},
}
# Submit pipeline and wait for completion
pipeline = client.pipeline.create(pipeline_config)
print(f"Pipeline submitted: {pipeline.id}")
pipeline = client.pipeline.wait_for_completion(pipeline.id, timeout=600)
if pipeline.status == "completed":
result = client.pipeline.result(pipeline.id)
print("Fitted parameters:", result.element_results["fit data"])
Running simulations
The client supports running battery simulations using the Universal Cycler Protocol (UCP) format:
from ionworks import Ionworks
client = Ionworks()
# Define a charge/discharge protocol in YAML format
protocol_yaml = """global:
initial_state_type: soc_percentage
initial_state_value: 50
initial_temperature: 25.0
steps:
- Charge:
mode: C-rate
value: "0.6"
ends:
- Voltage > 4.2
- Rest:
duration: 3600
- Discharge:
mode: C-rate
value: "0.5"
ends:
- Voltage < 2.5
"""
# Create simulation with quick model
config = {
"parameterized_model": {
"quick_model": {"capacity": 1.0, "chemistry": "NMC/Graphite"}
},
"protocol_experiment": {
"protocol": protocol_yaml,
"name": "NMC Charge Discharge Protocol",
},
}
result = client.simulation.protocol(config)
print(f"Simulation ID: {result.simulation_id}")
# Wait for completion
simulation = client.simulation.wait_for_completion(
result.simulation_id, timeout=60, poll_interval=2
)
# Get results
simulation_data = client.simulation.get_result(result.simulation_id)
time_series = simulation_data.get("time_series", {})
Environment Setup
The client uses environment variables for configuration. Copy the example file and fill in your values:
cp .env.example .env
| Variable | Required | Default | Description |
|---|---|---|---|
IONWORKS_API_KEY |
Yes | — | API key from account settings |
IONWORKS_API_URL |
No | https://api.ionworks.com |
API base URL |
PROJECT_ID |
For pipelines | — | Project ID from your project settings page |
The client loads .env automatically via python-dotenv.
Error Handling
The client will raise exceptions in the following cases:
- Missing API credentials
- Invalid API credentials
- API request errors (will raise
IonworksErrorwith details)
When HTTP errors occur, the client automatically prints the x-correlation-id header
from the response (if present). This correlation ID helps trace requests in backend
logs for debugging purposes.
Make sure to handle these exceptions appropriately in your code.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ionworks_api-0.4.0.tar.gz.
File metadata
- Download URL: ionworks_api-0.4.0.tar.gz
- Upload date:
- Size: 41.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
645e906f7f697ee13a2f6ae7a0e0faba44f5f874e217d4008b16ad4b83aa1111
|
|
| MD5 |
3603cbf9fb43446653f06c641dc72b33
|
|
| BLAKE2b-256 |
24453aa25539159cf9179a186f5b2f3486f8bee2f2a7c5c692b7ac8ea0232f85
|
Provenance
The following attestation bundles were made for ionworks_api-0.4.0.tar.gz:
Publisher:
release-package.yml on ionworks/ionworks-app
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ionworks_api-0.4.0.tar.gz -
Subject digest:
645e906f7f697ee13a2f6ae7a0e0faba44f5f874e217d4008b16ad4b83aa1111 - Sigstore transparency entry: 1272491154
- Sigstore integration time:
-
Permalink:
ionworks/ionworks-app@a115c445721cd6f053ddf79e7c205f2cda1a9a05 -
Branch / Tag:
refs/tags/ionworks-api-v0.4.0 - Owner: https://github.com/ionworks
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
release-package.yml@a115c445721cd6f053ddf79e7c205f2cda1a9a05 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ionworks_api-0.4.0-py3-none-any.whl.
File metadata
- Download URL: ionworks_api-0.4.0-py3-none-any.whl
- Upload date:
- Size: 48.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74afce36dfd22e68e912b5c29fc480854ad511cb7867c5b34206659cd1290d54
|
|
| MD5 |
29fc190eeff325f7f2457f5c89436c3a
|
|
| BLAKE2b-256 |
86787b0de4066014f80e3280b34b61237f642591279ab613fd9589229be9535b
|
Provenance
The following attestation bundles were made for ionworks_api-0.4.0-py3-none-any.whl:
Publisher:
release-package.yml on ionworks/ionworks-app
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ionworks_api-0.4.0-py3-none-any.whl -
Subject digest:
74afce36dfd22e68e912b5c29fc480854ad511cb7867c5b34206659cd1290d54 - Sigstore transparency entry: 1272491179
- Sigstore integration time:
-
Permalink:
ionworks/ionworks-app@a115c445721cd6f053ddf79e7c205f2cda1a9a05 -
Branch / Tag:
refs/tags/ionworks-api-v0.4.0 - Owner: https://github.com/ionworks
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
release-package.yml@a115c445721cd6f053ddf79e7c205f2cda1a9a05 -
Trigger Event:
push
-
Statement type: