- 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: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
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
Fitting from Python
The same fits available in the UI can be submitted programmatically throughclient.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 thationworksdata can detect:
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 owninitial_soc so the fitter starts each segment from the correct state of charge:
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:- Per-measurement
capacityis 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.capacityis ignored. When they’re not, the shared value applies to every segment (or capacity is estimated / fit againstbounds_capacitywhen the shared value is also omitted). - The returned
FitResults.capacity_Ahis a list with one entry per measurement segment. When a single cell-wide capacity was used (estimated, fitted, or supplied viaecm_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.
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 viaecm_options.ocv_soc_curve to skip OCV fitting and (optionally) co-optimise capacity within explicit bounds:
ocv_soc_curve.socmust be strictly increasing and lie in[0, 1].ocv_soc_curve.socand.ocvmust have the same length (≥ 2).bounds_capacityis only consulted whencapacityisNone; it requireshi > 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 viaecm_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: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:
Validating on held-out data
Once you have a fitted ECM, useclient.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 returnedValidationResults 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
- Upload measurements to a project so you can fit them in place
- Create a Parameterized Model with your fitted parameters
- Learn about ECM and other model types available in Ionworks Studio
- Explore the data format requirements for uploading cycling data