Skip to main content
The ECM Parameterization tool fits an equivalent circuit model (ECM) to experimental battery cycling data directly in the browser. Fit a measurement that you’ve already uploaded to a project, upload your own file, or use one of the built-in example datasets to extract cell capacity, OCV, R0, and RC-pair parameters as functions of state of charge (SOC). There are two ways to launch the tool:
  • Inside a project — open the ECM Fitting page from the project sidebar. You can pick a measurement that’s already attached to one of the project’s cells and the result is saved back to the project.
  • Standalone demo — visit studio.ionworks.com/ecm-demo directly. No login is required, and you can experiment with example datasets or upload a one-off file without saving anything.

How it works

The tool fits a circuit consisting of an open-circuit voltage (OCV) source, a series resistance (R0), and one or more RC pairs to time-series voltage and current data. The fitting process extracts parameters as smooth functions of SOC, and co-optimises the cell’s usable capacity together with the RC parameters using the fitted OCV(SOC) curve as a constraint. The circuit structure looks like this:
Each RC pair captures a different timescale of dynamic polarization behavior. More RC pairs produce a more accurate fit but also increase model complexity.

Capacity co-optimisation

Cycling data often doesn’t reflect the cell’s exact usable capacity — measurements are taken at different temperatures, C-rates, and ages, and small errors in the assumed capacity bias every SOC-dependent parameter that follows. To avoid this, the fit co-optimises the cell’s capacity alongside the RC parameters, using the OCV(SOC) curve as a self-consistency constraint: SOC at any time is computed from the integrated current divided by the fitted capacity, and the OCV at that SOC must agree with the rest-voltage segments of the data. The fitted capacity is returned in the fit response, so you can use it directly when building a parameterized model without having to estimate cell capacity separately.

Fitting a measurement in a project

Use this workflow when you want the fit to be associated with a specific project and cell, and to use a measurement you’ve already uploaded.
1

Open ECM Fitting from your project

Open the project, then click ECM Fitting in the sidebar. The page lists the cells in the project and the measurements attached to each one.
2

Pick one or more measurements

Select the cell measurements you want to fit. A preview plot of the voltage and current traces is shown so you can confirm it’s the right data before running the fit.Only time_series measurements with voltage, current, and time data can be fit. Properties and file-type measurements aren’t shown in the picker.You can select multiple measurements to fit them jointly as a single ECM. This is useful when each measurement covers a different part of the operating window (for example, separate pulse trains at different SOCs or on different cell instances). The fit treats each measurement as its own segment and shares a single set of SOC-dependent parameters across all of them.
3

Configure and run the fit

Set the number of RC pairs (0–5) and toggle Fit OCV as described in Configure the fit.When you select two or more measurements, you must enter an initial SOC (0–1) for each measurement in the configuration card. This tells the fitter where each segment starts on the SOC axis so it can stitch them together. Capacity remains a single value shared across all selected measurements (leave blank to estimate from the data). For a single measurement, the initial SOC field stays optional and is estimated automatically when left blank.Click Parameterize ECM to start.
4

Save the result to the project

When the fit completes, review the results and click Save to attach the fitted parameter set to the project’s cell. Saved fits appear in the cell’s measurement history and can be used as a starting point when creating a parameterized model.

Using the tool

The standalone demo at studio.ionworks.com/ecm-demo — and the fit configuration step inside a project — share the same controls.
1

Select your data

Choose from built-in example datasets or upload your own cycling data file. (Inside a project, you instead pick a measurement attached to one of the project’s cells, as described above.)Built-in examples include cells from published literature (Chen 2020, Ecker 2015, Prada 2013, and others) as well as drive-cycle profiles (UDDS, mixed current). Each example shows a recommended number of RC pairs.Uploaded files are automatically detected and parsed. The tool supports common cycler formats including CSV, Excel, and formats from BaSyTec, Maccor, and Biologic. Your file must contain time, voltage, and current columns. If an Open-circuit voltage [V] column is present, you can use it directly instead of fitting OCV.
2

Configure the fit

Set the number of RC pairs (0–5). More RC pairs capture faster dynamics but increase complexity. The recommended value depends on your data — example datasets show a suggested count.Toggle Fit OCV on or off. When your data includes a measured OCV column, you can disable OCV fitting to use the provided values directly and only fit R0 and RC parameters.
3

View results

After fitting, you see:
  • Model vs. data voltage comparison plot and RMSE
  • OCV(SOC) and R0(SOC) parameter curves
  • R_rc(SOC), C_rc(SOC), and τ_rc(SOC) curves for each RC pair
The fitted cell capacity, co-optimised from the OCV(SOC) curve, is returned in the fit response.
Full RC-pair parameters require ECM results access to be enabled for your organization. Contact [email protected] to request access.

Downloading results as CSV

After a fit completes, click the Download CSV button in the results header to export the fitted parameters. The CSV contains 200 interpolated SOC points with these columns: Columns for each fitted RC pair follow this pattern (e.g. R_rc_1, R_rc_2, …).
RC-pair columns are included only when ECM results access is enabled for your organization. Otherwise the CSV contains SOC, OCV, and R0 only. Contact [email protected] to request access.

Data requirements

Your cycling data must include:
  • Time [s] — time in seconds
  • Voltage [V] — terminal voltage
  • Current [A] — applied current
Optionally, include Open-circuit voltage [V] to skip OCV fitting and use measured OCV directly.
The tool uses ionworksdata for format detection, so data exported from common cyclers is usually recognized automatically.

Fitting from Python

