Skip to main content
The ionworks-api Python package lets you run simulations and submit parameterization pipelines programmatically. For installation and authentication, see the Python API client page.

Running simulations

Use client.simulation to run simulations. A simulation requires a parameterized model and a protocol in UCP format.

Single simulation

You can also pass experiment parameters and design parameters:
design_parameters is a single-simulation convenience field on protocol(). Pass a flat dict[str, float] of parameter overrides — the client translates them internally to a one-row discrete DOE before submission. Use it when you want to vary one or more design parameters for a single run without writing out the full DOE schema.
In protocol(), design_parameters and design_parameters_doe are mutually exclusive, and any DOE you supply must resolve to exactly one simulation. Passing both, or a DOE that would expand to multiple simulations, raises ValueError — use protocol_batch for multi-simulation sweeps instead.

Waiting for results

Use wait_for_completion to poll until the simulation finishes. The method detects failed and canceled jobs immediately rather than waiting for the timeout.
Set raise_on_failure=False to get the result dict instead of raising an exception when a simulation fails:

Batch simulations with design of experiments

Run multiple simulations across a parameter sweep using protocol_batch:
Supported DOE row types: Sampling strategies: grid (all combinations), random, latin_hypercube.

Retrieving simulation data

get_result returns a typed SimulationResult dataclass with three fields: time_series and steps are returned as polars DataFrames by default. Call set_dataframe_backend("pandas") once at session start to receive pandas DataFrames instead.
Discharge capacity [A.h] and Charge capacity [A.h] in time_series reset to 0 at each step boundary. Use "Step count" to join time_series to steps, or accumulate per-step end values if you need a continuous cumulative capacity trace.

Running pipelines

Pipelines combine data fitting, calculations, and validation steps for battery model parameterization. Use client.pipeline to submit and manage pipelines.
Pipelines require a project_id. Set the IONWORKS_PROJECT_ID environment variable (or pass project_id= to Ionworks(...)) to configure a default project, or include project_id in the pipeline config explicitly. The deprecated PROJECT_ID env var is still accepted as a fallback.

Submitting a pipeline

Pipeline elements must be a dictionary (not a list). Each key is the element name and the value is its configuration.
Prefer the typed iws.Pipeline builder for construction-time validation and IDE autocomplete — it serializes to the same config shown here. Raw dicts (as above) are accepted too.

Waiting for pipeline completion

Getting pipeline results

Data references in pipelines

Use these prefixes to reference data sources in pipeline configs:
For inline DataFrames in pipeline configs, there is a 1,000-row limit. Upload larger datasets as measurements first, then reference them with db:measurement-id.
The folder: scheme expects a directory containing time_series and steps files. Both .parquet and .csv are supported, and parquet is preferred when both are present. For example, a folder with time_series.parquet and steps.parquet (or .csv) loads correctly.

PyBaMM model support

Pipeline configs accept PyBaMM model objects directly. The client auto-serializes them before sending:

Running simple pipelines

For pipelines that contain a single data fit or a single validation step, use client.simple_pipeline instead of client.pipeline. A simple pipeline is a lightweight, fire-and-forget alternative: you submit one config and the server runs it end-to-end as a single job, returning a flat parameter_values result.

When to use simple pipelines

Simple pipelines require a project_id. Set the IONWORKS_PROJECT_ID environment variable (or pass project_id= to Ionworks(...)) to configure a default project, or pass project_id= explicitly on each call.

Submitting a simple pipeline

Prefer the typed iws.SimplePipeline form for construction-time validation and IDE autocomplete (e.g. cost=iws.costs.RMSE()). It serializes to the same config shown here.
The elements dict may contain at most one data_fit, array_data_fit, or validation element. Helper entries such as entry elements are allowed and are evaluated before the fit.

Accepted element_type values

Each element’s element_type accepts the canonical wire values below. For backwards compatibility, configs authored against earlier versions of the app may also use the legacy display labels in parentheses — the server normalizes them to the canonical value before running the job. New configs should use the canonical values. An unrecognized element_type causes the job to fail with a ValueError listing the accepted values.
data_fit elements in simple pipelines are evaluated in parallel using the same distributed worker pool as regular pipelines. No extra configuration is required — set optimizer.population_size as usual and the server fans the population evaluations out across workers.

Execution options

Pass an options dict to create to control runtime execution behavior for the submitted pipeline. Options are submission metadata — they affect how the server runs the job but are not stored as part of the pipeline config.
You can also embed options (along with project_id, name, or description) directly in the config dict — create lifts them out of the config before submission. Arguments passed explicitly to create take precedence over values found in the config.

Waiting for completion

wait_for_completion polls until the pipeline reaches a terminal status (completed, failed, or canceled) and returns the final record.
For validation runs, the result also contains a summary_stats block alongside parameter_values. If the pipeline does not finish within timeout, a TimeoutError is raised. If it ends in failed and raise_on_failure=True (the default), an IonworksError is raised with the server-side error message.

Listing, filtering, and sorting

list returns a paginated response with items, count, and total. String filters accept either an exact value or an operator-prefixed expression such as ilike.%foo% (case-insensitive contains) or in.(completed,failed) (match any of a set).

Updating, cancelling, and deleting

Handling errors

Managing studies

Use client.study to create, list, update, and delete studies. Studies are scoped to a project. All client.study.* methods accept project_id as an optional keyword argument. When omitted, they use the default project configured on the client (or resolved from IONWORKS_PROJECT_ID). Pass project_id= explicitly to override on a per-call basis.

Listing studies

Supported filters: name, name_exact, order_by, order.

Getting a study

Creating a study

Updating a study

Assigning simulations and measurements

Deleting a study

Managing protocols

Use client.protocol to validate UCP protocols.

Validating a protocol

Finding input references

Find input[...] placeholders in a protocol string, useful for building experiment parameter forms.

Converting UCP to a vendor protocol file

Use client.protocol.convert to translate a UCP YAML protocol into the native file format used by a commercial cycler. This is the reverse of the commercial protocol upload flow — start from a protocol designed in Ionworks and produce a file you can run on hardware. Supported targets: maccor, arbin, neware, biologic_bttest, novonix.
ConvertResult exposes:
  • primary_bytes — raw bytes of the primary protocol file.
  • text(encoding="utf-8") — decode primary_bytes to a string.
  • save(dir) — write every output file (primary plus any sidecars) into dir and return the list of paths written.
Maccor protocols that include drive-cycle steps produce one or more .MWF waveform files alongside the primary .000 file. Use result.save(dir) so every sidecar lands next to the primary protocol — handling only primary_bytes drops the waveform files and the protocol will not run on the cycler.
Some UCP features map cleanly across all formats, but each vendor has its own syntax and limitations (see Differences between commercial protocols). If a UCP construct can’t be expressed in the target format, the conversion returns an error naming the unsupported step (see Export-time validation for the specific features each target format rejects). Validate the output by reuploading it through the commercial protocol flow before running it on a real cycler.
You can find the ID for any resource from the Ionworks Studio web app. The ID is displayed in the URL when you navigate to a resource’s detail page.

Next steps

Simulations

Learn about running simulations in Ionworks Studio.

Protocol reference

Full reference for the Universal Cycler Protocol format.

Uploading data

Upload and manage cell data via the Python API.

Build API

List and retrieve models and parameterized models.