requested (with an estimated duration but
no channel); a scheduler later assigns a channel and a
[planned_start_time, planned_end_time) window, moving it to scheduled.
Planned measurements never create or mutate a real
cell measurement. When the real test starts, the actual
cell_measurement links back to the plan and moves it to in_progress — the
planned row stays as the request-and-schedule audit trail.
When to use it
Planned measurements are optional — you can still create measurements directly and setchannel_id at run time as described in the
Lab view. Use planned measurements when you want to:
- Track a backlog of tests requested against a project or a specific cell specification.
- Reserve future channel time so two schedulers don’t book the same channel and window.
- Separate the request (from a scientist or PM) from the scheduling decision (from a lab operator).
- Keep an audit trail of who requested and scheduled each test.
Lifecycle
Scheduling is fully manual — the scheduler picks the channel and times.
There is no automatic optimizer.
Reserving future channel time on a
scheduled plan does not make the
Lab view show the channel as occupied — only a running real
measurement does that. A plan reserves the calendar; a cell_measurement
reserves the current moment.
Fields
Names are unique per project (case-insensitive). Creating a plan with a
duplicate name raises
IonworksError with error_code == "CONFLICT" (HTTP
409). Use create_or_get to make creation idempotent.
Requesting a measurement
Create arequested plan with no channel; supply the protocol
to run, the cell specification you want tested, and an estimated duration. The
scheduler picks the concrete cell instance and channel later.
create_or_get to make the request idempotent by name:
Protocol validation
protocol_id must reference an experiment template
in your organization, and the underlying protocol must be ready to run against
a real cell — a planned measurement pins the exact test the lab will execute,
so half-configured protocols are rejected at request time rather than surfacing
as a failed run later.
Both create and update reject a plan with IonworksError (HTTP 400) when
the protocol_id:
- Does not exist in your organization. The error is
protocol_id '…' does not reference a protocol in this organization. - Still has unresolved inputs. Protocols authored with
input["…"]placeholders (see Parameterized inputs) must have every input resolved to a concrete value before they can back a planned measurement. The error lists the missing input names:protocol_id '…' references a protocol with unresolved inputs (C-rate, Temperature [°C]). Planned measurements require a fully-specified protocol — set all input values first. - Fails UCP validation. Structurally invalid protocols (bad step
definitions, inconsistent terminations, and so on — the same checks
POST /protocols/validateruns) are rejected with the underlying validation error attached.
Scheduling onto a channel
Assign a channel and a time window withschedule — a convenience wrapper
that moves a requested plan to scheduled.
scheduled in one call:
Picking a channel in the UI
The Schedule dialog’s channel picker shows each channel’s live availability and electrical ratings alongside its name, so you don’t need to jump to the Lab view to judge fit:- Primary line —
cycler / channel. - Ratings — max current and voltage window (e.g.
40 A · 0–5 V), pulled from the channel’s ratings. Unrated fields are omitted. - State —
free,occupied, orstale, derived from the same channel occupancy rules as the Lab wall. Out-of-commission channels are listed but disabled.
Scheduling conflicts
Scheduling is rejected when the window would collide with something already on the channel. Pick a different channel or window and retry.
Cancelling or completing an existing plan is always allowed, even after the
channel goes out of commission.
Listing and filtering
list is project-scoped and returns a PaginatedList[PlannedMeasurement].
Filter by lifecycle status, channel, or name.
Updating, cancelling, and deleting
schedule again with a new channel or window (or
update the individual fields). The server re-runs the overlap and
out-of-commission checks against the new values.
Test scheduler row actions
The Test scheduler page (per project, under Lab → Test scheduler) lists every plan in the backlog. Each row’s overflow menu offers the actions below. Which ones show up depends on the plan’s current status — the UI hides an action rather than letting you click it into an error.
Delete is deliberately gated behind Cancel: you cannot delete a live
request, a booked channel, or the record of a test that ran. Cancel first,
then delete if you want the row gone.
Copy is the fastest way to queue up several near-identical tests (same
cell spec and protocol, different notes or setup). It uses the same request
form as the Request test button, so the usual validation applies. The
new plan gets its own name and its own audit fields — the original is not
touched.
Linking a real measurement to a plan
You do not transition a plan toin_progress by hand. When the real run
starts, create the cell_measurement with planned_measurement_id set —
the backend links it and moves the plan to in_progress atomically.
- The plan is
scheduled. - The measurement is a
time_seriesmeasurement and carries achannel_id(aplanned_measurement_idwith nochannel_idis rejected). - The plan and measurement are in the same project and organization.
- The measurement’s
channel_idequals the plan’schannel_id. - If the plan has a
cell_instance_id, the measurement must run on that same cell instance.
status = scheduled, so the loser is left
unlinked (and logged as a warning).
After linking, channel occupancy on the Lab view is driven by
the running cell_measurement. The planned row remains as the audit trail.
Auto-watching the requester
When ascheduled plan links to a real cell_measurement and transitions to
in_progress, the requester (requested_by on the plan) is automatically
added as a watcher on the started measurement. Requesters see the run appear
under My Channels in the Lab view on their next lab
status refresh — no manual Watch click required.
Behavior:
- Fires on both link paths: creating a
cell_measurementwithplanned_measurement_idset, and patching a plan toin_progresswith astarted_measurement_id. - Idempotent — re-linking or re-transitioning does not create duplicate watches, and already-watching users stay watching.
- Only
requested_byis auto-watched.scheduled_byand lab operators are not; they can still watch manually from the channel or measurement pages. - Best-effort — a watch failure never fails the measurement create or plan update. The link and status transition still succeed.
Programs
A program is an organization-scoped catalog entry — a short, reusable name for a class of lab test such asFormation, Cycling, or RPT. Setting
program_id on a plan records which category the test belongs to, and the
value is copied onto the real measurement when it links back to the plan.
Programs are not free-text tags. The catalog is managed from Organization
settings → Programs, and the request and schedule forms pick from that list,
so the same category is spelled the same way by everyone. Names are unique
within the organization (case-insensitive).
Once tagged, the program is visible on the plan and in the test scheduler’s
planning table, so a lab operator sees at a glance which category a request
belongs to.
program_id is nullable everywhere it
appears. If your project and cell specification names already say what a test
is, you can ignore them.
Permissions
Planned measurement endpoints reuse the existingcell_measurement
permissions:
project_id
All client.planned_measurement.* methods accept an optional project_id.
When omitted it falls back to the project_id configured on the
Ionworks client (or the IONWORKS_PROJECT_ID env var).
Methods raise ValueError if no project_id is available from any source.
Next steps
Lab view
Set up the sites, cyclers, and channels that planned measurements schedule onto.
Measurements
Create the real
cell_measurement that links back to a scheduled plan.