Raw data: drop a folder of cycler files, get measurements
A project now has a Data → Raw Data area that takes cycler exports as they come off the machine. Drop a batch of files or a zip on the upload page and each one becomes a record that is detected, parsed and — where the file’s name says which cell it belongs to — turned into a measurement without anyone typing a cell number.The parts worth knowing about:- Nothing has to be right first time. Files that need a human land in a review queue with the specific finding and a choice to make, rather than failing quietly. Attaching a record to a cell is one action from the row.
- A re-upload of the same bytes is refused before the upload starts, with a pointer to the record that already holds them. Identical content under a new name almost always means the first name was wrong, so records can now be renamed — which is the actual fix, since the cell and measurement names are read from the filename.
- Large archives upload directly, so a multi-hundred-megabyte export no longer dies partway through.
- A re-pulled export is a new snapshot, not an overwrite. A test that is exported again after another day of cycling keeps every earlier file exactly as it was; the snapshots group under a run so the history stays readable.
A test record now describes its own sections
Point the platform at a cycling record and it identifies what the test actually contains — a formation, a rate ladder, a pulse train, a stretch of cycling — and computes the headline numbers each of those is asked for, per occurrence.Several measurement conventions were tightened while this was built, and they change the numbers you get:- Capacity is named by direction. Charge and discharge are separate quantities and are now reported as such, with an explicit direction on every row rather than folded into a metric name. The same applies to capacity retention, which was silently a discharge-only number, and to pulse resistance, which was pooling charge and discharge pulses into one series.
- State of charge is bounded by the cutoffs, not anchored on them. A rate ladder is built from discharges that hit the voltage floor without emptying the cell, so treating the deepest one as empty put the pulse train that followed at a negative state of charge. Loads that end on a limit now bound the count instead of defining it — no threshold, nothing to tune.
Header metadata from every cycler, not just one
Every reader now extracts what its file’s header declares — operator, schedule or procedure name, channel, start time, cell identifiers — and translates it into one shared vocabulary, so Maccor’sProcedure, Novonix’s Protocol,
BaSyTec’s Testplan, Arbin’s Schedule File Name and Neware’s Step file all
arrive under the same field. Previously only Maccor carried a real header
through and everything else reported little more than a start time.The immediate payoff is that a measurement records the protocol it was run
under at upload time, with no extra parsing step.Protocols draw themselves
A protocol’s detail page gains a Flowchart view alongside the existing UCP, human-readable and vendor-format views. It draws the compiled protocol as a spine of step cards, with repeat loop-backs andgoto jumps in their own lanes,
blocks outlined with their repeat counts, and parameter references marked as
tokens. Step cards and edge conditions show their full detail on hover.Studio
Studio
- The lab status report can now be exported as a PDF. A Generate report button on the Lab wall opens a dialog to pick sections and tune the report’s windows, then downloads the result.
- Filter pills on data tables are multi-select. The enum filter on every server-filtered table is now a checkbox list that stays open while you toggle, showing up to three labels before collapsing to a count.
- Cell specifications are listed on a material’s detail page, including the component role each one uses the material in.
- The built-in material catalog grows from 22 to 30 materials, adding Verbrugge 2017 graphite, silicon (both directions), LFP, LMO and NMC, plus two Paul 2024 graphites — LFP and LMO being chemistries the catalog previously lacked entirely. Each arrives with both its fitted MSMR parameters and the OCV curve evaluated from them.
- A large burst of fits or optimizations no longer fails on submission.
Batch jobs beyond the compute provider’s rate limit now wait as
pendingand submit when capacity frees up, instead of being marked failed. - Cell specification and instance pages render nested JSON as nested, so a nested key is visually distinct from a sibling.
- The pipeline element drawer now shows the configuration an element actually ran with. A datafit could not show what it was fitting, and every Calculation element rendered an empty details panel with a generic header.
- Uploading a vendor protocol file and pressing Save failed with a message about YAML mappings — it was reading the raw vendor file rather than the converted protocol. Every vendor format was affected.
- Selecting a right-hand y-axis variable no longer resets the plot’s zoom.
- The pan tool stays selected after a pan, instead of the toolbar switching itself back to zoom.
- Tables on the cell specification page fill the viewport height instead of stopping at a fixed box.
- The two shipped system optimization templates could not be edited — the write path rejected the very form they ship with.
Pipeline
Pipeline
- The typed result object gains a
seriesaccessor giving the full-resolution model-vs-data channels per objective, alongside the decimatedoverlayused for figures.
- Long array fits no longer run out of memory partway through.
- A
Validationkeyed by a number (a temperature, a C-rate) emitted a configuration its own reload path rejected. - A fit whose every evaluation failed is reliably reported as failed rather than depending on the cost it reported.
- A composite stoichiometry window now requires its usable capacity at validation time rather than failing later at runtime.
Python API
Python API
client.material_property_dataset.to_prior(...)reads a scalar from a material property dataset and returns a prior centred on it, ready to drop into a fit. Width is supplied explicitly as either an absolute or a fractional standard deviation, with a lognormal option for strictly positive parameters spanning orders of magnitude.
- 33 schema classes that their packages defined but never exported are now
importable — every
*Optionscompanion was affected. A test now enforces that in both directions, so it cannot regress. - Fits whose posterior chains were too large to inline now work with
marginal(),credible_interval()and.x, which previously raised or returned nothing on exactly those fits.
Data Processing
Data Processing
- Maccor exports reporting milli-units (
Current (mA),Capacity (mAHr)) now read, with the scale applied on read. Previously they could not be read at all, and the obvious workaround — remapping the column name — produced values a thousand times too large with no warning. The cycler’s own DCIR column is carried through too. - The Maccor reader now carries the mode, end status, loop and register columns the cycler writes about its own execution. The mode column is the only thing distinguishing step-transition markers from genuine rest samples, and the register columns often hold the per-cell capacity a procedure used as its C-rate basis.
- The CSV reader tolerates a metadata preamble above the header and ragged rows below it — a trailing delimiter on every data row no longer aborts the parse.
Protocol Simulator
Protocol Simulator
DeltaSOCis now a first-class end condition. A protocol ending a step on a change in state of charge previously had that limit dropped silently, leaving an unbounded step that surfaced much later as an opaque “each step must have at least one termination condition” error. Because it stays relative, it resolves against whichever cell the protocol runs against rather than the one it was authored on.- Cell capacity is prefilled from the protocol file’s header where the file declares it, so a protocol’s C-rate steps resolve against the right cell instead of a 1 Ah placeholder. Units are read from the file rather than assumed.
- Three operator and end-type rules now warn instead of rejecting the protocol. A protocol imported from a real cycler file may legitimately contain any of them, so blocking was too strong. Validation and parse both report their findings, so nothing is lost by not blocking.
Cycler reading, measured against a public adversarial corpus
We ran every reader against the Battery Data Alliance parser test-fixture corpus — a published record that exists to test battery data pipelines and deliberately includes broken exports. 25 of its 28 files now read, up from 3, all with monotonic time axes. The three that still refuse are correct refusals rather than silent damage.The fixes matter beyond that corpus, because most of them were failures that produced plausible data rather than an error:- Arbin workbooks read their metadata sheet instead of the channel data sheet, making most workbooks unreadable, and one header dialect dropped the time axis itself while keeping voltage and current.
- Maccor exports using bracketed units (
Test Time [s],Current [A]) lost most of their columns, which surfaced much later as an unrelated-looking error from a fitting routine. A header carrying its own units also silently ate the first measurement. - BioLogic exports written in a European locale (decimal comma) failed before a single row was read.
A Digatron CSV reader
Digatron CSV exports now read directly. The file’s header declares its duration columns in seconds while writing milliseconds — trusting the label would give a time axis a thousand times too long — so the time axis is derived from the timestamp instead, and a duration column whose span disagrees with the wall clock is reported rather than swallowed.Arbin EIS sweeps are no longer dropped
Arbin writes impedance spectroscopy to a separate sheet, and nothing read it — a workbook could report as read while losing every EIS row, with no warning. Sweeps now come back spliced into the cycling data in test-time order as their own step, with time, voltage and current left null because a sweep is measured against frequency rather than the clock. Passinclude_eis=False to read the
cycling data alone.A protocol’s name is now checked against the protocol
1C/1C, 500 cycles over a 100-cycle protocol is a perfectly valid protocol with
a misleading name, and the name is the only thing most readers ever see — it
travels to the channel assignment, the lab report and the result set. Protocols
now get a check that reads the name against the protocol and flags which claims
are contradicted, with a suggested rename, surfaced while you are still typing.It deliberately says nothing when there is nothing to contradict: a codename like
ETR874 or RPT claims nothing, so it draws no warning.Plots fetch what they can actually show
Every plot surface now asks the server for the rows its pixels can represent, and hands its zoom back to the same route — so opening a chart over a large measurement no longer pulls down far more data than the screen can draw, and zooming in fetches the detail for the window you are looking at. Validation plots read from stored series the same way, so large fits stay responsive.A new Zero x-axis at view start checkbox on the measurement time-series tab relabels the axis from 0 at the left edge of the current view — zoomed into a pulse, the axis answers how long it lasted rather than where it sits in the file. It re-zeroes on every pan and zoom.Protocol detail shows the lab work it drives
A protocol’s detail page listed the simulations it produced but not whether it had actually been run. It now shows Simulations, Planned measurements and Measurements as one tabbed region with counts, each searchable, so “has this been run, and is anything queued against it?” is answered on the page.Measurements can also record the protocol they were run under, which is what links the two together — including as a filter when listing measurements.Studio
Studio
- Planned measurements can record a required temperature and thermal chamber, so a test that must run hot or cold carries that with it. No chamber means ambient. Scheduling itself is unchanged for now — a temperature can be set and read, but nothing schedules around it yet.
- The Test Scheduler’s search box now searches the whole backlog on the server, not just the rows already on screen, and matches the protocol, cell spec, program and channel names shown in the columns rather than only the underlying ids.
- Raw uploaded cycler files are now detected, parsed and validated automatically, with anything needing a human parked in a review queue with actionable choices rather than failing quietly.
- A still-running measurement’s time series can be extended with new data
rather than re-uploaded whole, via
client.cell_measurement.extend(). - Record links across the app now render consistently, with the external-link icon marking what is clickable.
- Plot traces, gridlines and links now follow dark mode. Some traces previously drew in a near-invisible colour against a dark background.
- The Cycles tab offered only two metrics on production — every capacity, energy, voltage and duration metric had silently disappeared because of a units-spelling mismatch. The picker now derives from the data itself, so it cannot drift again.
- Re-running a simulation briefly showed the previous run’s error, then eventually the new result. A job could also be marked complete when its result had not actually been stored, surfacing as a failure to fetch results on an apparently successful job.
- The pan tool now stays selected after a pan.
- A tab left open across a deploy detects the new version reliably again.
Python API
Python API
client.pipelinenow has the same lifecycle methods asclient.simple_pipeline—update(),cancel()anddelete(). Previously a pipeline submitted from Python could not be cancelled from Python.client.pipeline.list()accepts the full set of filters the API supports and returns the total count alongside the page.
Data Processing
Data Processing
- New Digatron CSV reader.
- Arbin EIS sweeps are read and returned with the cycling data;
include_eis=Falseopts out. - Data-sheet selection in multi-sheet workbooks is now consistent across the Arbin, Maccor and Neware readers.
- Eight cycler-reader bugs across Arbin, Maccor, BioLogic and BaSyTec — see the headline above.
Search every model list from one box
Every model list — pipelines, designs, models, optimizations and the rest — now has a search box that queries the whole list on the server, not just the page you happen to be looking at. Type a name, a fragment of one, or paste a full id, and the list narrows to matches across all of your records — partial ids included. A CSV export carries the active search with it, so the file you download matches the list you were looking at rather than everything.The filter controls moved with it. Filters that previously lived behind a separate panel button now appear as the same pills as every other active filter, so what is narrowing a list is visible at a glance and removable in one click, rather than hidden one dialog away.Download measurement data as a zip
A new Download data action bundles a cell measurement’s raw data — no plots — into a zip. It works for a single measurement from its detail page, and for a multi-select on every measurement-list surface, so a whole batch comes down in one file. Each measurement gets its own folder containing its data tables (or its uploaded files, for file measurements) plus ametadata.json recording the
measurement’s id, name, type and creation time, its cell instance and
specification, and each table’s row count and column names.Multi-gigabyte uploads
client.raw_data.upload() now handles payloads up to 500 GB, transferring
large files in parts — enough to store a multi-gigabyte published dataset as the
raw bytes it was released as. Upload errors now report how many bytes transferred
against the total, so an interrupted transfer is legible. Install the optional
large-uploads extra to enable it:
pip install 'ionworks-api[large-uploads]'.Cycler exports now preserve what you wrote
We audited every export format against every protocol we can read, round-tripping the whole fixture corpus, and tightened the places where an exported file could drift from the protocol you authored. Exports now faithfully carry:- Jumps to the end of a schedule, so a protocol’s step count and total duration match what you designed.
- Full current precision, rather than rounding to one decimal place.
- A CCCV block’s constant-voltage taper when the block also has a duration, so the voltage hold keeps its termination.
- Repeat-block loop counts, so a routine meant to run three times runs three times.
- The auxiliary sensor a temperature end condition references — including safety limits — on both Maccor and Arbin, instead of collapsing every temperature end onto sensor 1. Two distinct sensors compared against the same threshold now stay distinct.
Arbin MITS Pro 8+ export
Arbin exports now cover both MITS Pro generations:.sdx for MITS Pro 8 and
newer, alongside .sdu for 7 and earlier. Previously only the older dialect
was written, so a bench running MITS Pro 8+ could not load the file.Studio
Studio
- The Test Scheduler now flags overdue runs — a run still open past its estimated end — in the Lab view, so an operator can close it out or extend the estimate. Scheduling behaviour is unchanged: an estimate is a forecast, not a commitment, so a lapsed one still releases its channel rather than freezing the schedule.
- The in-app agent now knows which page you are on across every route, so you can ask about what’s in front of you without naming it.
- Planned measurements can no longer be scheduled into the past, on every path that books a channel window — creating a scheduled test, the Schedule dialog, and applying an auto-schedule proposal.
- A browser tab left open across a deploy now refreshes itself cleanly instead of showing an error.
- The job configuration and metadata on optimization and fit detail pages now load reliably.
Python API
Python API
- Uploads above roughly 512 MB now transfer in parts, raising the practical
ceiling to 500 GB, behind the optional
large-uploadsextra.
Protocol Simulator
Protocol Simulator
- Protocols can be exported to Arbin
.sdx(MITS Pro 8+) in addition to.sdu. - Temperature end conditions now carry the auxiliary sensor index they reference, on both read and write, for Maccor and Arbin.
- A protocol’s sampling interval can now be given as an expression, not just a plain number.
Skills
Skills
- The skills now explain how to run long jobs from inside the in-app agent: submit the work, print the job id and return, then poll that id in later turns rather than blocking on a wait that would be cut short. A cut-short call never cancels work already submitted, so the guidance is to poll rather than re-submit.
Your organization in the navigation
Organizations can now show their own logo and name at the top of the navigation. An admin uploads a mark and edits the name in Organization settings → Branding, and the Ionworks lockup moves to the foot of the nav at the same size. An optional dark-mode logo can be uploaded alongside it; each variant falls back to the other, so an organization with a single mark shows it in both themes. An organization that hasn’t uploaded anything gets a neutral placeholder rather than ours — the Ionworks mark is never paired with someone else’s name. Branding is gated on its own permission, so granting it does not hand over anything else about the organization.New projects arrive with a materials library
A new project used to start empty, so building a model meant hand-entering chemistries and their properties first. Every new project is now pre-populated with 27 materials and 55 property datasets drawn from LiionDB — the subset that can actually close a full cell, supplying every required characterization parameter for the negative electrode, positive electrode and electrolyte. Where the same chemistry was measured by two different papers, both are kept as separate materials, because they are two independent parameterizations. Creating a project also returns faster now: the libraries are copied in the background and land moments after the project appears.Group your protocols, and export them to a cycler
Protocols can now be collected into named groups — a formation set, an aging campaign, a requested test matrix. Groups are managed from the Protocols page: create, rename, describe or delete one, then assign a protocol from its row menu or many at once by selecting rows. Deleting a group keeps its protocols and simply ungroups them, and says so with a live count before you confirm. The protocol table filters by group, with “Ungrouped” available as its own choice.A protocol can also be exported to a cycler format from its detail page. In the process we fixed a data-integrity bug worth knowing about: a protocol with unresolved input parameters previously downloaded as a valid-looking Maccor or Arbin file carrying a placeholder expression where a current belonged — a file that previewed cleanly and failed only once it reached the hardware. Export now refuses an unresolved protocol and tells you which inputs need values.Propose a schedule for a batch of test requests
Select a set of requested tests and the Test Scheduler will now propose the earliest reservations that genuinely fit, for you to review and apply. Each request takes the earliest free window across the project’s in-service channels, in the priority order you send them; tests already booked and measurements already running are treated as immutable, so nothing on the wall is ever moved. Setup, run and teardown all sit inside the reserved window, and the search is unbounded in time — a request comes back unscheduled only when no channel in the project could ever take it, which is the one case you can act on. Applying a batch is all-or-nothing: if a later reservation conflicts, the earlier ones are released rather than left half-booked.Studio
Studio
- A booked service visit — on a whole cycler or a single channel — now records when it ends, not just when it starts. A firmware update and a two-week send-away calibration are no longer indistinguishable, channel-hours can be counted, and a planned test booked on channels that will be out for service can be spotted before the work slips.
- A new lab operations report compiles the digest a lab manager asks for on a schedule — momentum, utilization now versus 24 hours / 7 days / 30 days ago, what came off test overnight, what frees up today, what is queued behind it, what is still waiting to be scheduled, and equipment out of service. Eight sections, each independently selectable, available as structured data or rendered Markdown.
- Thermal chambers can now be recorded as equipment in their own right, sitting alongside cyclers under a site rather than beneath one — a chamber commonly holds cells driven by several cyclers, or none.
- The Agentic Toolkit can be downloaded as a zip directly from the Agent page’s Bring your own agent tab, for anyone who can’t clone the private mirror.
- Plain-English protocol generation now understands protocol variables, so requests like “discharge, capture the capacity, stop cycling when it drops to 80%” work. It also gained the parts of the protocol language it previously named but couldn’t use — safety limit fields, impedance frequency settings, rate-of-change and temperature end conditions, and ambient-temperature ramps.
- Two protocols can now be compared for semantic equality, reporting the differences that actually affect how a cell is driven rather than differences in document shape.
- The active-organization picker in account settings is now searchable and sorted by name — focus, type, Enter — instead of a flat list in creation order.
- Cell specifications can be found by material: which cells use a given material, and which other cells share a given cell’s anode, cathode or electrolyte.
- The project overview’s pipeline list loads substantially faster.
- Last-modified timestamps are now accurate for designs, models and optimization templates. They previously recorded the creation time and never moved, which quietly misled anything sorting by recency.
- Two cell specifications in different projects can now share a name. Name uniqueness was enforced across the whole organization even though a specification belongs to exactly one project, so a name taken in one project blocked it everywhere. The same fix applies to cell instances.
- Simulation and fit jobs are now sized against the number of sequential rounds a fit really takes and its slowest task, rather than an idealised iteration count and an average — work that should have scaled out was being kept on a single node.
Pipeline
Pipeline
- Post-fit analysis is now available as pipeline elements — linear confidence intervals and Sobol sensitivity, returning typed results that decode client-side without any extra code.
- Model, objective and calculation options are now typed rather than free-form dictionaries, so an unrecognised or misspelled option is reported when you submit rather than minutes into a run.
- The model-fitting objectives documented
modelas required but accepted an objective without one, failing deep in the run instead. A missing model is now reported at submission. DataLoadersilently accepted and ignored unknown options — a misspelled key changed your results with no error anywhere. Unknown options are now rejected.- A measurement given as a plain string now requires its
file:/folder:/db:prefix at the point you write it, rather than being accepted and then failing at load time. - A
nullparameter value is now rejected instead of being serialised into a config that cannot run. - A weight naming an objective or variable that doesn’t exist silently fell back
to
1.0, so a fit ran with a weight the user believed was applied. It is now an error. - Fixed a composite-electrode fitting contract: an electrode’s lower excess can now be given either as a known per-phase split or as a single electrode-level value, with a clear error when neither is supplied, and the solved stoichiometry windows are reported back.
- Fixed a lumped single-electrode model leaking its own options into the underlying PyBaMM model.
Python API
Python API
client.pipelinegainedupdate,cancelanddelete, matchingclient.simple_pipeline— a run submitted from Python can now be renamed, stopped or removed from Python.- Material property datasets can be written from the client: create one from a DataFrame, replace the stored file while keeping the record, and update or delete it — no more reaching past the SDK to raw HTTP.
- New methods for finding cell specifications by material and for listing the specs related to a given one by shared anode, cathode or electrolyte.
- Auto-scheduling proposals and the new booked-service end times are exposed through the client.
- Step-summary validation now catches swapped charge/discharge capacity and energy columns. The swap is symmetric under every check that existed, so a file with the pair transposed passed strict validation cleanly — found on real uploaded data. A step whose current range picks up a single opposite-sign sample from the preceding step no longer abstains from the check either.
Protocol Simulator
Protocol Simulator
- A protocol can be compared with another for semantic equality, reporting the earliest real divergence in how the two would drive a cell.
- A slow step with no explicit duration was cut off at 24 hours. The runaway guard for a step that never meets its end conditions was capped rather than floored, so a genuinely long low-rate step was truncated. Low C-rate steps now run to completion.
- A jump that fires the moment a step is entered is now honoured, instead of the step running once first.
Skills
Skills
- Manage planned measurements covers requesting auto-scheduling proposals, reviewing them and applying them.
- Manage equipment covers the new end times on booked cycler and channel service.
- Manage cells covers finding cell specifications by material and listing related specifications.
- New Manage materials skill, covering material and property-dataset management from the SDK, including the new write methods.
- Validate data covers the swapped capacity/energy column check.
- Run simple pipelines covers requiring a model on the fitting objectives and the locator prefix on a string measurement.
Know how much longer a running test has left
A test already on a channel can now report how much of it is left. The platform reads the steps the cycler has actually measured, works out exactly where the cell has reached in its protocol — which branch it took, how many loops it has been through, what its variables hold — and simulates only the remainder. Because it starts from where the cell really is rather than where a model would have gone, the estimate tracks the physical run instead of an idealised one. Duration estimates also now work from the cell specification alone, so a request that hasn’t been assigned a specific cell yet can still be estimated.See what’s happening inside the cell
Simulation results now include spatial profile plots. Where a result carries a field that varies through the cell rather than a single number per timestep, it’s rendered as an interactive profile with fixed axes, a proportional time control, typed time overlays and marked domain boundaries. You don’t pick a plot type — whether a variable is scalar or spatial is inferred from the variable itself.Webhooks for your project’s events
Projects can now register HTTPS webhooks that fire when something finishes or changes. Pipelines and simple pipelines notify you when they reach a terminal state — completed, failed or canceled — and nine new cell events cover specifications, instances and measurements being created, updated or deleted. Webhooks are managed from Project Settings, each delivery is signed so you can verify it came from us, retried on failure, and viewable in a delivery log.Cyclers as real instruments
A cycler in the Lab now records the details a real instrument has: version, serial number, firmware version, and the hostname, IP address and port of its control host. On top of that, calibration and service are tracked — record when a cycler was last calibrated and how often it needs to be, and its next due date is derived for you. A cycler that isn’t on a calibration schedule reads as unknown rather than overdue. Scheduled service windows can be recorded ahead of time so the channels are accounted for before the engineer arrives.Studio
Studio
- The sidebar gained an Operate section holding the Channel Wall and the Test Scheduler. The Test Scheduler was previously reachable only by URL.
- Plain-English protocol authoring is now available everywhere a protocol is created — the New Protocol page, the new-simulation flow and the interactive builder, not just the test scheduler.
- The Agent now collapses code and printed output by default, showing the answer rather than the transcript. Plots and errors always stay visible.
- Activity log entries can now be filtered to a single project.
- Fixed live results going missing or stale on some jobs — result metadata could silently fail to upload while the job still reported success.
- Quick-model simulations now create their model inside the project you ran them from, so it appears in the project’s model lists instead of being invisible everywhere.
- Fixed a crash on the pipeline detail page when a parameter had no value.
- Deleting a measurement that a channel booking or an active plan depends on now explains which record is blocking it, and stored files are only removed once the deletion itself succeeds.
- Fixed the “learn more” link on the Protocol Simulator upload screen, which 404ed.
- Render failures are now reported to our error tracking, so crashes get fixed rather than going unnoticed.
Pipeline
Pipeline
- Fits now report per-objective timing and the cost of a parameter sweep, so the work a fit represents can be measured before it is scheduled.
- Breaking:
MultiCostnow takes one input form across both the schema and pipeline packages. The previously documented{cost: weight}mapping never worked in the schema package — a list of cost/weight records is now the single supported form on both sides.
- Invalid
DataFitoptions are now rejected when you submit, with a message naming the unrecognised option, instead of failing minutes into the run with an unexplained internal error.
Python API
Python API
- New
client.searchsub-client for global search across projects, models, cell specifications, instances, measurements, materials, studies, optimizations and pipelines. client.protocolnow covers the whole protocol lifecycle — listing, fetching, finding by name, creating, updating and deleting saved protocols — instead of only validation and conversion.- New clients for project webhooks and for cycler hardware, calibration and scheduled service.
- Fixed
get_plot_datareturning a 404 for every request — the client was calling an address that did not exist. - An API URL configured with a trailing slash no longer produces a doubled slash and a 404.
Protocol Simulator
Protocol Simulator
- A protocol’s position can now be recovered from a real cell’s measured steps — which step it is on, its loop counters, subroutine stack, variables and cycle number. Combined with the existing resume support, a simulation can pick up exactly where a physical test has got to.
Skills
Skills
- New Search skill covering global search across the platform from the SDK.
- New Manage protocols skill covering the full saved-protocol lifecycle, authoring and conversion.
- Manage equipment covers cycler hardware details, calibration tracking and scheduled service.
A home page for every project
Opening a project used to drop you straight onto its studies list. Projects now open on a proper home page: an assistant prompt front and centre, a Running now panel showing pipelines still in flight, a Pick up where you left off row of your most recently touched studies, pipelines, measurements and conversations, and browse tiles with counts for each area of the project. Ask a question from the home page and it opens a fresh Agent conversation with your question already sent.Describe a test in plain English
The Lab test scheduler can now author a protocol from a description. Type something like “1C/1C cycling for 100 cycles between 4.2 V and 2.5 V with 10-minute rests” and you get back a validated protocol, ready to request. If the description leaves out something that would change what physically runs on the channel, you’re asked about it rather than having a value guessed; common conventions (25 °C ambient, CC-CV taper, rest lengths) are assumed and reported back to you. If one of your saved protocols already does the job, it’s offered instead of a new one. Anything the generator returns is a protocol the platform accepts — it’s validated before you ever see it.Test requests get their own page, and export to your cycler
Planned tests now open on a detail page instead of jumping straight into the edit form, with the request, its scheduling, and its actions laid out separately — so an unscheduled request reads as “not booked yet” rather than a half-empty form. From that page you can export the request’s protocol in a cycler’s native format — Maccor, Arbin, Neware, BioLogic (BT-Lab) or Novonix — preview it, and download it, with no need to re-author the test in vendor software. Exports that need more than one file arrive as a single zip.Charge-transfer kinetics in the ECM
The Equivalent Circuit Model gained an optional Butler-Volmer charge-transfer element. Enabling it adds a symmetric charge-transfer overpotential driven by a new Exchange current [A] parameter, which captures rate-dependent losses that a linear series resistance cannot — nearly linear at low current, logarithmic at high current. It’s off by default, so existing models and simulations are completely unchanged, and the new Charge-transfer overpotential [V] output is available when it’s on.Studio
Studio
- ECM simulation results now show a real voltage components plot — open-circuit voltage, the series-resistance drop, and one band per RC pair, stacked down to the terminal voltage.
- Measurement views gained a Filter by Steps or Cycles selector. Measurements with no cycle data — OCV sequences, pulse and DCIR tests, single-pass characterisations — now get the full step filter instead of no filter controls at all, and open on Steps.
- Channel incident history — taking a channel out of service now records the outage with its cause, category, who reported it and when. A down channel shows a callout with the cause, start time and running duration plus a Return to service action, and the channel page lists its past incidents.
- Organization admins can manage the Programs catalog from a new Programs tab in Organization settings — create, rename and delete the programs used to tag planned tests.
- Protocols are now scoped to a project. Every project starts with its own editable copy of the standard protocols instead of sharing a read-only library, so edits in one project can’t affect another. Existing projects have been seeded with theirs.
- Uploading measurement time series now returns immediately and processes in the background, with progress and any processing error visible in the measurement list, so large uploads no longer block the request.
- Revoking an API key now takes effect immediately rather than after a delay.
- The Agent widget’s New chat button now actually starts a blank conversation instead of re-opening the last one.
- Reloading the page mid-reply no longer blanks the earlier messages in an Agent conversation — history and the streaming reply are merged rather than one replacing the other.
- Failed API-key authentication no longer echoes the submitted key back in the error response; only the key’s short prefix is returned.
- Sorting or filtering cell specifications by last-updated no longer errors —
the field is now stored and returned alongside
created_at. - Transient failures in authentication and membership lookups now report a retryable error with a real cause instead of an opaque failure.
- Program names consisting only of whitespace are now rejected, and program-related text meets WCAG contrast requirements.
Pipeline
Pipeline
- Pipeline elements now return typed result objects — parameter-estimation,
optimization, posterior, ensemble, regression and validation results each have
their own type, reachable from
Pipeline.results. A newiwp.analysisnamespace collects post-fit analyses, includingLinearConfidenceIntervalandSobolSensitivity. - Interpolant-valued parameters (for example a measured ambient-temperature profile
supplied per objective) now serialise from a plain dictionary, not just from a
pybamm.ParameterValues. Array-valued parameters round-trip correctly instead of being misread as indexed parameters.
- Fixed a memory leak where every fit result held a reference to itself, keeping results alive longer than necessary. A parent result whose child happened to hold equal parameter values also no longer silently loses that child when copied.
Python API
Python API
- New clients for channel incidents and for the background measurement upload flow, so an upload can be started and its processing state polled from the SDK.
- Protocol clients are now project-scoped, matching the per-project protocol change above.
- Breaking (direct
ionworkspipelineusers only):result.optimizer_result,iwp.OptimizerResultandiwp.SamplerResultare removed in favour of the typed result objects above (OptimizationResult.x/.fun/.success,PosteriorResult, …), andRegressionResult.resultis now.results.
Data Processing
Data Processing
- Power [W] is now computed when a measurement is processed and stored with the time series, rather than derived on every read. It also stays correct when the current sign is auto-corrected during processing.
Protocol Simulator
Protocol Simulator
- A protocol can now be resumed exactly from a captured point — its position, loop counts, variables, cycle number and full physical state — so a run can be checkpointed and continued with no rest step and no loss of accuracy.
- New protocol authoring warnings flag common mistakes before you run anything: mistyped or cross-scope jumps, missing subroutines, loop conditions that can never be satisfied, unreachable steps, voltage limits that contradict the step direction, targets outside the safety window, and rests with a current-based end condition. These are advisory — nothing that runs today stops running — and can be made blocking if you’d rather catch them as errors.
- Protocols now report their derived voltage and current limits — the minimum and maximum voltage and the peak charge and discharge currents implied by the steps, safety limits and drive cycles.
- Maccor and Novonix exports now use the earliest duration end condition rather than the last, so a step no longer runs for longer than requested.
- Fixed a Novonix export writing a structured safety-limit value where a plain number was expected.
- Fixed Arbin loop detection and Neware template handling cases where two divergent code paths disagreed.
Skills
Skills
- Manage equipment covers recording and reading a channel’s incident history.
- Upload data covers the background upload flow and how to poll a measurement’s processing state.
Agent chat, built into the app
A new in-app Agent puts a conversational assistant right inside Studio. Ask it questions about your data and models, hand it files, and follow along as it works — replies stream in as they’re generated, and each conversation is saved so you can pick it back up later. The Agent runs in an isolated sandbox per organization. It’s rolling out to a limited set of organizations first and will become more widely available over the coming weeks.Battery Cycler Simulator, now in your projects
The protocol simulator has moved out of a standalone page and into your projects, so simulations live alongside the cells, studies, and models they belong to. A new Quick model option lets you simulate straight away without first saving a parameterized model — just pick a chemistry and set a capacity and resistance scale inline. Prefer a fitted model? The From library toggle still runs against any of your saved cell → parameterized-model selections.Plan and track lab tests
The Lab view gained a full test scheduler. Request a test on a channel and the platform validates the protocol up front — an invalid protocol is rejected before the request is saved, with a clear message about what’s wrong. The scheduling dialog shows each channel’s live availability and electrical ratings as you pick, and you can copy an existing request to seed a new one or delete one you no longer need. An optional organization Programs catalog lets you tag each test with the program it belongs to, visible on the Lab wall and planning table.Engineers can also watch a channel to keep an eye on the test they care about and filter the Lab wall down to just those — and because a watch is tied to the run currently on the channel, it clears itself automatically the moment that test finishes.Studio
Studio
- Battery Cycler Simulator moved into projects, with a new Quick model option to simulate without a saved parameterized model.
- Lab test scheduler — request, copy, and delete tests on a channel; invalid protocols are rejected on submit with an actionable error.
- Programs — an optional organization catalog for tagging planned tests, surfaced on the Lab wall and planning table.
- Watch a channel to follow its live test and filter the Lab wall to your watched channels; watches clear automatically when the test completes.
- A cell specification can now designate a default parameterized model; the first model created for a spec becomes its default automatically.
- Measurement details gained a derived Power [W] column (voltage × current) selectable in the Time Series tab.
- The measurement Differential Analysis tab now plots dQ/dV in addition to dV/dQ, switchable from a plot-type dropdown.
- Material property datasets and analyses now track their source — when a dataset or analysis was computed from a pipeline or another analysis, you can see and click through to where its data came from.
- Organization admins can resend an invite or send a password reset to a member directly from the Members tab, and adding a member by email now distinguishes newly invited from already-registered users.
- Lab can now be shown or hidden per organization from the admin Navigation settings, like the other feature areas.
- A stale browser tab left open across a deploy now reloads itself to pick up the new version instead of showing a maintenance page.
- Plot axes, tick labels, and titles are now legible in dark mode on validation and other charts.
- Adding a member by email is now case-insensitive, so a differently-cased address no longer creates a mismatch.
- Cycler and channel detail pages no longer error on load for equipment with linked child records.
Pipeline
Pipeline
- MSMR half-cell OCP fits now constrain the fitted host-site occupancy fractions (Xⱼ) to sum to 1, so the values exported and reused downstream are self-consistent.
- A DataFit whose every evaluation is non-finite now fails with a clear error instead of silently returning the initial guesses as if the fit had succeeded.
Python API
Python API
- Fitted models now persist their simulation settings (mesh and solver
configuration), so a model simulates the same way wherever it’s used. The
ModelandParameterizedModelclients expose the setting and document how to build it from live PyBaMM objects viaiws.models.SimulationSettings(...). SimplePipeline.createnow accepts a schema object directly (matchingPipeline.create), so you no longer need to call.to_config()yourself; dicts still work unchanged.- New
JobClient.get_plot_data(job_id, objective_name, …)returns a DataFit’s model-vs-data overlay directly from a completed job.
Protocol Simulator
Protocol Simulator
- Impedance (EIS) simulations for the Equivalent Circuit Model now run through the same standard PyBaMM machinery as every other model.
- Arbin protocols whose step end conditions aggregate per-channel temperatures
(e.g.
max(Temperature, …) > 55) now parse correctly instead of failing with an invalid-end-condition error.
Lab view — see every cycler and channel at a glance
A new project-scoped Lab dashboard shows all of your test equipment organized as sites → cyclers → channels, so you can tell at a glance what’s running where. The Lab wall lists every cycler with a utilization bar and per-state channel counts, filterable by site and by amp/volt rating range. Drill into a cycler to see its full channel grid, or into a single channel to see exactly which cell is on test, its measurement history, and an editable out-of-service toggle with notes.Each channel’s state — occupied, stale (a run that stopped updating and likely needs attention), free, or out of commission — is derived from the measurements linked to it, so the view stays accurate without any live telemetry hookup. Channel cards also show an estimated end time for still-running tests when one is available. A set of scheduling rules keeps the data honest: two runs can’t overlap on the same channel, and a channel can’t be taken out of commission while a test is active.The same equipment picture is available programmatically through the newclient.lab sub-client in the Python SDK — ask for overall utilization, list
free channels (optionally filtered by required ratings), find stale channels
that need attention, or look up what’s on a specific channel, all from a single
call.Measurement analyses
You can now attach analyses to a measurement — a named table of extracted features (e.g. ECM parameters from EIS, or LLI/LAM degradation points from RPT data) stored alongside the raw measurement. The measurement detail page lists a measurement’s analyses, and each analysis has its own detail page with a data preview, downloadable parquet, and a link back to its source measurement. Analyses are fully supported in the Python SDK via the newclient.analysis
client (create from a polars/pandas DataFrame, list, fetch data, update,
delete).Throughput-based degradation in the ECM
The Equivalent Circuit Model (iwp.models.ECM) gained an opt-in degradation
capability: capacity and internal resistance can now evolve as user-supplied
functions of capacity throughput (the running integral of |current|), so a
single simulation can capture fade over the course of a run. Both options
default to constant, so existing ECM configs are unaffected.Studio
Studio
- Global search now covers cyclers and channels alongside projects, studies, and cells — search from anywhere and jump straight to a channel’s detail page.
- The cell specification detail page is now organized into three tabs — Measurements, Instances, and Parameterized models — each with server-side pagination, filtering, and sorting.
- Organization admins can now deactivate a member to suspend their access while preserving their membership and role, then reactivate them later. A deactivated user sees a dedicated screen with an option to switch to another organization.
- Materials and components are now scoped to the project of the cell specification that references them, keeping each project’s parameter data within its own boundary.
- Sorting the project measurements grid by the measurement id column no longer makes every row disappear.
Pipeline
Pipeline
- DataFit runs with a Bayesian sampler now return the full posterior sample chain (per-parameter samples and per-sample costs), not just the point estimate, retrievable from the job result.
Python API
Python API
- New
client.labsub-client for point-in-time equipment questions: overall utilization, free channels (optionally filtered by required amp/volt ratings), stale channels needing attention, and what’s on a given channel. - New
client.analysissub-client for creating, listing, fetching, updating, and deleting measurement analyses, serializing DataFrames to and from parquet transparently. - Submitted pipelines can now reference local data with
file:andfolder:refs; their contents are read and inlined at submit time, and the same inline row cap that applies to raw DataFrames is now correctly enforced for these refs (afile:pointing at a very large CSV no longer slips through). - Raw-data upload now uses the same fast signed-URL flow as regular measurement uploads.
Protocol Simulator
Protocol Simulator
- Arbin Power Simulation drive cycles are now supported — they parse into a drive-cycle step that can apply a power (W) waveform rather than current, and Arbin cumulative capacity/energy counters are modelled correctly across steps.
- Arbin
SetValuesteps that read a last-step quantity (e.g.MV_UD1 = LS_CHAN_Discharge_Capacity, the “measure C/20 capacity then log it” idiom) now resolve correctly at simulation time instead of failing with an unresolved-variable error, so the downstream steps that depend on that value run. - Arbin subschedule steps that happen to share a step index and label with a
step in the parent schedule no longer collide with a duplicate-step-name
error; each subschedule’s steps are kept distinct while still resolving
gototargets correctly.
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. 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
The pipeline detail page now loads noticeably faster: large per-element data is now loaded lazily on expand instead of upfront, and a slow client-side recalculation on every 5s poll tick has been optimized away. Separately, pipeline ECM fits got faster and more accurate through several internal fit-strategy improvements, with fit quality fully preserved.Studio
Studio
- 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. The UI flips immediately with optimistic updates, and the slower job-termination work is offloaded to run in the background. 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. 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 the delete was silently blocked 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 and validators). Descriptions of external cycler conventions that legitimately differ (e.g. BioLogic / Arbin native positive = charge) are unchanged.
Pipeline
Pipeline
- 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.
- Local pipeline runs now match server behavior in three places where they
had drifted. An OCP interpolant input with only a
datakey is no longer rejected as missing metadata. Schema-provided transforms (Log10,Log,Inverse, …) 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
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
- 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
- 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.
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
- 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
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
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
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.