ECM fitting with regularization and per-cell nominal capacities, ArrayDataFit through the JSON config path, and near-instant measurement deletion
ECM fitting: regularization and per-cell capacities
Studio’s ECM fit adds two options. A regularization setting smooths the fitted parameters, and a per-measurement capacity lets you set a known nominal capacity for each measurement in a fit that spans several measurements of the same cell. Capacity fitting is now opt-in, and each fitted measurement reports its own capacity.ArrayDataFit through the JSON config path
iws.ArrayDataFit — fitting the same model independently at each value
of an independent variable (e.g. diffusivity vs. stoichiometry from
GITT / pulse data, or a parameter vs. temperature) — is now a
first-class element_type: "array_data_fit" end to end. The library
and schema already supported it, but the config path (the only surface
the production API sees) previously collapsed it into a plain
DataFit. Array fits now round-trip through config, schema, parser,
executor, and results serialization, and Studio renders the array-
valued fitted parameters with a per-parameter scatter view reachable
from the parameter editor.Studio
Studio
Improvements
- Cell measurement deletion is now near-instant. The per-measurement storage layout is deterministic, so the file set to remove is now derived from the database record and removed in a single batched call, rather than a slow recursive folder listing.
- Missing or empty step data on a measurement now surface as a clear “data missing” error with a re-upload prompt in the UI, distinct from transient storage failures (which get a Retry button). Upload validation also rejects empty step sets, and the upload rollback cleans up orphaned storage files.
Pipeline
Pipeline
Improvements
initial_guess_sampleroniws.DataFitacceptsLatinHypercubeorUniformexplicitly, and unknown sampler / distribution / prior names and stray keys are now rejected at submission time with a clear validation error instead of a later runtime crash.
- Configuring an
ArrayDataFitwith a non-number-likeobjectiveskey now surfaces as a clear, actionable configuration error — the message is shown, no internal alert — instead of the opaque “An unexpected error occurred” path. The same improved error handling was applied broadly across data-fit, optimizer, sampler, metrics, and transform configuration, so user-correctable mistakes surface with an actionable message instead of a generic failure.
Python API
Python API
Improvements
client.ecm.fit(...)now accepts aregularizationoption and a per-measurementcapacityonFitMeasurementRequest(set on all measurements or none);FitResults.capacity_Ahreports one value per fitted measurement.- Submitting an
array_data_fitelement via the JSON config path now round-trips end to end (schema → parser → pipeline → results), so API clients get the same first-class support the library object path already had.
- Documentation examples fixed against the real API surface: the
resubmit endpoint is
POST /jobs/{pipeline_id}/resubmit(the documented/pipelines/{pipeline_id}/resubmitdoes not exist and would 404); theModellist response has nomodel_type/configfield (onlyclient.model.get(id)returns it);model.createconfig usestype, notmodel_type; simulate protocol examples use named steps + string end conditions;CellMeasurementBundleResponseis flat (bundle.name, notbundle.measurement.name).
Skills
Skills
Improvements
run-simple-pipelinesdocuments thearray_data_fitelement type alongside the standarddata_fit.manage-cells:cell_spec.createandcreate_or_getexamples now matchCreateCellSpecificationNested— aratingsobject (capacity,voltage_min,voltage_maxas{value, unit}Quantities) and per-slotcathode/anodekeys each holding aNestedComponentInputwith a singularmaterialdict. The previous body usedrated_capacity/voltage_range_dc/components: [...]fields that do not exist on the model and would have failed server-side validation.
Faster parallel data fits, name-based measurement lookup, Arbin subschedule/loop support, and clearer model and duplicate errors
Faster, more reliable parallel data fitting
Parallel data fitting has been rebuilt on a dedicated execution engine that drives optimizers, point evaluation, multistart coordination, and progress reporting more efficiently and reliably, with clearer error reporting when a fit fails.Name-based measurement lookup
client.resolve_measurement(cell_specification, cell_instance, measurement) resolves a measurement_id from human-readable names,
walking the spec → instance → measurement hierarchy with server-side
filtering at each level. Scripts no longer need to hand-walk three
list endpoints and repeat name-matching boilerplate just to get an id.
parameterized_model.create_or_get also lands, giving parameterized
models the re-runnable create-or-resolve behaviour the other cell
resources already had.Clearer errors for model failures and duplicates
Two opaque “An unexpected error occurred” cases — a fit whose model setup needs geometry the user didn’t supply, and a custom model with no discretisation recipe — now surface as a clearModelError naming
what failed. Separately, attempting to create a resource that already
exists now returns a 409 CONFLICT (with the existing id) instead of
a 500, so duplicate-creation attempts fail clearly instead of
erroring unexpectedly.Studio
Studio
Improvements
- “Save as template” for an optimization now builds the template server-side, copying an optimization’s saved config directly into the template.
- Completed validation/datafit results no longer sporadically show “Failed to load plot data.” for one of a pair of plots.
- Cycle-ageing experiments driven directly from stored measurement
data (
experiment="from data") now resolve their measurement references correctly, instead of failing later in the run.
Pipeline
Pipeline
Improvements
- A bare element-wise cost (
SSE/MSE/RMSE/MAE/Max) applied to a multi-variable objective now warns when variable lengths mismatch — e.g. a model-axis dQ/dV variable against a data-axis voltage variable — instead of silently broadcasting to a meaningless residual. - All 1-D interpolant calculations now accept a
"pchip"interpolator (monotone cubic), the right choice for sparse, order-of-magnitudeD(sto)tables such as half-cell GITT per-pulse diffusivity.
- The MSMR half-cell logistic value and derivative are now evaluated more robustly, so it can never overflow.
- Model configuration now rebuilds consistently across execution paths, so results agree regardless of how a run was launched.
- A custom model with serialised geometry/mesh now survives multistart runs reliably, fixing cases that previously failed to serialize.
Python API
Python API
Improvements
client.resolve_measurementandparameterized_model.create_or_get(both introduced above), plusModel.configfor inspecting a model’s stored configuration.- Passing a bare pandas/polars DataFrame to a schema
datafield (objectivedata_input,OCPDataInterpolant.data, the Arrhenius calculations’data) is now auto-wrapped correctly on serialization, instead of failing server-side validation with the opaque “Required field ‘data’ missing”.
Protocol Simulator
Protocol Simulator
Improvements
- Arbin protocols now support subschedules, counter loops, and temperature add-ins, so schedules that previously crashed on upload with “Unsupported step type: SubSchedule” now parse and simulate end-to-end.
- BioLogic
.mpssimulation fixes: the loop counter is off by one no longer (EC-Lab’sctrl_repeatdoes not count the first pass, so a loop now runsctrl_repeat + 1times), plus BCD/EIS support and drive-cycle fixes, each reproduced against the reported setting files before fixing. - User-correctable protocol and configuration errors across the Protocol Simulator and pipeline libraries now raise specific, actionable error messages instead of generic failures, so they surface clearly to the user.
Data Processing
Data Processing
Improvements
- The
process-datareader gotchas are now documented: selecting therecordsheet for multi-sheet Neware BTSDA.xlsxfiles, and current-unit handling — alongside the one-callread.time_series_and_stepsentry point.
GITTModel for diffusion-only fits, model downloads for pybamm-only users, full app-URL helpers, and clearer configuration error messages
GITTModel — a first-class diffusion-only model
GITTModel and HalfCellGITTModel are now first-class models in
ionworkspipeline (with matching ionworks_schema siblings). GITT
fits overwhelmingly use the same lightweight model rather than SPMe:
x-averaged particle diffusion per electrode, a single lumped ohmic
resistance, fixed OCPs, and no Butler-Volmer kinetics, electrolyte
dynamics, or thermal effects. Shipping it as a built-in model unblocks
server-side GITT fits and backs the new half-cell GITT fit template.Download ionworks-defined models for plain pybamm
Users who have onlyionworks-schema / ionworks-api — and not the
licensed ionworkspipeline package — can now obtain ionworks-defined
models (ECM, LumpedSPMR, the MSMR models, GITTModel) in a form
they can load and run with plain pybamm. A new endpoint builds the
model server-side (where the license lives) and returns a loadable
serialisation, exposed through the Python SDK.App-URL helpers for every routed resource
The SDK’sclient.urls grew from a single .measurement() method to
a full set of web-app link builders — project, model,
parameterized_model, optimization, pipeline, study,
simulation, cell_specification, cell_instance, and more — so
callers never hand-construct app.ionworks.com URLs from IDs. The
helpers are environment-aware, deriving the right host for whichever
API environment the client is configured against.Stricter, clearer pipeline configuration
Most user-driven errors inionworkspipeline now raise a clear
configuration error instead of a generic one, so configuration
mistakes — wrong field types, out-of-range values, missing keys — are
routed to a clear Configuration error for the user instead of
being treated as an internal error. Optimizer configuration is now
also validated up front: passing options meant for a different
optimizer now hard-errors at submission time instead of being silently
ignored.Pipeline
Pipeline
Improvements
- Objective- and variable-level cost scoping is now driven by a single source of truth mapping each objective to the variables it should compute. This lets a weighted Wasserstein cost (position-shifting dQ/dV) and a per-variable SSE cost be combined over one objective, with each cost explicitly scoped to the variables it should consume. Electrode balancing gained an option to emit dQ/dV on the model’s own full-window voltage axis so a weighted Wasserstein comparison can align peaks in voltage rather than on the data grid.
- Strict optimizer-option validation: unknown optimizer option keys (and method/option mismatches) are rejected at submission time, and unknown constructor options are rejected at runtime with an actionable message — the previous behaviour silently ignored them. The typed option wrappers for each supported optimizer (CMA-ES, PSO, Differential Evolution, XNES, Bayesian Optimization, SOBER, TuRBO) remain the recommended way to pass options.
- Failure handling across the fitting and design-optimization paths is now unified onto a single constant, so the two paths can no longer drift apart and failures are better-conditioned for surrogate-based fits.
- ECM coulomb-count capacity reference is now computed per segment. Multi-measurement fits previously accumulated the cumulative integral across concatenated segment boundaries, inflating the capacity estimate to roughly the sum of per-segment throughputs and triggering spurious capacity-sanity-check warnings.
- A custom
geometrywith symbolic bounds is now correctly restored before the simulation is built, instead of arriving in a form that choked the solver. - Custom models now correctly honour their serialised mesh and geometry settings, instead of having them silently rebuilt from defaults.
Python API
Python API
Improvements
client.model.download/serialize(introduced above) return ionworks-defined models in a plain-pybamm-loadable form.client.urls(introduced above) now builds links for every routed resource, environment-aware.
Global search with ⌘K, new Bayesian / TuRBO / SOBER optimizers, faster ECM parameterization, inline image previews for file measurements
Global search across the platform
A⌘K dialog now searches across projects, cell specifications,
cell instances, cell measurements, pipelines, datafits, simulations,
optimizations, and parameterized models — with grouped, deep-linked
results and per-entity-type chip filters. Cell measurements and
instances are indexed via server-side full-text search, so a partial
name or id from any of these surfaces lands on the right detail page
in one keystroke. The search dialog supports filtering and paging
results server-side.Bayesian Optimization, TuRBO, and SOBER for parameter estimation
Three surrogate-based optimizers ship inionworkspipeline:BayesianOptimization— sequential or batch BO with (log-)Expected Improvement and a feasibility-weighted acquisition for constrained problems.TuRBO— trust-region BO with Thompson sampling and constraint handling.SOBER— batch BO via Bayesian quadrature with prior-aware importance sampling.
BayesianOptimizationOptions,
TuRBOOptions, SOBEROptions schema, and a new method-selection guide
in the docs explains when to reach for them over Nelder–Mead, CMA-ES,
or differential evolution.ECM parameterization runs as a background job
Authenticated ECM fits now run as background jobs instead of blocking on a synchronous request for 10–60 s.POST /ecm/fit-from-file and
POST /ecm/fit-from-measurements return 202 {job_id, status}; the
public demo POST /ecm/fit stays synchronous so unauthenticated
example fits still complete in one round-trip. The new client.ecm
Python SDK sub-client covers all three input modes — fit_from_example
(sync), fit_from_file and fit_from_measurements (returning an
EcmFitJob with wait_for_completion(...) polling), plus
save_to_project and detect_and_read — and a new ecm-fitting agent
skill walks an agent through picking a mode, running the fit, and
persisting it as a parameterized model. Solver errors from user data
now surface as clear, actionable API errors instead of generic
failures.Inline image previews for file measurements
File-type cell measurements used to render a “Visualization not yet supported” placeholder; the measurement detail page now fetches every attached file, renders images inline (filling the column with a click-to-expand lightbox, Esc or click-out to dismiss), and offers a download link for any file type. The detail page also no longer fails to load forfile and properties-type measurements that don’t have
time series data.Studio
Studio
Improvements
- Optimizations get a lighter-weight
/optimizationsREST surface (list, get, config, metadata, runs, statuses, cancel, resubmit, delete), and the optimization list page now polls a lightweight status projection every 5 s for faster, more efficient updates. The parameterized-model selector also fetches by id rather than scanning a larger cache. - A project-scoped parameterized model listing lets the parameterized-model picker filter to models that belong to the current project.
- Internal indexing helper fields are hidden in the object-fields panels so detail views no longer surface implementation details.
- Datafit results now surface “Validation not supported” as an inline alert when applicable, instead of leaving the validation tab blank or failing the page.
- Protocol files that pause or end on a non-error stop condition now render a user-correctable inline message; previously the route returned a generic error.
- Errors raised internally are now consistently converted into structured error responses across simulation and datafit result endpoints.
- The Universal Cycler Protocol simulator pages now list Arbin and Novonix alongside Maccor, Bitrode, and BioLogic as supported cycler protocol formats, and the supported-protocols copy is shared between both UCP pages so the two stay in sync.
- Data grid cards now claim an intrinsic width, fixing collapsed-grid layout issues when the parent container had no explicit width.
- Measurement-file uploads to storage now retry on transient errors with capped exponential backoff and a clear error once attempts are exhausted.
- Pipeline list and detail views are more robust to out-of-order responses, so navigating between pipelines during a slow request no longer reverts the view to a stale pipeline. Pipeline-elements caching and background polling were also hardened against stale-data races.
- The measurements list resets to page 1 at render time when the parent entity changes, removing the flash of stale rows that appeared while a new request was in flight.
- Org-context resolution on hard refresh is now deterministic — the active project no longer briefly reverts to the first project in the list before the persisted selection loads.
- Dark mode now derives selection, focus, and hover colors from the Ionworks brand pink so the focused row, selected nav item, and hovered button no longer look muddy against the dark background.
- Validation plot axis titles render correctly with the latest charting library version.
- The cell card on the cell detail page no longer shows redundant metadata fields that duplicated the breadcrumb.
- The all-measurements page now loads cell specs on cold/direct navigation so the spec-name and spec-anode/cathode columns populate on first paint instead of only after navigating in from elsewhere.
Pipeline
Pipeline
Improvements
CycleAgeingdefaults to a unified experiment model when an experiment is supplied, and compiles by default in that mode. Cycling experiments repeat the same handful of steps many times, so this collapses build and solve cost, giving a substantial speedup for cycle-ageing fits. Pinned to PyBaMM 26.6.1.0.CycleAgeingacceptsexperiment="from data", which builds the cycling experiment from the loaded dataset instead of requiring the user to restate it.CycleAgeingautomatically skips storing intermediate-cycle data when every requested metric only needs first/last-cycle quantities.save_at_cyclesonCycleAgeingis now auto-derived from the requested metric tree when the caller does not pass one explicitly — only the cycles that downstream metrics actually consume are saved.ElectrodeBalancingemitsdQ/dVcurves alongside the existing capacity outputs, so weighted costs can be computed directly against the dQ/dV peak structure.- The
Timemetric accepts a vector of times and reports the metric at each one, replacing the previous one-scalar-at-a-time loop in callers that needed a few sample points. - Solver options can now be passed through to every objective, complementing last week’s solver options on the constructor side.
SimplePipelineis a new pipeline mode with a client-side validator that rejects configs containing more than one expensive element (DataFit,ArrayDataFit,Validation), mirroring the server-side guardrail.
- An unsupported preprocessing option is now rejected at config time when passed in objective options, matching the runtime ban and giving a clearer config-time error.
Python API
Python API
Improvements
client.electrolyte.transport_from_dataset(dataset_id, forms=, columns=)turns a material property dataset into apybamm.ParameterValuesof concentration-dependent transport functions ready to hand toiws.direct_entries.DirectEntry(parameters=...). Two function forms are supported per property: tabulated interpolation (default) and a Landesfeind–Gasteiger isothermal exponential fit, which stays positive and finite below the lowest measured concentration so high-rate DFN solves don’t fail when the electrolyte depletes.Quantityconstructors accept PyBaMM-style unit strings and normalize them on input, so values copied from a PyBaMM parameter set round-trip into and out of cell schemas without a manual unit rewrite.JobClient.get_parameter_trace(job_id)returns the parameter- evaluation trace from an optimization job as a DataFrame for inspection or downstream plotting.client.ecm(introduced above) is the new ECM sub-client.
- POST and PATCH calls retry on transient connection drops with the same capped-backoff policy already used for GETs, removing spurious connection errors during long-running uploads against a flaky link.
Data Processing
Data Processing
Fixes
- A constant-current discharge segment with the unsigned mixed-mode sign convention no longer mislabels the step direction, and the matching CC-discharge classifier no longer reverses the sign on file round-trip.
Protocol Simulator
Protocol Simulator
Improvements
- Arbin protocols with a
SIGN(...)or step-time piecewise-current formula now parse correctly and emit the expected step plan; the previous parser failed on the conditional with a generic syntax error. human_readable_protocol(...)renders drive-cycle steps in the same shorthand notation the simulator uses elsewhere, instead of expanding them inline.
- Pause and end stop reasons now surface as user-correctable inline errors instead of being treated as solver failures.
Skills
Skills
Improvements
- The
parameterizeskill gains a current-driven fit template and a full-cell OCV template, each with an objective / cost decision tree so an agent can route an incoming dataset to the right starting configuration without re-deriving the choice every time. - A new
electrolyte-transportSDK skill documents theclient.electrolyte.transport_from_dataset(...)workflow, including the interpolant vs. Landesfeind-exponential trade-off and theDirectEntryintegration pattern. - A new
ecm-fittingSDK skill walks through the three ECM input modes (example, file, measurements) and the save-to-project flow. - The
parameterizeskill explains the component/material model and the material → cells reverse lookup so an agent can find which cell specs reference a given material before editing it.
Brand-aligned theme refresh, semantic zoom on validation plots, new data agent skills, tunable solver options with PyBaMM 26.6 support
Brand-aligned theme refresh
Studio now follows the Ionworks brand guide. Pink (#FF87B7) drives primary
CTAs, selection, focus, and active nav/tabs; green-black (#020E0D)
anchors text and neutrals; blue (#0C68E9) is reserved for
hyperlinks so links stay obviously clickable. Corners are sharpened
to 4px, typography is updated, and JSON viewers, plots, tables, and
ID chips have been re-skinned to match. All changes are
theme-level — no underlying behavior changes — so every screen
lifts at once.Semantic zoom on pipeline validation plots
Validation plots now fetch their data on demand and decimate server-side based on the visible x-range. Box-zoom into a region re-requests denser data for that window; a step-back zoom and a full-reset control are stacked in a zoom history.Tunable solver options with PyBaMM 26.6 support
ionworkspipeline simulations accept new solver options that merge
over the tuned defaults — e.g. enabling compilation for long
unified-experiment runs without restating the rest of the solver
configuration. It threads through every simulation-backed objective.
The workspace also upgrades to PyBaMM 26.6, with a compatibility layer
so historical and freshly-generated payloads both decode correctly.New data agent skills
Two new agent skills land this release:build-data-report
(multi-section markdown + PDF analysis covering rate capability,
DCIR, OCV, GITT, entropic, aging, and gap analysis) and
validate-data (a pre-upload gate covering header audit, schema,
and strict measurement validation).Studio
Studio
Improvements
- Cell-measurements list endpoints have been consolidated and now use server-side pagination across project, spec, and instance scopes, keeping the main list view fast even for large datasets.
- Deleting a project no longer shows a misleading “The project you are trying to access does not exist…” toast. The delete confirmation dialog also now requires typing the exact project name to enable the Delete project button, matching the destructive-action pattern used elsewhere.
- Signed-URL generation for measurement files now retries automatically on transient network timeouts, and file listing uses a single batched request instead of many parallel calls. File downloads also retry when the storage service returns an unexpected response under load, and surface exhausted attempts as a clear error instead of a generic failure.
- Cell-instance measurements grid no longer renders the previous spec’s rows after navigating between specs; the cell selector shows a loading skeleton and no longer stalls when an unrelated fetch is in flight; the ECM measurement selector switched to true server-side pagination instead of loading every project measurement into memory.
- The drive-cycles template list endpoint no longer errors at runtime, and now supports standard pagination.
- Fixed an autocomplete component bug where custom dropdown styling options were silently ignored.
Pipeline
Pipeline
Improvements
- A new fit option skips extra pre- and post-fit result-capture simulations that aren’t surfaced to the user, speeding up server-side fits by default; local users keep the previous behavior unless they opt in.
- Configuration errors are now classified more reliably, so the Configuration error UI path lights up correctly instead of being reported as a generic solver error.
Python API
Python API
Improvements
client.simulation.get_result()returns a typedSimulationResultobject withtime_seriesandstepsas DataFrames (polars by default, pandas whenset_dataframe_backend("pandas")is active) andmetricsas a plain dict, replacing the previous raw-dict response. Callers use attribute access and.columnsmembership checks instead of dict-key lookups.
Skills
Skills
Improvements
- New
sim-resultsSDK skill: fetching time-series and step data from a completed simulation, computing SOC via step-boundary cumulation, identifying step types by mean current, deriving DCIR from pulse steps using an OCV baseline plus onset current, and polars-aware plotting conventions. - The
parameterizeskill now documents electrode geometry (thickness, porosity, particle radius, AM fraction, maximum concentration) as a hard build requirement for DFN/SPMe — a physics-based model cannot be assembled without these structural parameters. Geometry lives on the cell spec’s components (not on a measurement), can come from teardown / metrology / vendor datasheet / literature, and DFN is no longer offered as “available” for Tier-2 cells that lack it.
Faster default simulation solver, structured error details on failed pipelines and optimizations, Wasserstein weighted mode and MSMRFullCell dQ/dU output
Faster default simulation solver
Simulations now default to a new solver that is a drop-in replacement for the previous PyBaMM-based solver, with substantially reduced per-step cost on supported model types and automatic fallback for models it doesn’t yet cover. Piecewise interpolation now also acceptssmoothing=0 so a hard step function can be modelled directly.Structured error details on failed pipelines and optimizations
Pipeline element and optimization failures now carry a structurederror_detail with the exception type and a link to the captured
diagnostic event. Two new job error codes — CONFIGURATION_ERROR and
SOLVER_ERROR — separate user-fixable config mistakes from
solver-side failures. In Studio, failed optimizations now show a
View diagnostic button (superadmin only) that opens the captured
event directly; the exception message itself is stripped before
serialization so user-visible diagnostics stay safe to share.Wasserstein weighted-point-cloud mode and MSMRFullCell dQ/dU output
iws.costs.Wasserstein gains optional position_variable and
weight_variable fields. When both are set, the cost computes one
Wasserstein-1 distance per objective comparing two weighted point
clouds — useful for full-cell MSMR fits where peak-location error in
Voltage [V] should be measured by the |dQ/dV| weights instead of
sample-by-sample. MSMRFullCell also now emits
Differential capacity [Ah/V] when listed in objective variables,
derived from Full voltage [V] / Full capacity [A.h] and
interpolated to the data voltage grid.Pipelines documentation moved to schema-first Docs section
The runnable “how do I actually run this” pipelines content has moved out of the Guide into a new schema-first Pipelines section under the Documentation tab, with every code sample rewritten to useionworks-schema + ionworks-api. The Guide retains the theory —
equations, parameter tables, intuition — and its existing “Pipelines”
group is renamed to Parameterization. The Japanese tab mirrors
the new section.Studio
Studio
Fixes
- Project-scoped ECM fitting from existing measurements no longer fails with a validation error: the frontend now sends the payload shape the backend expects for per-measurement initial SOC, and shows a per-measurement initial-SOC input next to each selected measurement.
Pipeline
Pipeline
Improvements
client.simulation.protocol(...)acceptsdesign_parametersagain as a flat dict — the single-simulation convenience that was accidentally removed when the protocol-template flow landed. Supplying bothdesign_parametersanddesign_parameters_doe, or a DOE that expands to more than one simulation, now raises explicitly instead of silently billing for the extra runs.- BioLogic
.mpsprotocols with large embedded drive-cycle tables (e.g. ~96k-row Urban Profile traces inlined as YAML block scalars) no longer time out when parsed via/protocols/parse-to-template. iws.direct_entries.DirectEntryaccepts apybamm.ParameterValuesdirectly. Callable values (concentration- / temperature-dependent interpolants) are serialized automatically and deserialized back into pybamm symbols so local and API consumption paths behave the same.
- Logging configuration now correctly governs all pipeline submodule loggers, so log-level settings apply consistently across the package.
Python API
Python API
Improvements
client.simple_pipeline.create(...)accepts aPipelineOptions(e.g.live_progress_updates=False), wiring this option through end to end from the SDK client.
- Outbound JSON payloads no longer raise
TypeErrorwhen a request body contains a pandas DataFrame with datetime columns.pd.Timestampis serialized viaisoformat()andpd.NaTbecomesnull.
Protocol Simulator
Protocol Simulator
Fixes
- BioLogic
.mpsparser no longer hangs on protocols likelfp_gr_cccv.mpswhere an internal sub-cycle pointer could be misread as a forward jump. Only genuine forward jumps emit gotos; backward or equal values are treated as plain step-ends.
Skills
Skills
Improvements
- Ionworks skills can now be installed as a Gemini CLI extension; the Coding agents docs page is updated to cover Gemini CLI, Cursor, and GitHub Copilot install paths alongside Codex and Claude Code.
- New half-cell MSMR template and helper scripts in the parameterize skill. The reference page mandates the template and lays out a discover → inspect → scaffold → dry-run → submit → validate workflow so every half-cell OCP fit uses the same canonical priors, multistarts, and method.
- The process-data skill now documents the platform’s actual current
sign convention (
positive = discharge), matches the validator and corresponding transform, and calls out the double-flip trap.
Tighter measurement-data validation, broader UCP-to-cycler conversion, Wasserstein distance cost function
Stronger measurement-data validation and processing
A new strict-mode check,capacity_energy_from_current_power, compares the
reported Discharge/Charge capacity [A.h] and …energy [W.h] columns against a
per-step trapezoidal integral of Current [A] and Power [W], flagging
row-by-row mismatches (10% default tolerance) so a transient mid-step error that
later cancels out is still caught. When the reported charge/discharge columns are
swapped — common in half-cell exports — fix_swapped_charge_discharge_columns
detects and corrects the labels. The current-sign-convention check now weights
each step’s vote by the charge it actually passes (∫|I| dt) instead of its row
count, so a long near-zero-current voltage hold no longer outvotes genuine
discharge pulses and raises a false CURRENT_SIGN_REVERSED.Small-current coin- and half-cell data now processes end-to-end: rest-step
detection scales its threshold to the trace’s peak current (sub-mA currents are
no longer all classified as rest), the auto-flip retry drops stale
capacity/energy columns before recomputing, and caller-supplied Step count
labels survive sign correction. A new generic parquet reader uses the same
alias-based column detection as the CSV reader, and folder: data references now
accept time_series.parquet / steps.parquet (preferred over CSV when both are
present).Broader, validated UCP-to-cycler conversion
The UCP-to-Arbin and UCP-to-Maccor converters handle more end-condition and step types (variable / loop / compound ends, temperature ends, Maccor pause steps) and now validate up front, raising clear errors on features a target cycler genuinely cannot represent instead of emitting files that fail to re-parse.Wasserstein distance cost function
A new Wasserstein (earth mover’s) distance cost function is available for data fitting, comparing model output and data as distributions rather than point-by-point. Available in both the pipeline and schema packages.Studio
Studio
Improvements
- Protocols list loads dramatically faster: the experiment-templates list
endpoint now omits heavy JSONB columns by default (~7.5 KB vs 7.7 MB on 22
templates), with callers opting into
protocol_config,parameters_schema, and similar fields via?include=. - Failed pipelines can be resubmitted from the pipeline details page, which now shows an error banner that deep-links to each failed element; individual elements display an inline error alert.
- Material property dataset plots now have an always-visible vertical legend with units, positioned to the right of the plot.
- Filtering measurements by ID on the project data page now narrows the list —
the
idquery parameter was previously dropped silently, returning every measurement. - Material dataset upload no longer shifts column indices when a CSV has an unnamed leading column, and now requires every column to be named (with a clear error) instead of silently skipping unnamed ones.
- Project membership management, active-organization switching, and parameterized-model deletion now go through the backend API instead of direct database writes, so they behave consistently with the platform’s access controls.
Python API
Python API
Improvements
client.auth_check()andclient.whoami()verify which user and organization a configured API key resolves to, backed by a newGET /auth/healthendpoint — useful for debugging wrong-org (403) errors and confirming which key is active.
Protocol Simulator
Protocol Simulator
Improvements
- Maccor protocols with
SubRoutsteps survive UCP YAML round-trips: resolved subroutine steps are namespaced and written back into the YAML, and intra-subroutinegototargets resolve at simulation time, fixing theSubroutine '<name>' not founderror in the parse-then-simulate flow.
Skills
Skills
Improvements
- New
validate-dataskill guides agents through the measurement-data validation and column-fix workflow. - A Codex plugin manifest was added so the Ionworks skills package installs in Codex alongside Claude Code.
Material properties in Studio, native UCP simulation for design optimization, SimplePipeline workflow, global search endpoint
Material properties in Studio
A new Materials section in the project sidebar lets you create materials within a project and attach measured property datasets (CSV / parquet) to each one. Upload, plot, edit, re-process, replace, and delete are all wired up. The Python SDK gains read-onlyclient.material
and client.material_property_dataset sub-clients with list, get,
get_units, and get_data (returns a polars.DataFrame); the REST
surface supports signed-URL downloads, on-the-fly downsampling, and
x-range filtering. A new docs page covers the UI workflow and REST
endpoints.Native UCP simulation for design optimization
DesignObjective gained a backend="ucp" option that runs UCP protocols
natively inside the optimization loop instead of converting them first.
This preserves UCP features that the conversion dropped — dynamic loops,
conditionals, gotos, set_variable, subroutines — and avoids
per-iteration overhead. EIS steps are now rejected up front in design
optimization (with a clear error both in the frontend form and at the
backend), because the UCP backend does not yet support frequency-domain
steps; standalone simulations remain the path for EIS.SimplePipeline workflow
A new lightweight pipeline variant for configs with at most one expensive element (one data fit or one validation). The whole config runs end-to-end as a single background job instead of fanning out to child jobs. CRUD endpoints under/simple_pipelines (POST returns 202;
LIST supports filters; PATCH for name/description; cancel and delete),
plus a client.simple_pipeline SDK sub-client with create, get,
list, update, cancel, delete, and wait_for_completion.Global search API
NewGET /search endpoint performs prefix full-text + substring
search across projects, studies, simulations, models, parameterized
models, optimizations, optimization templates, experiment templates,
pipelines, cell specifications, and materials within the authenticated
organization. There is no frontend search bar in Studio yet — the
new docs page makes this explicit so you don’t go looking for one.Studio
Studio
Improvements
- Optimizations table: bulk Delete restored next to the existing
bulk Cancel action, gated by
optimization:delete, with a confirmation dialog that pluralizes correctly and per-row error toasts. - Protocol simulator: Download CSV button next to “Configure Plot” exports the full time-series plus step-level columns (cycle count, step number, protocol variables) expanded to match each time point, regardless of zoom.
- Time-series measurement plot: overlay multiple variables sharing the
same unit on either Y-axis via a
+button — unit-filtered dropdown, distinct color cycle per series, individual×to remove, and selecting a primary variable with a different unit clears incompatible extras. - ECM models now expose
Anode potential [V],Cathode potential [V], and their open-circuit counterparts so BioLogic three-electrode EWE / ECE control limits can be reproduced from a simulation. NewLFP/Li metalhalf-cell chemistry added to the parameter library and the cell configuration UI. - Hover tooltips standardized to 3 decimal places across all plots.
- EIS Nyquist plot renders as markers-only scatter (no connecting lines), with a slightly larger marker.
- Cell-spec cascade delete now batches storage-path deletion and parallelizes per-measurement folder deletes, so one transient failure doesn’t abort cleanup for the others.
- Storage downloads now retry transient errors with exponential backoff — fixes job failures on intermittent non-JSON error responses.
- A new endpoint returns the parsed contents of a job’s metadata blob, giving the Python SDK a path to large validation payloads that the legacy result endpoint could not reach.
- Simulation submission unified to a two-step pattern (parse-to-template then simulate-with-template). Removed several redundant older simulation endpoints.
- Simulation dedup: removed a session-specific identifier from the uniqueness key used to detect duplicate simulations, so the “simulation already exists” path actually triggers and duplicate rows stop accumulating.
- Measurement details: Cycles tab is visible again and the cycle
filter slider’s range is correct after the
Cycle number→Cycle countcolumn rename. - Measurements of type
propertiesorfilenow show an informational alert pointing to the details panel or the SDK instead of rendering empty time-series tabs.
Pipeline
Pipeline
Improvements
ionworks-schemais now the single validation boundary for parser inputs across the pipeline, improving consistency between the SDK’s schema classes and pipeline execution.- Standardized user-facing optimizer kwargs across all fitting
backends:
max_iterationsreplaces older per-backend names, andpopulation_sizereplacespopsizeon the differential evolution optimizer. Old names continue to work with aDeprecationWarning. - A transient protocol solver failure during differential evolution now lands on the finite-penalty path instead of killing the optimization. Protocol and configuration errors still surface as errors so static bugs remain visible.
pybamm.Experimentperiodandtemperaturenow round-trip correctly through serialization (fix shipped inpybamm 26.4.3). Experiment schemas accept the new field set (per-stepperiod,temperature,tags,description,direction,start_time,skip_ok; experiment-levelperiod,temperature,termination);durationalso accepts human-readable strings like"287 seconds".- SimplePipeline jobs run data fits in-process and now establish their own connection to the compute backend, so distributed evaluation actually fires; when that connection fails, the fit falls back to its in-process path. Legacy element-type labels are now canonicalized consistently at ingress.
Python API
Python API
Improvements
client.simple_pipelinesub-client for the new SimplePipeline workflow.client.protocol.convert(protocol, target)returns aConvertResultwithprimary_bytes,text(), andsave(dir)helpers — exports a UCP YAML protocol to a native vendor file (Maccor, Arbin, Neware, BioLogic BT-Test, or Novonix). Maccor returns any drive-cycle MWF assets alongside the primary file.client.job.get_metadata(job_id)returns the parsed contents of a job’s metadata blob, giving the SDK access to large validation payloads the legacy result endpoint could not reach.
Protocol Simulator
Protocol Simulator
Improvements
- BioLogic
.mpsparser: User Profile (drive cycle) steps are now extracted from embedded Urban Profile Tables, or from sibling.txtfiles supplied viaadditional_contentwhen the.mpslacks embedded tables. Current sign is flipped on the way in so positive represents discharge for UCP/PyBaMM. - Arbin parser rewritten to keep the step list flat with raw gotos
instead of inferring loops from backward-goto patterns. Fixes
sibling backward gotos to the same target, cross-loop goto
resolution, and digit-bearing formula labels like
F_EIS_10%_capacity_change. Pause steps emit UCP’s first-class auxiliaryPausestep. - More Arbin / Maccor step types recognized:
Arbin
Internal Resistance→Restwith aUserWarning, additional Arbin step variants mapped to their UCP types, bracketedMV_UD[n]normalised, leading-negative current expressions classified asDischarge. MaccorUser Def CYCLE <op> Ntranslated to a UCPVariableEndagainst the runtimeCYCLEalias. - Per-step overhead trimmed substantially on long protocols, speeding up simulation of protocols with many steps.
- Solver failures are now distinguished from protocol and configuration errors, which keep their original error types and gain step context.
- Real Maccor
.MWFexports that include a multi-line preamble plus a header row now parse correctly. Files containing only data rows still parse unchanged.
Skills
Skills
Improvements
- New
run-simple-pipelinesskill walks through the SimplePipeline client end-to-end. process-data: clarified thatprotocolholds test conditions that affect the electrochemical outcome (temperature, C-rate, SoC, DoD, pressure) whiletest_setupholds physical logistics (cycler model, operator, lab, channel) that do not.test_setuplives only on measurements, not on cell instances.process-data:set_step_countwith a step column is now the unambiguous default, so decreasing / repeating step ids from GITT or RPT-with-substeps work the same as monotonic ones; the sign-based fallback is reframed as a fallback for when no step column exists at all. Added a caveat for cyclers that emit duplicateTime [s]rows at step transitions.process-data: mandatory header-audit step codifies eight rules (walk every file, group by cohort × column-set, classify Standard / Auxiliary / Drop, diff reader output, preserve aux columns, keep multi-thermocouple channels separate, confirm units / sign per cohort, surface missing-temperature as a finding) and a required confirmation-report shape, so silent column drops between cycler families are caught before any standardized parquet is written.
Custom PyBaMM model + Li-S support, ECM capacity co-optimization, default project for the Python SDK, structured validation issues
Custom PyBaMM models with Lithium-Sulfur chemistry
The/models/upload-custom endpoint now accepts a chemistry field (defaulting
to lithium_ion), and Li-S models get more accurate and robust initialization
when they run. The manage-projects SDK skill documents the full upload
workflow — pybamm.Serialise().save_custom_model(filename=...) → multipart
upload → client.model.get(id) returns is_custom_model: true.ECM fit: capacity co-optimization and per-segment initial SoC
Several interlocking improvements to the project-scoped ECM fit. Supplying anocv_soc_curve (and optional bounds_capacity) lets you co-optimize cell
capacity Q jointly with the fit instead of pinning Q to a single seed; on
a 25 °C rate-test trace the fitted capacity now lands within 0.9 % of the
coulomb-counting truth across all knot schedules. initial_soc accepts a
list (one entry per measurement) so multi-measurement fits reset SoC at each
segment boundary instead of integrating coulombs across the gaps; if you omit
it, an improved auto-seed routine now estimates each segment’s starting SoC
automatically. num_knots, num_knots_r0, knot_schedule, and
clamp_max_ratio are now first-class parameters on /fit-from-measurements
and /fit-from-file. A boundary-clamp default was also loosened, fixing an
issue where it could collapse the R0 fit and cause solver failures on
rate-test forward simulations.Default project for the Python SDK
TheIonworks client now resolves a default project_id at construction time
from a project_id= argument or the new IONWORKS_PROJECT_ID environment
variable, so callers no longer have to thread project_id through every call.
The previous PROJECT_ID env var still works but emits a DeprecationWarning.
All client.study.* methods take project_id as an optional keyword
(after the resource ID) defaulting to the client value, and pipelines and
optimizations auto-inject it into payloads.Structured measurement-validation issues
MeasurementValidationError.errors is now list[ValidationIssue] — a frozen
dataclass carrying a stable IssueCode (StrEnum), severity, human-readable
message, and JSON-native payload. Downstream code can branch on check
identity via e.has_code(IssueCode.CURRENT_SIGN_REVERSED) instead of grepping
the message string. ionworksdata’s auto-fix path now keys off the new codes;
IssueCode and ValidationIssue are re-exported from the top-level
ionworks package.Studio
Studio
Improvements
- Simulation boards now have a dedicated backend API at
/projects/{project_id}/studies/{study_id}/simulation_boards, fixing a blank Visualization tab in some cases. - Optimization Performance Detail and Performance Summary tabs now surface
buried
validation_warning/validation_not_supportedissues as top-level alerts above the tabs, with info “no data” alerts inside the tabs for the rare empty-but-valid case. - Defensive UX in the Visualization tab: the Data/Visualization toggle stays visible even when no board is available, with a warning alert prompting the switch back to Data instead of trapping the user on a blank page.
- The single simulation result page no longer flashes “Simulation not found” before the data loads on a fresh navigation.
Pipeline
Pipeline
Improvements
ionworks-schemagainedConstraint,Penalty,CMAESOptions,PSOOptions,DEOptions,LatinHypercube, andUniformschema classes, plus improved documentation across objectives, data fits, parameter estimators, regularizers, and distribution samplers.
- Fixed an issue where a solver failure on a bad parameter combination during a fit could crash the whole datafit instead of being handled gracefully. Cloud fits stay alive and the offending sample just gets a huge cost.
Python API
Python API
Improvements
- New
client.urls.measurement(measurement_id, project_id)helper returns the web app deep link for a measurement, so callers don’t have to hand-build URLs themselves.
Skills
Skills
Improvements
manage-projectsdocuments the/models/upload-custommultipart workflow and the Model / ParameterizedModel disambiguation.upload-dataand other validation-aware skills updated to reference the newIssueCode/ValidationIssueAPI and thee.has_code(...)pattern instead of substring-matching error strings.
Full optimization experiment editor, Arbin reader, Maccor coverage, UCP input schema
Full editor for optimization experiments
Optimization experiments now use the same protocol editor as the rest of the app. The bare text field has been replaced with a rich editor featuring YAML syntax highlighting, dark-mode support, frontend pre-validation, and the full protocol-builder dialog for picking templates and tuning steps. New protocols pre-load a “Constant Current Charge” template so users have a working starting point.Iterative metrics for design optimization
Design optimization now supportsCyclewiseMetric and StepwiseMetric
wrappers end-to-end. The optimization form lets you target a metric on a
specific cycle or step with bounded input fields driven by the parsed
experiment, mix pipeline variables alongside PyBaMM variables, and
round-trips wrapped metrics through save/load. A long-standing bug where
repeated protocol blocks were flat-expanded has also been fixed, which broke
solution.cycles indexing for cycle-wise metrics. Two new templates ship: a
simplified Charge optimization and composite system models.Arbin cycler support
ionworksdata now reads native Arbin exports — CSV, XLSX, and the binary
.res format. The .res reader extracts data directly from Arbin’s export
format (no separate Access database tool required), sorts rows chronologically
to handle interleaved multi-session recordings, and reads the absolute start
time from the file’s session metadata. Auto-detection picks the right reader
from file headers, and arbin res is also exposed as an explicit reader name.Maccor protocol coverage
The Maccor parser and simulator now handle several real-world protocol features that previously failed at parse time or during simulation, including per-limit safety gotos,Chg/Dis Func CCCV step types, and robust variable
setvar handling. The Maccor ionworksdata reader also gained support for the
compact short-form column header set used by some firmware versions, which
previously crashed and silently dropped capacity/energy columns.Machine-checkable UCP input schema
The discovery endpoint/discovery/schemas/protocol now exposes a JSON
Schema matching the actual YAML authoring format (single-key dicts like
{Charge: {...}}) rather than the internal parsed shape. Parity tests
round-trip good and bad fixtures through both the schema and the parser so
they cannot drift. Submitting the legacy kind: shape to
POST /protocols/validate now returns a helpful error pointing at the
canonical YAML examples, and the discover-api and run-simulations skills
show local pre-validation via jsonschema.validate(...).Studio
Studio
Improvements
- The Ionworks Agent tab has been replaced with a static instructions page; the in-app chat agent has been removed in favour of the agent-skills workflow.
- New cell specifications no longer pre-fill a default capacity, so users enter the actual cell capacity from the start.
- Storage permissions are now enforced at the organization level so members of the same org can read each other’s measurement files as expected.
created_by_emailis now consistently populated on cell-spec, cell-instance, and cell-measurement responses across bothgetandlistendpoints.- Simulation usage is aggregated at the organization level (matching the
org-level usage limit that the backend already enforces) and is fetched
from a dedicated
GET /organizations/current/usageendpoint.
Pipeline
Pipeline
Fixes
- Half-cell ECM now exposes anode and cathode potential variables
(
Anode potential [V],Cathode potential [V]) for plotting and metrics. get_cycle_metricskeeps theCycle countcolumn name on output instead of renaming it toCycle number, matching the input convention used throughout the data pipeline.
Python API
Python API
Improvements
validate_measurement_data,CellMeasurement.create, andCellMeasurement.create_or_getaccept askip_checksparameter so callers can relax a single strict validator (e.g.time_gaps) instead of disabling strict mode wholesale. Unknown check names raiseValueError, and the canonical set is exposed asionworks.validators.STRICT_CHECK_NAMES.validate_strict=Trueis now the recommended default.
Data Processing
Data Processing
Improvements
- New Arbin reader covering CSV, XLSX, and native
.resexports (see the highlight above). - Maccor reader now accepts the compact short-form column header set used by some cycler firmware versions.
Documentation
Documentation
Improvements
- New electrolyte parameterization page with a worked Landesfeind fit example.
- Optimization experiment editor, iterative metrics, simplified Charge template, and composite system models are documented.
- Custom variables reference now documents anode/cathode potential exposure on the half-cell ECM (English and Japanese).
- Maccor native
CCCVstep type is documented (English and Japanese). - Arbin is listed in the supported cyclers table.
- SEO metadata (keywords, OG tags, tightened descriptions) added across the docs site, including expanded data-fitting guide descriptions.
Skills
Skills
Improvements
- Each mirrored package (
ionworksdata,ionworks-schema,ionworks-api,iwutil,ionworkspipeline,skills) now ships a per-packageCHANGELOG.mdin Keep-a-Changelog format, written and validated as part of the release workflows. discover-apiandrun-simulationsskills updated to reference the new UCP input JSON Schema and demonstrate local pre-validation.upload-dataskill updated to recommendvalidate_strict=Trueand document the newskip_checksparameter.