The same fits available in the UI can be submitted programmatically through client.ecm in the Python API client. Authenticated fits run as background jobs — each fit_* call returns immediately with a job handle, and wait_for_completion blocks until the result is ready (typically 10–60 s). Three input modes are supported:

Fit from stored measurements

result is a FitResults model with time, data_voltage, model_voltage traces, soc/ocv/r0 parameter grids, and rc_pairs[i].r/.c/.tau curves for each RC pair.

Fit from a local file

Accepts CSV, parquet, and any cycler format that ionworksdata can detect:
To preview a file before fitting (auto-detect format, return its time-series without running a fit), call client.ecm.detect_and_read(file).

Multi-measurement fits with per-segment SOC seeds

When you fit multiple measurements jointly, each segment can carry its own initial_soc so the fitter starts each segment from the correct state of charge:
When initial_soc is omitted and an ocv_soc_curve is provided in ecm_options, the service auto-seeds soc0 by inverting V[s] = OCV(soc0) − I[s]·R0(soc0) after a warm-up fit. Without a curve, single-measurement runs fall back to coulomb-counting.

Per-measurement capacity

When each measurement was recorded on a cell with a different known capacity — e.g. measurements taken at different ages, or on different physical cells you’re fitting jointly — attach the capacity directly to each measurement dict:
Rules:
  • Per-measurement capacity is all-or-none — either every measurement supplies one, or none of them do. Mixed configurations are rejected at submission time.
  • Each capacity must be > 0 (Ah).
  • When per-measurement capacities are provided, the shared ecm_options.capacity is ignored. When they’re not, the shared value applies to every segment (or capacity is estimated / fit against bounds_capacity when the shared value is also omitted).
  • The returned FitResults.capacity_Ah is a list with one entry per measurement segment. When a single cell-wide capacity was used (estimated, fitted, or supplied via ecm_options.capacity), that value is repeated across segments so the shape stays consistent.
Fitting capacity (via bounds_capacity) still produces a single cell-wide value shared across segments. Per-measurement capacity is for cases where you already know each segment’s capacity and want to hold each one fixed.

Smoothness regularization

ecm_options.regularization applies a Gaussian smoothness prior to the R0 / RC parameter curves (never to OCV). Increase it to damp oscillations in the fitted SOC-dependent parameters when your data doesn’t tightly constrain them — for example, noisy pulse data or short traces that only cover a narrow SOC window.
For regularization > 0 the value maps internally to scale = 5 / regularization, so 1.0 is a modest prior and larger values apply a stronger smoothness penalty. 0.0 (the default) is special-cased to disable the prior entirely — no smoothness penalty is added and the scale = 5 / regularization formula is not evaluated (so there is no division by zero). The same option is available on fit_from_file(..., regularization=...).

Fitting capacity from a known OCV(SoC) curve

If you have an OCV curve from a separate slow-rate characterisation, pass it via ecm_options.ocv_soc_curve to skip OCV fitting and (optionally) co-optimise capacity within explicit bounds:
Constraints validated locally before the request hits the wire:
  • ocv_soc_curve.soc must be strictly increasing and lie in [0, 1].
  • ocv_soc_curve.soc and .ocv must have the same length (≥ 2).
  • bounds_capacity is only consulted when capacity is None; it requires hi > lo.
  • Mutually exclusive with input data that already carries an Open-circuit voltage [V] column — pass one or the other.

Tuning knot resolution

For challenging traces (long relaxations, multiple time scales), bump the SOC-knot resolution via ecm_options:
knot_schedule must be a strictly increasing list of positive ints ending at num_knots. Defaults are auto-derived when omitted.

Save a fit as a Parameterized Model

Once a fit completes, persist it inside a project so it can be used in simulations:
The returned parameterized_model_id can be used as the parameterized_model in client.simulation.protocol(...). See Parameterized Models for more.

Fit a built-in example without auth

fit_from_example is rate-limited (60/min) and synchronous — no job polling needed:
RC-pair parameters are only included for authenticated callers with ECM results access enabled.

Validating on held-out data

Once you have a fitted ECM, use client.ecm.validate(...) from the Python API client to check how well it reproduces a held-out load case — a measurement, rate, or drive cycle the fit did not see. The call re-simulates the fitted model forward on the held-out current trace using the same engine the fit uses internally and returns aligned model-vs-data traces plus error metrics. The call is synchronous (no job, no pipeline) and is the right tool for ECM held-out validation — don’t route an ECM through a validation pipeline for this.

When to use it

  • After a fit, to gate whether the model is accurate enough for the application.
  • To compare a saved parameterized model against a new measurement at a different rate or drive cycle.
  • To produce a model-vs-data overlay and residual plot for a report.

Inputs

Provide exactly one held-out source and exactly one model source: Optional arguments:
  • start_step, end_step — inclusive step bounds applied to the held-out measurement.
  • initial_soc — known SOC (0–1) at the start of the held-out trace. When omitted it is recovered from the trace’s first voltage via the fitted OCV(SOC) curve (assumes the trace starts near rest); pass it explicitly if the trace starts mid-load.
  • capacity — cell capacity [Ah] used for SOC integration. Defaults to the fit/model capacity (the SOC reference the curves were fitted against); it is never re-estimated from the held-out trace.

Example

Results

The returned ValidationResults object carries error metrics plus aligned, downsampled traces ready to plot as a two-panel (overlay + residual) figure: A typical plot overlays model_voltage and data_voltage against time in one row, with residual_mV against time in a second row sharing the x-axis:

Next steps