EIS upload validation
cell_measurement.create(...) now accepts a data_type="eis" hint on the
measurement dict. When set, validate_measurement_data runs a structural
columns check (always on, requires Frequency [Hz], Z_Re [Ohm],
Z_Im [Ohm]) plus two strict-only, individually-skippable heuristic checks.
eis_zim_sign flags a spectrum whose capacitive band is predominantly
positive — i.e. the raw Im(Z) sign is flipped, with the fix hint
Z_Im = -Z_Im. eis_impedance_magnitude catches order-of-magnitude unit
errors by comparing min(Z_Re) against a wide 100× band around a capacity-
derived estimate — no data fetch, just a sanity check against the supplied
rated_capacity. Both fire only on order-of-magnitude issues (a 1000× unit
error, a fully flipped sign) so a plausible spectrum is never touched. Under
the hood, the BioLogic reader now stores the raw imaginary part directly as
Z_Im [Ohm] (negative across the capacitive arc), matching the validator’s
convention.Faster pipeline detail page and ECM fits
Phase 1 load-time wins on the pipeline detail page: the bulk element endpoint no longer ships the multi-MBjob_config.parameters / cost / optimizer
for every element (those keys already hydrate lazily on expand), and the
frontend computeCumulativeParameters no longer re-runs O(N²) per render on
every 5s poll tick. Large element types (DATA_FIT / ARRAY_DATA_FIT /
VALIDATION) also stop double-storing their full objectives blob in both
storage and the pipeline_elements DB row on newly created pipelines — the
DB copy was never read. Separately, pipeline ECM fits reuse the fit’s own
V_model for the final voltage (dropping a full symbolic build + CasADi
compile), fit unknown initial SOC directly as an outer parameter (removing
the coarse warm-up fit), and gain a lossless O(N) fast path on
PiecewiseLinearTimeseries — all with bit-for-bit fit quality preserved.Studio
Studio
Improvements
- Protocol detail pages now show a Simulations section listing every simulation that uses the protocol, with the same bulk actions (add to study, rerun, delete) available on the parameterized-model simulation list.
- Pipeline bulk cancel is now instant. DB status writes stay inline so the UI flips immediately with optimistic patches + rollback, and the slow Anyscale/Ray job-termination is offloaded to the background task queue. A single bulk-cancel endpoint replaces the per-pipeline loop the frontend was previously doing.
- The Cycle Filter now clamps
First N,Last N, andRangevalues that exceed the number of available cycles: it returns all available cycles and showsShowing all N cyclesin neutral text. Explicit single-cycle typos (e.g.0,50,200on a 100-cycle measurement) still error, with a short, actionable message instead of the previous thousands-of-numbers wall of text. - Compute hours are now a first-class usage dimension alongside
simulation hours, driven by each org’s contract (
usage_limitcan holdsimulationand/orcomputekeys in seconds). The account drawer renders one meter per configured usage type, gated on a combined loading signal with placeholder cards sized to the last-known meter count, so the list no longer briefly collapses to zero at load.
- Deleting an organization as a regular Admin (non-super-admin) now returns a proper 403 Forbidden. Previously RLS silently blocked the delete but the endpoint returned 204, giving a false success while the org remained in the database.
- Current sign-convention documentation corrected across backend field descriptions, the API discovery endpoint, and the data-upload docs: positive = discharge, negative = charge (matching the platform’s actual data, the ionworksdata validators, and the AI step-filter agent prompt, which already used the correct convention). Descriptions of external cycler conventions that legitimately differ (e.g. BioLogic / Arbin native positive = charge) are unchanged.
Pipeline
Pipeline
Improvements
- Default population size for the DE and PSO optimizers is now
capped at 40. Explicit
population_sizevalues still bypass the cap; only the auto-scaled default changed, and only above the cap.
Pipeline.from_schema— the schema→runtime path used by local runs — now matches the server’s parser path in three places where it had drifted. The OCP interpolantmetadatakey defaults to{}(a{"data": df}input was previously rejected as missing themetadatakey). Transform classes (Log10,Log,Inverse, …) resolve fromiwp.transformsrather than top-leveliwp, so schema-provided transforms are no longer silently dropped. And the vacuous multistart guard (Multiple multistarts are being used, but all initial guesses are identical) that fired as a downstream symptom of those drops is gone as a consequence.
Python API
Python API
Improvements
- New
ionworks-mcppackage — a lightweight, read-only MCP (Model Context Protocol) server that exposes the Ionworks public API to MCP clients like Claude Desktop and Claude Code. It’s a thin wrapper over theionworks-apiPython SDK (auth, retries, caching and pagination inherited) with 15 tools spanning capability discovery, the cell hierarchy (specs, instances, measurements with time series, steps and cycles), and materials plus material-property datasets. Uses the sameIONWORKS_API_KEYenv var, launches over stdio, and mandatorily row- windows any DataFrame-returning tool so time-series calls never dump an unbounded payload (default 500 rows, max 5000,offsetpaging, optionalcolumnsprojection). Nothing is ever written or mutated. GET /organizations/current/usageis now public and returns per- dimension usage (simulation,compute) with limits, so SDK clients can read their own quotas without an admin token.
Data Processing
Data Processing
Improvements
- Neware BTSDA
.xlsxfiles with no explicitsheetsoption now auto-select therecordsheet — where the time series actually lives — instead of defaulting to the metadata-only first sheet and failing with a missingTimestamperror. The previous “you must passsheets={type: 'name', value: 'record'}” gotcha is now automatic; files without arecordsheet still fall back to the first-sheet default.
- The Maccor reader now maps
Cycle C— the cumulative cycle counter, the true cycle number — toCycle from cycler. Previously it mappedCycle P, a program/loop counter that is often0and can reset within a procedure, so any file containing both columns reported meaningless zeros for the cycle number.
Protocol Simulator
Protocol Simulator
Fixes
- Arbin schedules that reference a subschedule (
SubSchedulestep) no longer fail parsing withDuplicate step name found: 'End Test'. The reservedEnd Testterminal is exempted from the duplicate-name check — each subschedule keeps its own copy, so anygoto: "End Test"from any scope still resolves at simulation time. Genuinely-named block collisions (e.g. a userLoop_Xappearing in two scopes) still error as they should.