> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 2026 09 07

<Update label="September 7, 2026" description="Raw cycler files upload, dedupe and attach themselves to cells; automatic section detection on a test record; header metadata for every cycler format; a protocol flowchart view">
  ## 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.

  Everything in the table narrows on the server — page, status, search and sort —
  so a project that accumulates a file per export still shows a row count that
  agrees with the rows.

  ## 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's `Procedure`, 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 and `goto` 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.

  <AccordionGroup>
    <Accordion title="Studio">
      **Improvements**

      * 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 `pending` and
        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.

      **Fixes**

      * 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.
    </Accordion>

    <Accordion title="Pipeline">
      **Improvements**

      * The typed result object gains a **`series` accessor** giving the
        full-resolution model-vs-data channels per objective, alongside the decimated
        `overlay` used for figures.

      **Fixes**

      * **Long array fits no longer run out of memory partway through.**
      * A `Validation` keyed 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.
    </Accordion>

    <Accordion title="Python API">
      **Improvements**

      * **`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.

      **Fixes**

      * **33 schema classes that their packages defined but never exported** are now
        importable — every `*Options` companion 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.
    </Accordion>

    <Accordion title="Data Processing">
      **Improvements**

      * **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.
    </Accordion>

    <Accordion title="Protocol Simulator">
      **Improvements**

      * **`DeltaSOC` is 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.

      **Fixes**

      * 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.
    </Accordion>
  </AccordionGroup>
</Update>
