Introducing ionworks: one package for everything Ionworks in Python
Working with Ionworks from Python now takes a single install. pip install ionworks
gives you the API client, data processing, pipeline building and shared utilities in
one package, with one version and one set of docs:- One install, always in step. You no longer have to keep
ionworks-api,ionworksdata,ionworks-schemaandiwutilat compatible versions. They ship together, so they always work together. - Laid out like the app.
iw.datafor measurements and processing,iw.pipelinefor building fits and validations,iw.apifor everything on the platform. - One place to look. A single documentation site, changelog and repository.
- Up to date. Python 3.12 through 3.15, including the newest Python that PyBaMM supports.
migrate-to-ionworks skill from the Ionworks skills
and do it for you. Install ionworks in a fresh environment: it can’t share one with
ionworks-api.We’re starting at 0.1.0 so we can refine the API with your feedback before 1.0. Let us
know what you think.Protocol version history and a live preview
Protocols now keep a version history. Editing a protocol no longer creates a same-named copy: Save records the next numbered version, with an optional name (after an AI edit, the name starts as your prompt). Older versions open read-only with a Restore option, and the header shows when you have unsaved changes and which version they’re based on.While you edit, a new Preview tab simulates the protocol on your parameterized model’s equivalent circuit model and redraws as you change it, so you can check a protocol behaves as intended before running a full simulation.Design lab
The new Design lab (under Optimize, and from a cell specification or parameterized model page) lets you explore cell designs against a metric suite’s surrogate. Drag design parameters and every metric updates instantly, with a spider plot and deltas against the baseline design. Meet targets finds a design that hits the metric targets you set. You can compare several cell specifications side by side in both views, and train surrogates for several specifications in one go.Versions for parameterized models
Parameterized models can now have versions. Save a new version from the model page (or withcreate_version() in the Python API), keep the original’s name, and compare
any two versions side by side. Model lists show one row per model.Studio
Studio
- Simulations in the sidebar. A project-wide Simulations list under Simulate, also shown on Project Home, includes runs made outside a study. A New Simulation button starts one from there.
- A dashboard for every study. A study’s Dashboard tab creates its dashboard on first visit, and the empty state lists the study’s runs, models, protocols, inputs and metrics to plot. The plot builder offers every variable of a run’s model, computing ones that weren’t stored on request.
- State of charge in study plots, on either axis (e.g. voltage against SOC), for any model that can compute it.
- Metric scatter plots are coloured by condition, with a legend, so a sweep no longer reads as one cloud. Choose what drives the colour with the Color by option.
- Clearer plot tooltips. Simulation tooltips show the x value and a short default set of fields. Pick up to 20 extra fields under Plot appearance → Tooltip fields.
- Linked parameters read as formulas. A linked parameter’s expression shows parameter symbols and rounded numbers; hover for the full name or exact value, click a symbol to jump to that parameter. Edit a parameter’s symbol on the model page.
- Protocols show their sub-procedures. A protocol that calls sub-procedures (such as a Maccor master procedure) now shows them in its UCP, flowchart and plain-English views.
- Better section detection for linked protocols. For a measurement linked to a protocol, sections (pulses, full loads) are identified using the protocol’s planned steps rather than guessed from the data alone.
- Live sync shows the Ionworks Sync version each PC runs, its schedule and any upload-rule errors, and offers an update when a newer version is available. Maccor files with four-digit extensions now sync, upload rules can be edited on the PC, and each run reports how many files the rules left out.
- Organization admins can hide more pages. Every sidebar page can now be hidden per organization, and links to hidden pages are hidden everywhere else too.
- Dashboard plots no longer warn that pack or module voltages are “outside the physical range”.
- Time-series reads no longer fail for measurements uploaded from the SDK without the cycle capacity and energy columns.
- Simulations of unstructured (3D) DFN models now include State of charge.
- Cell names on the Cells page link to the cell again, and a specification’s parameterized-models tab follows the Parameterized Models page setting.
- The study report’s upload guide link points at the right docs page.
- Design lab labels, parameter names, values and units no longer clip.
Pipeline
Pipeline
CycleAgeing.plot_fit_results()draws the model and residual lines through sparse targets’ scored points instead of leaving them invisible.- Stored parameter sets keep only the hysteresis branches the model actually uses. The
check_for_hysteresisoption ofiwp.util.clean_parametersis removed.
Python API
Python API
- Dashboards from code.
client.dashboardlists, previews, creates, updates, renders and deletes dashboards and plots. - Function-valued design parameters. A design parameter can be a lookup table,
{"x": [...], "y": [...], "interpolator": "linear"}, so you can screen candidates such as electrolyte conductivity curves as a batch without storing a model for each. - Parameterized model versions:
create_version()andlist_versions().get_parameter_values()takesnamesandmatchto read only the parameters you need. - Pipelines and simulations:
client.pipeline.list_elements(),get_element_job_config()andclient.simulation.get_steps(). - MCP server: new tools create, copy and version parameterized models, read pipeline outputs, manage studies and compare runs, and results are more compact. An expired sign-in now prompts you to reconnect instead of failing every tool call.
Protocol Simulator
Protocol Simulator
- Much faster long simulations. Equivalent circuit model simulations of repeated cycles are dramatically faster (1000 CC-CV cycles in well under a second), and per-step overhead is lower for every model, with unchanged results.
Skills
Skills
- New
manage-dashboardsskill: read, author and render dashboards through the SDK. manage-protocolscovers protocol versions;run-simulations,manage-projects,run-pipelinesandsim-resultscover function-valued design parameters, parameterized model versions and the new pipeline and step reads.
Simulation plots and study dashboards
Project dashboards can now hold simulation plots as well as measurement plots. Pick runs by filtering the simulations table (including on inputs and metrics), either as a fixed set or as a saved filter rule that picks up new completed runs when refreshed, then preview them in a compact plot drawer and save the plot. Metric plots are scatter plots with hover detail, and time-series legend fields are configurable.A study can now have its own dashboard, kept with the study rather than in the project’s dashboard list. A study’s creator controls its dashboard and which simulations it contains; anyone else can view and preview results, or Copy study to get their own editable copy with its dashboard and plots. The study list shows each study’s creator, with an All / Mine toggle.See the procedure a Maccor run recorded
Maccor raw (binary) data files, which were previously marked unsupported, are now read for the test procedure the cycler recorded in them. A complete recording is added to the protocol library (or matched to a protocol already there) and linked to the run’s measurement automatically. Raw files uploaded before this change have been re-read.On a measurement page, the protocol now has its own Protocol card: change, link or unlink the protocol, see whether it matches what the cycler recorded, and Replace with what the cycler recorded when it differs. The raw file’s page shows the recorded procedure too.Export measurements as MF4
The measurement page’s Download data menu now offers MF4 (ASAM MDF4) alongside Parquet and CSV, for use in CANape, asammdf and other MDF tools. Channels carry their units (e.g.Voltage in V), and the download includes a README showing how to read the
files with asammdf.Faster protocol simulations
Long protocol simulations spend much less time outside the solver: a 1,000-cycle ageing protocol runs about 3× faster, with identical results.Studio
Studio
- Cycle-level capacity and energy. Measurements and simulations now include
Cycle discharge capacity [A.h],Cycle charge capacity [A.h],Cycle discharge energy [W.h]andCycle charge energy [W.h], which accumulate across every step of a cycle and reset at the next. Existing measurements have been updated, and the columns are included in data downloads. - Raw files on the measurement page. A Raw files card lists the files a measurement was built from, what each did (created, replaced or extended it) and links to each file’s page. The Details, Analyses and Raw files panels can now be collapsed.
- Project Contributors can delete the project content they can create and edit. Deleting the project itself, its members and roles, live-sync sources and raw-data issues stays with Project Admins.
- Every protocol needs a name. The simulation builder always asks for one, prefilled from an uploaded file or a generated protocol, and won’t run with a name another protocol already uses.
- Protocol names link to the protocol on the simulation page, in measurement tables and on the lab channel schedule. The simulations table groups its Columns panel and links its Protocol column.
- Column widths are remembered. A column you resize keeps its width through search and page reloads, on every table.
- Failed measurements show a red alert icon beside their name instead of a separate column.
- Live sync sources that are still being set up show amber on the Live sync page, in the top bar and on project Home, instead of looking healthy.
- Dashboards load faster, fetching all their plots in one request.
- Parameter metrics. Metric suites can define metrics such as stack thickness or areal capacity, computed directly from a parameterized model’s parameters.
- Simulating a saved protocol fills in every input it references, including inputs used only in its global settings, from the protocol page, a study and the full setup page.
- Table rows can’t lose their controls. The selection checkbox, View button and row menu can no longer be hidden from the Columns panel.
- The last row of a table is no longer partly covered by the scrollbar strip on macOS, and single-page tables no longer show a pagination footer.
- The Voltage components section is only offered for models that have a voltage breakdown.
- Opening a raw file’s plot no longer fails intermittently right after the file was updated.
Pipeline
Pipeline
ElectrodeBalanceFromFirstCycleEfficiencysupports composite electrodes (e.g. graphite/SiOx) throughoptions, and now computes the formation loss against the positive electrode’s capacity, so it follows design changes to loading."Nominal cell capacity [A.h]"is no longer an input, and results change for existing configs.
- Data fits and validations now use the model’s saved simulation settings (mesh and solver) instead of the defaults.
CycleAgeingwarns with the cause whenever a metric is scored as a failed evaluation, and a fit where every evaluation fails raises an error instead of returning the initial guess.
Python API
Python API
- Every record links to the web app. Detail
getcalls returnurl(the record’s page in the app) andapi_url(its canonical endpoint). - Per-run simulation settings. Simulation batches take
simulation_settings(solver,var_pts,submesh_types,spatial_methods,discretisation_kwargs), overriding the model’s and parameterized model’s settings for that run.discretisation_kwargscan also be saved on models and parameterized models. - Repeat inline simulations reuse stored results. Submitting the same inline parameterized model again reuses the existing one instead of creating a new copy or failing on its name.
- Protocol groups.
client.protocol_groupcreates, lists, updates and deletes groups, and protocols takeprotocol_group_id. - Projects carry your own access. Project records include
my_roleandmy_permissionsfor the caller, and no longer embed every member’s role, so project lists are much smaller. - Metric suite surrogates.
client.metric_suite.create_surrogate(...)trains a model that predicts a suite’s KPIs anywhere in a range of design variables without simulating. - Sites have a timezone (
Site.timezone, an IANA name defaulting toAmerica/New_York).
Data Processing
Data Processing
- Under
termination="events", a constant-current or constant-power step whose last logged sample belongs to the next step now takes its end value and setpoint from its own samples, so simulated steps no longer stop early.
Protocol Simulator
Protocol Simulator
- Voltage sweeps (e.g. slow cyclic voltammetry) with no explicit duration run until their setpoint reaches an end condition, instead of stopping at 24 hours.
- Sub-procedure jumps in protocols imported from Maccor, Arbin or UCP files resolve
correctly, and an unresolved block-level
gotois reported when the protocol is saved.
Skills
Skills
run-simulationscovers per-run simulation settings, metric suite surrogates and protocol groups.manage-protocolsanddiscover-apidocument protocol groups.manage-projects,manage-cells,run-pipelinesanddiscover-apilink to records through theirurl.manage-equipmentdocuments site timezones.
Export parameterized models to MATLAB and Simulink
The Download button on a parameterized model’s page is now a menu: the existing model and parameters JSON, MATLAB code, and Simulink block (Beta). The Simulink block has been checked in Octave but not yet run in MATLAB/Simulink. Both exports use the model’s saved simulation settings, so the exported model matches what runs in Studio. Current and ambient temperature are always inputs, and initial SOC is an input for ECM and lithium-ion models. The MATLAB export includes a README and arun_example.m, and
models with algebraic equations (such as ECM and DFN) work in both exports.3D simulations
Models can now start from a 2D (x-z) or 3D (x-y-z) unstructured DFN preset in the model create form, and their results have a new Spatial field plot. It draws the field on the cell’s mesh in the browser, with a time slider, a cutaway along any axis, mesh edges and a fixed colour bar.Build a model’s parameters from any cell spec
A model builder is a recipe, saved on a model, that turns a cell specification into that model’s parameter set. Each parameter comes from the cell spec (with units converted automatically), a fixed value, or a calculation whose inputs can themselves be read from the spec. Test on example runs an unsaved recipe against an example spec, and Build model in a cell spec’s Parameterized models tab saves the result. Builders are also available in the Python API asclient.model_builder.Parameterized models can now keep a calculated parameter as the calculation that
produces it rather than a frozen number, so overriding one of its inputs in a
simulation (e.g. an active material fraction) recomputes it.Raw files you can open, plot and triage
Every file in Data → Raw data now opens its own page. A file that parsed is plotted with the same plot card as a measurement (time series, cycles, dV/dQ, step filters); a file that didn’t shows its findings with Retry and Download. Files waiting for a decision or for their cell to be registered are counted on the Measurements sidebar item and announced on project Home and Measurements, linking to a review view. Files in a format no reader recognizes are marked Unsupported and hidden from the list by default, so they no longer bury the failures that need attention.Studio
Studio
- Models belong to a project. A model is visible only in its own project, and each project has its own copy of the built-in models. Model names are unique per project.
- Report a cell or test as failed. A Report failure dialog on a measurement marks either that test or the whole cell as failed, with a reason. A failed cell fails every test on it; a failed test leaves the cell alone.
- List pages remember their view. Filters, search, sort and page size are kept when you leave a list and come back in the same tab, on raw data, measurements, cells, materials, models, parameterized models, pipelines, protocols, optimizations and dashboards.
- Simulation plot boards are saved. Plots you add and the layout you arrange on a simulation’s page are restored the next time anyone opens it.
- Copy a plot to the clipboard from the plot toolbar, ready to paste into a doc or slides. Downloaded and copied PNGs now use the plot’s background colour and have padding on every edge.
- The Voltage components plot is opt-in. It is shown with a Show voltage components button, and only offered when the current keeps one sign.
- Filter pills on status columns show ticks for what the grid shows, with Only to keep a single value and Select all to clear the filter.
- Re-uploading a fuller cycler export no longer fails when the cycler renumbered its cycle counter between exports.
- Auto-fixing a reversed current sign now flips power too, so charge and discharge energy are no longer swapped.
- Fits whose validation produced no score no longer stay “processing” after they finish, and jobs that will never finish are now marked failed instead of showing “pending” indefinitely.
- A design optimization or fit where every simulation fails now fails with an error instead of completing with a penalty cost.
- A cell can no longer be scheduled onto two channels at overlapping times.
- Icons on light buttons in dark mode match their label’s colour instead of white.
- A raw file’s page adds one browser history entry and shows one loading screen.
- Listing a cell’s measurements now returns each measurement’s
channel_id.
Pipeline
Pipeline
- New calculations:
ElectrodeBalanceFromFirstCycleEfficiency(stoichiometry limits and initial concentrations from electrode geometry, nominal capacity and first-cycle efficiency) andElectrodeGeometryFromLoading(thickness, active volume fraction and porosity from coating loading and press density). - Requires
pybamm>=26.10.1.1.
- A fit where every evaluation fails now raises an error instead of returning the initial guess.
- A composite-electrode MSMR config with hysteresis on only one phase gives a clear
configuration error instead of a bare
KeyError.
Python API
Python API
client.model.create_from_zoo(...)imports a model from the PyBaMM model zoo and creates both a model and a parameterized model in one call.cell_spec_idis optional, and model constructor arguments go inmodel_kwargs.- Cheaper simulation lookup.
client.simulation.listtakesprotocol_id,state(queued/running/completed/failed) andsummary, and parameterized models can be listed without their parameter values. Every simulation record carries itsprotocol_idandprotocol_name.
- Large uploads no longer fail with HTTP 524 on a slow part.
- Dependency floors across the public packages are raised to versions that actually
install and import (e.g.
pandas>=2.2.2,pyarrow>=16.0.0).
Data Processing
Data Processing
- Step classification ignores a step’s trailing sample when it carries the next step’s setpoint, so constant-current steps are no longer classified as “Unknown step type”.
Protocol Simulator
Protocol Simulator
- BioLogic exports with C-rate steps or end conditions load on the instrument: C-rates are written as absolute currents against the cell’s nominal capacity.
- Nested repeat blocks keep the right cycle counts through an Arbin export and re-import.
- A
step_block:written with aname:field now takes that name, so two such blocks validate andgotocan target them. - A
C-rate < xend condition now fires on models without a C-rate variable, such asiwp.models.ECM.
Skills
Skills
manage-projectscovers project-scoped models, importing from the PyBaMM model zoo, and live calculated parameters.run-simulationsandsearchshow how to find and reuse an existing simulation.manage-protocolsnotes that BioLogic exports need the cell’s nominal capacity.
PDF reports for parameterized models
A parameterized model’s page has a Report button that downloads a PDF of the model as it stands. Each function-valued parameter is plotted against its input (stoichiometry, state of charge, electrolyte concentration or temperature), with one curve at each of 0, 10, 25, 35 and 45 °C where temperature is an input. Where possible it is also written out as an equation, with a legend giving each referenced parameter’s name and value. A parameter that can’t be plotted is listed in a Not plotted table with the reason. Scalar parameters are tabulated in the same sections as the model’s parameter tabs, after a cover page listing the model type, thermal and ageing options, and description.See and export the data behind a plot
Dashboard plots, and plots in the measurement plot drawer, have a View source data menu item. It opens one table of the data the plot is drawn from — with the measurement, cell and specification names alongside the values where the plot reads them — and the same table downloads as CSV. Values the plot calculates while drawing are not included, and the dialog says so.Dashboards stay the way their creator left them
Only the person who created a dashboard can edit or delete it, its plots, or its agent drafts. Everyone else with access can still view it and change plot inputs for themselves (never saved). Anyone whose role can create dashboards (Project Admins and Contributors) can also make their own version of the whole dashboard, or copy a plot to a dashboard of their own. A duplicated dashboard shows where it came from (“Copied from X on 2026-10-11 15:52”). Trying to change someone else’s dashboard explains how to get an editable copy.Repair a file whose time runs backwards
A raw file that fails the time-ordering check no longer leaves only Accept and continue or Discard this file. The review now shows the offending rows and offers just the repairs that fit the problem, recommended first: rebuild a continuous clock (when a per-step clock was exported instead of total elapsed time), sort rows by time, drop the out-of-order rows, or separate identical timestamps. A repair that doesn’t restore ordering is reported as still needing input rather than marked fixed.Studio
Studio
- Choose the agent’s model. A picker under the chat input switches between Opus 5.5 (the default), Sonnet 5.5 and Haiku 5.5, and your browser remembers the choice.
- Analysis plots read cleanly when a test repeats set-points. Points are drawn in x order as markers, with a line through each set-point’s mean, so a rate table run twice reads as one line instead of a sawtooth. This applies in the plot drawer, dashboards and the analysis page.
- The protocol generator is faster and fails less often. It no longer gets stuck re-reading the same reference material until it gives up.
- An older export of a running test no longer closes it. A manually uploaded file whose data ended more than two days ago marked the test as finished, so the next, fuller export was refused as not fitting. Runs already closed this way are unchanged.
- Reported metrics no longer show a misleading number when a threshold is never reached. A metric such as “Charge time (10–80% SOC)” on a charge that stalls before 80% now shows no value.
- Stacked dashboard plots put the x axis under the bottom row instead of the top. Plots already on a dashboard pick this up when they are re-sent or edited.
- Paging past the end of a list, for example after a filter shrinks it, returns an empty page on the pipelines list and most others, instead of a server error.
Pipeline
Pipeline
ionworkspipeline Python classes; in a pipeline config
the same metrics are written as dicts, e.g. {"type": "Crossing", ...}.Improvements- A metric can span several steps. Any metric’s
stepaccepts a list of consecutive steps, read as one, e.g.Minimum("Negative electrode potential [V]", step=[2, 3, 4]). Gaps, repeats and descending lists are rejected with a message pointing toComposedMetric. - New
Crossingmetric,Crossing(variable, crossing_variable, value, step), readsvariableat each point wherecrossing_variablecrossesvalue.SOCandVoltageare now special cases of it, with their configs unchanged. - Crossing thresholds can be metrics.
valueaccepts a metric evaluated on the whole solution, so a threshold can depend on an earlier step, e.g. the time for throughput to go from 10% to 80% of a step-0 capacity. by_cycle(step={cycle: step})reads a different step in each cycle, for a quantity logged at different positions in different cycles.RelativeTimevalidates as a metric config, on its own, as a threshold, and in design optimizations.DirectEntryreferences must be in the pipeline’s project. Apipeline_idorcell_spec_idfrom another project is refused with a permissions error that says how to fix it.
- Pipeline calculations that read a stored measurement (for example an OCP interpolant from a GITT measurement) no longer fail with an authentication error.
CycleAgeingno longer saves only a threshold’s cycles for a crossing searched over the whole solve; an unsliced crossing with a cycle-sliced threshold is now rejected.- A missing variable in
SOCnow gives aUserConfigurationErrorthat names it, rather than a bareKeyError.
Protocol Simulator
Protocol Simulator
- Arbin
LS_CHAN_*capacity and energy are read as the cumulative channel counters at the end of the previous step, matching the cycler. Protocols that read them after several steps without a counter reset (e.g. sizing GITT pulses from a two-part discharge) had used only the last step. Arbin energy counters now accumulate too.
Plot measurements from the table
The separate comparison page is gone, and so is its 10-measurement limit. Select measurements in any measurement table, click Plot and pick a plot type: time series (with multiple and stacked Y axes), a cycle metric against cycle (optionally relative to a reference cycle), voltage against capacity, dQ/dV and dV/dQ, or an analysis when every selected measurement has the same kind. A plot type the selection can’t support is shown disabled with the reason (“4 of 12 have no cycle data”).The plot opens in a resizable drawer over the table, which stays usable underneath: ticking or unticking rows adds or removes measurements from the plot. Closing the drawer collapses it to an edge tab, and the plot survives a reload. A finished plot can be saved as a project-wide template, which then appears as a plot type, or sent to a dashboard — either for the measurements you picked, or for every measurement matching the table’s current filters, so new matches appear on their own. A dashboard plot draws up to 500 measurements (250 for analysis plots), and the builder says so when a scope is larger.Your measurement selection now persists across pages, filters, tables and reloads within a project, with its actions in the table toolbar. Other paginated tables clear their selection when you change page, so a bulk action only ever applies to rows you can see.Dashboards you can edit yourself
- Build a plot without the agent. A dashboard’s New plot offers Build a plot, which starts from the project’s measurement table with its search, filters and tags, then the same plot types and controls as the drawer, with a live preview. Builder plots can be rebuilt in place with Edit plot, and each card shows whether it came from the builder or the agent.
- Change titles, axis labels and colours from the plot’s Configure drawer, including five palettes (among them colour-blind-safe and sequential). The agent never overwrites your choices; when one of its edits would, the review card lets you keep yours or take its version.
- See and edit the code behind an agent plot. Edit code (or View code without edit rights) shows the plot’s data plan, transform and parameters with a live preview. Save is only enabled once the edited code has run without errors, and a concurrent edit is refused rather than overwritten.
- Know what a plot shows. Each plot has an editable one-line description, lists the filters that selected its data, and its record count opens a list of the records it read (up to 500), grouped by cell, each linking to its page.
- Plot cell design data. Dashboard plots can read electrode and component properties (thickness, porosity, loading, active fraction, and separator, electrolyte and case properties) and chain from a spec’s components to their materials’ datasets.
Filter measurements by any metadata
Measurement tables gain a column for every metadata field on the measurement, its cell instance and its cell specification — anode loading, cathode porosity, cycler, ratings, material properties and more — all hidden until you show them. Numeric fields filter with a range slider over a histogram of the project’s values; text fields filter by value. The columns panel is searchable and grouped, and CSV export writes these values as columns. Column headers are the field’s full path in the specification (for exampleanode.properties.thickness (um)), the same path a pipeline uses to read it (see
Pipeline below).Studio
Studio
- Download measurements and analyses as CSV as well as parquet, at full resolution, from a format menu on their download buttons.
- Move, resize and dock the agent chat. Drag the panel or its launcher anywhere, resize it from any edge, or dock it to the right so the page reflows beside it. Minimized while docked, it becomes an edge tab that shows when a reply is running or has finished.
- Datasheet fields on cell specifications: charge and discharge temperature limits, maximum pulse current and duration, standard charge and cutoff currents, 1 kHz ACIR, DCIR with its pulse length and SOC, and cycle life. The protocol generator uses the charge currents, pulse limit and temperature limits.
- Section analyses are versioned. After a measurement is extended or re-exported, its analyses show once, labelled with the time their data runs through, with earlier versions in a menu and as tabs on the analysis page.
- A raw file can update the measurement it belongs to, extending it when the file continues an existing test rather than creating a duplicate.
- Raw-data review shows the file beside the measurement it matched, with both spans on one timeline and a different procedure flagged.
- Process pending files on the Raw Data page queues a project’s waiting files, including ones waiting for their cell.
- Drive-cycle uploads for simulations are easier. Drop several files at once to fill matching slots by name, use one profile for every slot, and see each file’s points, duration and current range as it is checked. An unreadable file is refused on its own row, and a protocol missing a drive cycle now fails with a message naming it instead of simulating without it.
- Formation detection handles noisy loggers and narrow voltage windows better.
- Faster page loads inside a project, and much faster simulation results for long solutions.
- Projects that have run simulations can be deleted. Deleting one failed with “Invalid reference”.
- ECM fits and validations with a start or end step work on stored measurements. They were rejected for a missing step column.
- Study validation with an open-ended step range no longer drops steps past the first 10,000. A step range on a measurement without step data is now an error.
- A rolled cycler file that starts a few seconds before the stored data ends is appended instead of being held for review.
- Cancelling a job, simulation, optimization or pipeline you can only view is now refused with a permissions error before anything is stopped.
- Icons and chips in table cells are vertically centred in every table.
Pipeline
Pipeline
DirectEntrycan keep part of a pipeline.DirectEntry(pipeline_id=..., keep=[...])takes only the named parameters from a completed pipeline, for example a half-cell fit’s kinetics without its coin-cell geometry.DirectEntrycan read a cell specification.DirectEntry(cell_spec_id=..., mapping={...})maps each parameter to a path in the spec (e.g."anode.properties.thickness","ratings.capacity") and converts each value to the unit in the parameter’s name, including offset units such as °C to K.provenancerecords where each value came from.SimplePipelineis deprecated in favour ofPipeline, which takes the same elements. It will be removed no earlier than November 2026; a migration guide is in the docs.
- A log-scale fit parameter reached through a chain of parameter links is no longer rejected as unused when the links are set out of order.
CycleAgeingmetrics read the right cycle when the solver skips an infeasible experiment cycle. Later cycles were shifted by one, reading the wrong values or failing the fit.- Post-fit validation retries an objective whose worker was lost, instead of dropping it
from
summary_statsandvalidation_results. - Least-squares fits with an objective initialized from
"Initial voltage [V]"or"Initial SOC [%]"no longer stop at their starting point when a fitted parameter also changes the initial state. - Creating a parameterized model no longer fails when a custom model has a lithiation or delithiation parameter without its counterpart.
Python API
Python API
client.simulation.protocol()andprotocol_batch()acceptprotocol_idto run a saved protocol, andprotocol_batch()acceptsconditions, an explicit list of runs each with its own parameters.client.simulation.get_statuses(simulation_ids)returns many statuses in one call.client.simulation.delete()andclient.parameterized_model.delete(), so a project holding either can be cleaned up and deleted from the SDK.client.cell_measurement.time_series(..., row_range=(start, stop))downloads only that window of rows.- Simulation configs are checked for unknown keys. A misspelt or misplaced key raises
a
ValueErrornaming it, where it was previously ignored. - A pipeline data fit reports its best cost in
fit.cost. client.simple_pipelineis deprecated. Each method warns and names itsclient.pipelineequivalent.POST /cell_measurements/exportacceptsformat="csv", andGET /analyses/{id}/csvdownloads an analysis as CSV.- Analyses created without
columnshave them filled in from the uploaded file.
Data Processing
Data Processing
DataLoader.from_dbwithfirst_step/last_stepdownloads only the rows those steps cover instead of the whole time series — a small fraction of the data for one cycle of a long test.
Protocol Simulator
Protocol Simulator
- BioLogic
|Q|limits are supported, so a partial-discharge drive cycle stops at the charge it should. Limits relative to an earlier sequence’s charge warn instead of being guessed. - A BioLogic protocol whose drive-cycle table doesn’t match its step asks for the profile file instead of failing to load.
- BT-Test protocols export C-rate step ends.
- Current limits in C-rate mode in BioLogic EC-Lab and BT-Test protocols are read as C-rates. A C/20 taper had been read as a current in mA or A.
Skills
Skills
run-simulationscovers running a saved protocol byprotocol_id, explicit run lists withconditions,get_statuses()anddelete().manage-cellscovers downloading part of a time series withrow_range;manage-projectscovers deleting parameterized models.run-pipelinesanddiscover-apimarkclient.simple_pipelineas deprecated.
manage-projectsanddiscover-apishowclient.studymethods with the resource ids first andproject_idlast, matching the SDK.
Tag your measurements
Measurements can carry free-form tags — “baseline”, “rpt”, “batch-7” — added the way you would in Notion: type to find one of the project’s existing tags or create a new one. Tags match regardless of case and reuse the project’s existing spelling. Click a tag chip in any measurement table to filter by it, and a second to narrow further; tag several measurements at once; and find measurements by tag in global search. The spec and instance pages gain the tag column and filter, plus a type filter.Through the API, measurements accepttags on create and PATCH, lists filter with
tags_all / tags_any, GET /cell_measurements/tags lists the project’s tags with
usage counts, and POST /cell_measurements/tags/bulk adds and removes tags on up to
1000 measurements.Cell batches and CAD models
- Batches are records of their own. A cell’s manufacturing lot used to be a text
field on each instance. It is now a batch belonging to a cell specification, with a
name, notes, manufacture date and properties. Existing batch text has been converted
into batches. Deleting a batch keeps its instances. This changes the API: cell
instances replace
batchwith a writablebatch_idand a read-onlybatch_name, and batches have their own endpoints under/cell_specifications/{id}/cell_batchesand/cell_batches/{id}. - Attach a CAD model to a cell specification (
.step,.iges,.stl,.obj,.ply,.glb,.off, up to 100 MB). A rendered thumbnail shows on the spec page and in the Cells table.
Lab: utilization history and channel checks
- A Utilization history page shows the cycler fleet over time as bars stacked by state (occupied, stale, free, out of service), from 30 days to 10 years, daily to annually, as a share or as a channel count. Open it from History under the utilization figure.
- Scheduling checks channel ratings. The Schedule dialog shows the voltage and current range the protocol reaches, and flags any channel whose ratings it would exceed (“Draws 7.5 A, rated 5 A”) or whose ratings are unknown. It warns but does not block.
- A test request shows what actually happened once it starts: the channel and window it ran on, a link to the measurement it produced, actual against estimated duration, and live channel data while it runs. Schedule is now the first row action in the Test Scheduler.
Studio
Studio
- Simulate a protocol from its own page. A Simulate button runs the saved protocol against a cell and model you choose, with its inputs prefilled and comma-separated values sweeping. Full setup opens the full form with the protocol preselected.
- Looping protocols no longer need a setting raised. Max backward jumps now defaults to 1000 and has left the simulation forms; a simulation that exceeds it offers Rerun with higher limit.
- Cycles plots for every simulation, not only Cycle Aging (EIS excepted).
- Auto-generated analyses open on a plot suited to their kind: retention against cycle for cycling, capacity against C-rate for a rate test, resistance against SOC for a pulse sweep, charge and discharge capacity for formation.
- Rate-capability analyses record each step’s start and end voltage, so a step that began below the upper cutoff is visible as such rather than looking like poor rate capability.
- Analysis detection covers more test shapes. Staircase charges and pulses logged in stages are read as one load, GITT and incremental-OCV titrations are found as pulse sections, capacity-capped rate tests keep their slow and fast steps, and a record that changes voltage window between tests (formation then rate tests, for example) reads each test against its own window. Stored analyses have been re-derived.
- Invite a member as Member or Admin. The Members invite box has a role choice defaulting to Member; inviting someone who is already a member keeps their role.
- Faster time-series loading for large measurements, which now fetch only the part of the file a plot needs.
- Deleting a study says its simulations are kept, and how to delete them first if you want to. Study simulation counts stay current.
- The project members panel says clearly when everyone in the organization is already on the project.
- Simulation actions in study, model and protocol grids now show only when you can carry them out.
- The Cells table gives the name column most of its width; measurement tables beside a details card no longer hide their toolbar on a laptop screen.
- Project Contributors can create pipelines. Creating one failed for members whose organization role was Member.
- The protocol generator no longer puts cutoffs on its own safety limits. A step ending on or past the protocol’s safety limit is now an error, so a generated test no longer aborts in its first cycle.
- Older Data Fit and Validation results draw their plots again, for jobs from before March 2026 that showed a legend and no plots.
- Adding a time-series plot to a simulation in a study loads it. It could sit on “Loading variables” indefinitely.
- Comparing measurements keeps the Cycles tab when both have cycle data.
- Table search is consistent as you type: a whole word no longer returns more loosely related rows than a partial one.
- The specification-name filter on the Measurements list applies. It showed the pill but kept every row.
- A material’s Used by cell specifications table no longer empties on scroll.
- The optimizations list and the lab utilization plot fill the page height.
Pipeline
Pipeline
iwp.Parameteris immutable. Theset_*methods are replaced by copies:with_bounds,with_initial_value,with_fitting_scale,with_normalize,with_priorandwith_initial_guess_distribution. Assigningp.boundsorp.initial_valueraises, naming the method to use instead.- A half-cell
GITTModelcan start from"Initial voltage [V]". It used to fail, or, with a full-cell parameter set, start at the wrong voltage.
- Objective-level constraints are applied with every SciPy optimizer.
ScipyMinimize(all methods) andScipyShgosilently ignored them. - The regularization docs now state that a penalty contributes
w * fun**2, notw * fun, sofunshould not be squared beforehand.
Python API
Python API
- Manage memberships from the SDK.
client.organizationgainsmembers(),get_member(),invite(),set_role(),deactivate(),reactivate(),resend_invite()andremove();client.projectgainsroles(),add_member(),invite_member(),update_member()andremove_member(). Invites take a role and default to Member. client.analysis.create(..., plots=[...])stores plot presets for an analysis, validated against its columns.- The MCP server can run simulations, with
run_simulation,run_simulation_batchandwait_for_simulations. POST /jobsis retired and returns410 Gonenaming the endpoint to use instead:/pipelines,/simulations/with-template/batch,/optimizationsor the ECM fit endpoints.
- A malformed id returns
400, not500— for exampleclient.job.cancel(None). - NaN or Infinity in analysis metadata returns
400naming the offending key, instead of500.
Data Processing
Data Processing
generate_experimentsplits a CC-CV charge logged as one step into a CC step and a CV step, so long cycling replays stay within the cell’s voltage window. Passsplit_cc_cv=Falsefor the previous behaviour.- Step typing works for sub-mA coin-cell data. Rest and constant-current thresholds
scale with the cell’s rated capacity (pass
cell_spec), or with the data’s own current, instead of typing every step as Rest. - Unparseable numbers warn. Values like
"N/A"in voltage or current columns are reported with the column and examples rather than silently becoming null. - Step labels and groups are removed.
iwdata.steps.label_*andvalidateare gone, steps no longer carryLabel/Group number, and thegitt_to_ocptransform is removed (userest_to_ocp).
- Neware BTSDA flat CSVs map
Cycle Index/Step Index, so cycles no longer collapse into one, and capacity and energy columns read as floats. - The empty-column warning from Excel readers is silenced.
Skills
Skills
run-pipelinesreplacesrun-simple-pipelines, steering fits to regular pipelines so they appear in the web app.run-simulationscovers running simulations through the MCP server.discover-apilists the new membership methods;manage-cellsdocuments analysis plot presets, measurement tags and cell batches;process-datadocuments passing a cell spec for coin-cell step typing.
Stacked and multi-series plots
Measurement time-series plots gain stacked rows, the way a cycler’s own software lays them out. Add row puts a new band under the plot on the same x axis, each with its own left and optional right axis, and a single hover box reads every band at the cursor. Every line on an axis shares that axis’s colour and differs by dash, so matching a line to its scale never depends on colour alone. The right axis of the first row is now drawn dotted.Analysis plots draw more than one series. Split a table by a text column (charge vs discharge pulses, for example) to get one line per value instead of a zig-zag joining them, overlay several columns, put one on a right axis, and stack rows as on the measurement plot. Analyses can carry named views — OCV and resistance against SOC, pulse power against SOC, capacity against C-rate — and the view on screen can be linked directly.Pipelines record exactly which data they ran against
Every pipeline element now records the measurements and time windows it read. A new panel on the pipeline page shows each pinned span next to the measurement’s current span, so you can see at a glance when a measurement has grown since a fit was run, or is no longer available. Existing pipelines have been backfilled.Studio
Studio
- The Validation Report compares temperature as well as voltage when the model is thermal and the measurement has a temperature channel. A pair whose measurement was never instrumented says so in one line rather than drawing empty axes.
- Simulation time-series plots take a step filter in the same syntax as the
measurement filters (
1:3,5), can use any loaded column as the x axis (voltage against capacity, for example), and show cycle and step on hover. - Validation sections load in a single request, and returning to the full view after zooming no longer refetches.
- Simulation results load faster, as compact files the page can zoom within without going back to the server.
- Parameterized-model lists are lighter for projects with uploaded custom models, which were sending the full model with every row.
- The in-app assistant starts answering within a few seconds. It now says what it is looking up before it looks, and finds a record you name by searching for it rather than walking the whole project.
- Fit progress is tracked per array element and per start, so a multistart or array fit reports each run separately.
- Global search opens a cell instance at its own page, rather than its specification’s list of instances.
- No white flash when loading the app in dark mode.
- Name columns keep a usable width on narrow screens; the parameterized-model ID column is shorter and copies the full ID on click.
- Pulse sections find every pulse. Short pulses were rejected whenever the same record also held much longer steps, so a pulse test could report under half of its resistance values. A pulse section now also spans the discharges and rests between its pulses, a rate ladder run in duplicate is one ladder, and cycling whose cut-off drifts is counted rather than dropped. Existing analyses do not recompute on their own; new and re-run records carry the corrected numbers.
- Maccor sub-procedures are read as siblings. Three sub-procedures called in turn were read as nested four levels deep, with every boundary one call late.
- Variables evaluated later on a stored simulation now match the solve. On a simulation started from a set initial SOC, electrode and electrolyte potentials computed after the fact were offset (by up to ~0.7 V on a DFN). Affected stored results have been corrected.
- Design optimizations honour the model’s options, including its degradation mechanisms. Previously a design objective ran against a model that could not degrade, so every degradation mode reported zero while the job completed normally. Models saved in the current configuration format were also rejected outright.
- A pinned time window combined with a first/last step selects the right data. It used to either fail with an unexpected error or fit a slice offset from the intended one. A window that excludes the chosen steps is now a clear error naming the span those steps cover.
- Organization Admins can choose a project role when adding members. The role dropdown was empty for them; a failure to load roles now shows an error with Retry.
- Creating a study opens it, so the next simulation goes into the new study rather than the one you were on.
- The Protocol column filter is back on a study’s simulation list.
- The simulation form clears a stale cell or model remembered from another project instead of showing a red “not found” error.
- Pickers say they are loading while loading instead of “No options”, which read as “none exist” — in the channel picker, protocol groups and template pickers among others.
- A zoomed plot frames a newly added axis on the visible window, not on data just off screen, and zooming back out is instant.
- The Raw Data page no longer flickers on background refreshes.
- Table cells no longer show through the scrollbar beside the row-actions column.
- Older pipelines open reliably. Pipelines that ran before late August could fail to load.
Pipeline
Pipeline
CycleAgeingscores a target only where it has values. ANaNin a target column now means “not measured here”, so a resistance measured on alternate check-ups can be fitted directly instead of being interpolated first.- A fit can target a measurement’s stored analysis. Point a
CycleAgeingobjective at one measurement — its steps give the experiment and its analysis the targets — withionworksdata.AnalysisLoader. - The fit trace is always recorded, whatever progress sink is in use, so
plot_trace()works alongside printed or hosted progress.TraceLoggerSinkis deprecated.
- Objective-level
penaltiesandconstraintsare applied. They were accepted and echoed back but had no effect on the fit, and a submitted config using a symbolic penalty was rejected by validation. - A
CycleAgeingfit whose experiment comes from a stored measurement can now be built withionworks_schemaand submitted. - Fixed a rare failure of multistart half-cell OCP fits when a capacity sweep flattened against a voltage limit.
Python API
Python API
- Simulation results download as parquet.
get_result()still returns aSimulationResult, fetched faster; the new/simulations/{id}/time_series/downloadand/simulations/{id}/steps/downloadendpoints redirect to the files directly. - Large uploads are more robust. Files from 32 MiB use a multipart transfer, and an upload that hits a gateway timeout is retried once that way.
- An explicit
nullin aPATCHclears a nullable field — for example a cell specification’sform_factor,manufacturerornotes, or a model’sdescription. Omitting a field still leaves it unchanged.
- A refused write returns
403. Updating or deleting a record your key cannot change used to return500or204, even though nothing was changed. - Fit results are available the moment a job completes. Reading plots straight after completion could intermittently fail with “No plots are stored”.
Data Processing
Data Processing
AnalysisLoaderloads a measurement’s stored analysis as fit targets.
DataLoader.generate_experimentkeeps cycles and cut-offs. It returned one cycle per step and dropped every termination condition. It now returns one cycle per cycle count with the recorded cut-offs. This changes the shape of a generated experiment, and existingCycleAgeingfits usingexperiment="from data"will produce different (correct) numbers.
Skills
Skills
manage-cellslists the fixed columns of the steps, cycles and time-series tables, so an agent can use them without a discovery call.run-simple-pipelinesdocuments using stored measurements as inputs, with pinned time windows.
Invite a collaborator straight into a project
Bring someone into a project with just their email address — a partner at a supplier, a consultant, a colleague who has never signed in here. They do not need to be in your organization first, and they do not need an account at all.One step does the whole thing: an unregistered address is sent a sign-up invitation, anyone outside your organization is added to it at the least-privileged level, and they land in the project with exactly the role you picked. Someone already in your organization keeps the role they hold, so inviting a fellow Admin into a project can never change their standing elsewhere. Inviting by email grants organization membership, so it sits with organization Admins; Project Admins continue to add existing members to their own projects.The app now lives at the site root
Links to everything in the app are shorter. A project is/projects/<id>,
your account is /account, organization settings is /organization-settings —
the /dashboard segment is gone from every page. It said nothing (everything
you see while signed in sat under it) and it was carried by every link you
paste into a message, every documentation URL, and every link the Python SDK
mints.Everything you have already shared keeps working. Any /dashboard link
redirects to the same page at its new address, query string and anchor intact —
bookmarks, links in notification emails sent months ago, and links produced by
older SDK builds all land where they should.Studio
Studio
- The material detail page shows who created it. Creation has been recorded all along; there was no name to display until now. Materials created before the field existed simply omit the row rather than showing a blank.
- Rate-ladder specific capacity is exported. Discharge and charge specific capacity now flow out alongside their absolute counterparts for the rate-capability sections. A cell whose active mass is unknown emits the absolute figures as before.
- Analysis plots open on something worth looking at. A plot used to default to the first two numeric columns, which on a section table meant drawing the row’s own index against a second way of counting the same rows. Axes are now chosen by what the columns mean — a cycling analysis opens on capacity against cycle, a pulse section on internal resistance against cycle. Both dropdowns still offer every numeric column.
- Faster pipeline pages, and bulk actions that no longer move megabytes. Reading a pipeline’s elements, and cancelling or resubmitting them in bulk, were each carrying the full configuration and results of every row they touched, none of which was read. Cancelling a large selection is the most noticeable.
- Formation cycles are grouped by their opening charge. A formation is the one case where a cell arrives empty, so its cycle is led by the charge rather than the discharge. Grouping the other way left out the opening charge — the large, irreversible one that formation exists to measure — which distorted first-cycle coulombic efficiency.
- A constant-voltage hold counts toward its cycle. The taper that finishes a CC-CV charge starts and ends at the ceiling, so it was not joined to the cycle and charge capacity covered only the constant-current leg. On a C/20 taper that is roughly 9% of the charge. The hold, and the rest that follows it, now belong to their cycle.
- Rate ladders keep their fastest rungs. A ladder made of charges was judged by where the cell had relaxed to during the preceding rest rather than where the load began, so faster rungs were the ones dropped. A seven-rung ladder now reports seven, and the capacity retention computed against them follows. Existing analyses do not recompute on their own; new and re-run records carry the corrected numbers.
- A pipeline can build on an earlier fit. An entry naming where its starting parameters come from — a completed pipeline, or a JSON file — now submits. The reference is resolved to real values as you submit, against your own permissions, so an unreachable one is an immediate, explanatory error on the request.
- The right-hand y-axis on a measurement plot can be cleared again. Once a series was chosen there was no way back to an empty right axis — the “None” option disappeared and the last series could not be removed. Every right-axis series now has a remove control, labelled “Clear right axis” when it is the last one.
- Single-point plots render. A trace with exactly one point was drawn as a zero-length line, which is invisible; it now shows as a marker, with the axes framed proportionally around it.
- The account page no longer claims you belong to no organizations while it is still loading them, or if the request fails. That message now appears only when it is actually true.
- The project members panel no longer hangs on “Loading members…” when there is no organization context; it says so instead.
- An experiment with no description falls back to its protocol name rather than the literal text “Description not available”.
- A Project Viewer no longer sees an empty, unlabelled actions column on the parameterized-model lists. The menu items were already hidden; the column itself is now omitted when none of its actions are available.
- Stored degradation-model parameters are cleaned more thoroughly, including ones a model only reveals while it is being built, and the result is verified against a fresh model before it is saved.
Python API
Python API
- A value that cannot be sent to the server now fails where you wrote it, naming the field. A live model object, a callback, or a logger placed in a configuration field used to survive locally, arrive as its text representation, and fail server-side far from the cause. Parameter mappings are unaffected — functions and array data in a parameter set are converted as they always were.
Every section of a record becomes an analysis
When a cycling record finishes processing, the platform now measures each section it found — a formation, a rate ladder, a pulse train, a stretch of cycling — and saves one analysis per section against the parent measurement. The numbers are stored next to every other extracted feature rather than recomputed each time a page asks for them, so they are queryable, plottable and downloadable like anything else.One analysis per section, not one per record: the sections measure different things, and a section that occurs twice — two stretches of cycling at different rates — is two results rather than one. Each carries the window it was measured over, the metrics it produced, and a note saying why any number is missing. Rows the platform derived itself are flagged as such, so a view can separate them from analyses a person uploaded.Two new families of metric come with it, both of which need the cell rather than the record:- Specific capacity. Every capacity gains a counterpart in mA.h.g⁻¹, computed from the instance’s active mass.
- Instance C-rate. The existing rate divides by the capacity this record’s window happened to reach; the new one divides by the capacity the cell actually holds. On a real rate ladder that is the difference between reading 0.16 / 0.39 / 0.79 / 1.58 C and reading the 0.2 / 0.5 / 1 / 2 C rungs the ladder was run at.
A timeline of what ran when on a cell
The cell instance page gains a Timeline: every measurement on that cell drawn on one shared time axis, docked to the bottom of the viewport as a title bar that expands on demand. The grid answers “what exists”; this answers “when, and with what gaps” — the question a date-sorted list can only be read one row at a time to approximate.Runs that don’t coincide sit on a single line with the name written inside each bar. The solid bar is what the cell actually recorded; where the logged end time disagrees, it is drawn beside it — dashed out to a later logged end, or marked at an earlier one — because the two disagree often enough to be worth seeing.Pipeline pages answer from the pipeline, not from its jobs
A pipeline’s progress is now computed server-side and served per element, so opening a pipeline no longer means the browser fetching a job and its hundred children one request at a time. On a large multistart fit that was hundreds of requests in a couple of seconds, enough to trip a rate limit with two people on the same page. The page now makes a handful.Alongside it, a cancelled pipeline is now terminal on the wire. Pipelines publishis_terminal and is_failed directly, so a client waiting on one stops
as soon as it is cancelled instead of polling to its timeout and raising a
confusing error — and a status added later classifies itself for clients that
have never heard its name.Confidence intervals and sensitivity as pipeline elements
LinearConfidenceInterval and SobolSensitivity are now pipeline
elements you can add after a fit, returning typed results that decode
client-side with no extra client code. They run as backend jobs, which is the
only practical home for a Sobol analysis, and reuse the same recipes the
pipeline library already ships.Studio
Studio
- Drag files straight onto a project’s Raw Data table to upload them — the same gesture as a file drive — with a progress bar, a cancel, and new rows appearing at the top as they land. The upload page still works as before.
- The raw data grid fills the viewport height instead of stopping at a fixed box.
- The analysis preview reads every analysis the platform writes. Previews of compressed results failed to open; they now decode in the browser.
- A file that could not be parsed now stays failed instead of flipping back to “waiting for a cell” with an Attach button that could never succeed — and a file whose data cannot be rebuilt fails once, terminally, rather than being retried on every cell that is created.
- Rows appear during an upload into a project that had none. The table only refreshed while something on screen was already in flight, so a first upload showed a progress bar over an empty table.
- A measurement created from a raw file now carries its whole header — cycler, channel, operator, instrument, cell label, temperature setpoint, software version, export provenance and the test’s start time — rather than only the procedure name. Nothing downstream can recover it once the file has become a measurement, so this was the only place to write it.
- Section detection reads its voltage window from substantial loads only. A brief pulse on a depleted cell could define the window, which collapsed a whole rate-capability record into one bogus capacity check. Pulse grouping also tolerates the cycler’s own timing jitter, so a train of 20 pulses stamped 9.000001 s no longer loses several of them.
- Large batches of fits size their submission limits per user, so one user’s burst no longer eats the headroom of everyone sharing the platform.
- A simulation that asks for an output it cannot produce is now refused when
you submit it, naming the variable and suggesting the nearest real one,
rather than completing with the column quietly missing. Note the behaviour
change: such a request used to return a simulation and now returns a
400. Nothing that produced correct output changes, and a refused request creates nothing, so correcting the name and sending it again works. Separately, a variable that fails while results are assembled now costs only its own column instead of every variable requested alongside it.
Pipeline
Pipeline
- MSMR site fractions that did not sum to 1 were being accepted silently. Under one of the constraint methods the fit could return fractions summing to 0.885 or 1.72, which effectively rescales the electrode capacity — a fit could look excellent at ~2 mV RMSE while the parameters were unphysical. The fractions are now normalized, a post-fit check names the sum and the remedy if they still drift, and the stricter constraint method fails loudly rather than reporting a bad number.
- An MSMR half-cell fit keeps its data’s capacity origin. The capacity column was being re-zeroed on the first point, so the model was compared against a grid shifted by whatever a cycler export happened to start at, and the discarded offset reappeared as a wrong lower excess capacity — a physical quantity that feeds downstream state-of-health calculations.
Python API
Python API
raise_on_failurenow covers cancellation, so a cancelled pipeline raises rather than returning as though it had finished.
- The extra-variables example and its field documentation asked for electrode-resolved names their model does not have, so they never produced the column they demonstrate. Both now request anode and cathode potentials, which the quick model exposes.
Skills
Skills
- The parameterize templates now read model-vs-data channels off the typed result object rather than assembling them by hand, and gain a section on fitting a parameter per objective — both the fixed-per-objective and the fitted-per-objective forms, which the granularity guidance previously described without showing how to express.
- discover-api points at the typed series accessor, so an agent reading the reference before an operation finds the one-call path rather than only the raw two-call read.
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.