Cell Measurement#
Client for managing cell measurements and time series data uploads.
For usage examples and guides, see Data API on docs.ionworks.com.
Cell measurement client for managing battery cell test data.
This module provides the CellMeasurementClient for uploading,
retrieving, and managing measurement data from battery cell testing. It
supports time series data (signed URL upload, redirect-based download),
file measurements (signed URL upload, redirect-based download), and
properties measurements (direct JSON).
- ionworks.cell_measurement.PROCESSING_TIMEOUT_SECONDS = 600.0#
How long to wait for the server to derive an upload’s steps before giving up. Generous: the work is queued, so it covers both a busy queue and a large file, and giving up only stops the waiting, never the processing.
- ionworks.cell_measurement.PROCESSING_POLL_SECONDS = 2.0#
Seconds between
processing_statuspolls while waiting.
- class ionworks.cell_measurement.CellMeasurementClient(client)[source]#
Bases:
objectClient for managing cell measurement data.
- Parameters:
client (Any)
- UPLOAD_TIMEOUT: tuple[float, float] = (10, 300)#
Default timeout for signed URL uploads as (connect, read) in seconds.
- __init__(client)[source]#
Initialize the CellMeasurementClient.
- Parameters:
client (Any) – The HTTP client instance for making API calls.
- Return type:
None
- list(cell_instance_id, limit=None, offset=None, measurement_type=None, *, name=None, name_exact=None, created_by_email=None, started_after=None, started_before=None, created_after=None, created_before=None, updated_after=None, updated_before=None, order_by=None, order=None)[source]#
List cell measurements for a cell instance with optional filtering.
Always returns a
PaginatedListwhich behaves like a regularlist. Uselimitandoffsetto control the page.- Parameters:
cell_instance_id (str) – The ID of the cell instance.
limit (int | None, optional) – Maximum number of measurements to return per page.
offset (int | None, optional) – Number of measurements to skip for pagination.
measurement_type (str | None, optional) – Filter by measurement type (e.g.
"time_series","file","properties"). If None, returns all types.name (str | None, optional) – Case-insensitive substring match on measurement name.
name_exact (str | None, optional) – Exact match on measurement name. Takes precedence over
name.created_by_email (str | None, optional) – Case-insensitive substring match on the creator’s email.
started_after (str | None, optional) – ISO datetime; return measurements started after this time.
started_before (str | None, optional) – ISO datetime; return measurements started before this time.
created_after (str | None, optional) – ISO datetime; return measurements created after this time.
created_before (str | None, optional) – ISO datetime; return measurements created before this time.
updated_after (str | None, optional) – ISO datetime; return measurements updated after this time.
updated_before (str | None, optional) – ISO datetime; return measurements updated before this time.
order_by (str | None, optional) – Column to sort by (
"name","created_at","updated_at","start_time").order (str | None, optional) – Sort direction:
"asc"or"desc".
- Returns:
All measurements for the cell instance.
- Return type:
- get(measurement_id)[source]#
Get a specific cell measurement by its ID only.
- Parameters:
measurement_id (str)
- Return type:
- detail(measurement_id, use_cache=True, include_steps=True, include_cycles=True, include_time_series=True)[source]#
Fetch measurement data.
Automatically adapts to the measurement type:
time_series: fetches steps, cycles, and time series data
file: fetches signed download URLs for files
properties: returns properties from the measurement metadata
Uses flat endpoints with parallel requests and downloads time series and steps via signed URL.
Use the
include_*flags to skip fetching data you don’t need, which avoids unnecessary requests. These flags only apply to time_series-type measurements.- Parameters:
measurement_id (str) – The ID of the cell measurement.
use_cache (bool, optional) – If True (default), check the local file cache before making API calls and store results for future use. Applies to time_series measurements (steps, cycles, and time series data). File URLs are never cached because signed URLs are short-lived.
include_steps (bool, optional) – Whether to fetch step data. Defaults to True. Only applies to time_series measurements.
include_cycles (bool, optional) – Whether to fetch cycle metrics. Defaults to True. Only applies to time_series measurements.
include_time_series (bool, optional) – Whether to fetch time series data. Defaults to True. Only applies to time_series measurements.
- Returns:
Measurement details with requested data fields. Fields not requested will be None.
- Return type:
- steps(measurement_id, use_cache=True)[source]#
Download step data via redirect.
Downloads the raw parquet file directly from storage.
- steps_and_cycles(measurement_id, use_cache=True)[source]#
Get steps and cycles in one call.
More efficient than calling
steps()andcycles()separately since cycles are derived from steps on the server.- Parameters:
- Returns:
Object with
stepsandcyclesDataFrames.- Return type:
- time_series(measurement_id, use_cache=True)[source]#
Download full time series as a parquet file.
The API endpoint redirects to storage; the HTTP client follows the redirect automatically and returns the raw parquet bytes.
- update(measurement_id, data)[source]#
Update an existing cell measurement.
- Parameters:
- Returns:
The updated cell measurement.
- Return type:
- Raises:
IonworksError – When attaching a
channel_idbreaks a channel rule:BAD_REQUEST(400) for a cross-project channel, a non-time_series measurement, or a missingstart_time;CONFLICT(409) for an out-of-commission channel or a time span overlapping another run already on that channel.
- delete(measurement_id)[source]#
Delete a cell measurement by measurement ID only.
- Parameters:
measurement_id (str)
- Return type:
None
- attach_raw_data(cell_measurement_id, raw_data_ids)[source]#
Attach raw-data records to this measurement (bulk, idempotent).
- detach_raw_data(cell_measurement_id, raw_data_id)[source]#
Remove one raw-data link from this measurement.
- watch(measurement_id)[source]#
Start watching a measurement (the “watch this channel” action).
A watch is per-user and keyed on the measurement, but reads as watching the channel the measurement is running on: it powers the lab “my channels” view (
client.lab.watched_channels) and clears itself once the test finishes, so you are no longer watching a channel whose test has ended. Idempotent – watching an already-watched measurement is a no-op.- Parameters:
measurement_id (str) – The ID of the (live) measurement to watch – typically the one on test on a channel (
channel.measurement.idin the lab status).- Raises:
IonworksError –
NOT_FOUND(404) if the measurement does not exist.- Return type:
None
- unwatch(measurement_id)[source]#
Stop watching a measurement (the “unwatch this channel” action).
Idempotent – unwatching a measurement you are not watching is a no-op.
- Parameters:
measurement_id (str) – The ID of the measurement to stop watching.
- Return type:
None
- list_raw_data(cell_measurement_id, limit=100, offset=0)[source]#
List raw-data records linked to this measurement.
- Parameters:
- Returns:
Raw-data records linked to this measurement.
- Return type:
- wait_for_processing(measurement_ids, timeout=600.0)[source]#
Block until the server finishes deriving uploads’ steps.
Polls
processing_statusuntil every measurement reaches a terminal state. Steps are excluded from the reads: requesting them is exactly what the server refuses while processing is in flight.Pass every id of a batch in one call rather than waiting on each in turn. The server processes uploads concurrently, so a batch takes about as long as its slowest member — and timeout is one deadline shared across the batch, where per-measurement waits would each carry their own and a stuck batch could hang for a multiple of it.
Waiting is not fail-fast: a measurement the server rejects does not stop the others being waited on. Every failure in the batch is reported together, once, when the batch settles.
- Parameters:
- Raises:
MeasurementProcessingError – If the server rejected any upload, or if any did not finish within timeout. Inspect
failuresfor the per-measurement reasons. A timeout does not cancel the work — it only stops waiting — so a measurement may still complete afterwards.- Return type:
None
- create(cell_instance_id, measurement_detail, validate_strict=False, rated_capacity=None, voltage_window=None, skip_checks=None, wait_for_processing=True)[source]#
Create a new cell measurement with steps and time series data.
Uses signed URL upload for better performance with large datasets. Data is uploaded directly to storage as parquet, bypassing backend JSON parsing. No database record is created until the upload is confirmed, preventing orphaned records if upload fails.
- Parameters:
cell_instance_id (str) – The ID of the cell instance to create the measurement for.
measurement_detail (dict[str, Any]) –
Dictionary containing ‘measurement’, ‘steps’, and ‘time_series’.
measurement: dict with ‘name’ (required) and ‘notes’. An optional ‘data_type’ key routes validation:
"ocp"for open-circuit potential data and"eis"for impedance spectra (validates the EIS columns and, in strict mode, theZ_Imsign and impedance magnitude). It is a client-side validation hint only and is not persisted. May also carrychannel_id(the physical lab channel the test ran on) andstart_time. Ifchannel_idis set, this measurement is a channel-linked run, which requiresstart_timeand forbids overlapping another run on the same channel — see the Raises note below and themanage-equipmentskill.time_series: pandas DataFrame or dict with time series data
steps: optional dict with pre-calculated steps data
validate_strict (bool, optional) – If False (default), runs only the always-on checks (positive current convention, time starts at 0, time monotonic, step count sequential, cumulative capacity/energy reset per step). If True, additionally runs: minimum points per step, cycle constant within step, time-gap check (> 5 h), and — when the corresponding inputs are provided — voltage continuity and consecutive-full-step / per-step capacity checks.
rated_capacity (float, optional) – Rated (nominal) cell capacity in A.h. Used only when
validate_strict=Truetogether with astepsentry inmeasurement_detail; enables the consecutive same-direction full-step check (hard) and the per-step capacity 500 % soft warning.voltage_window (tuple[float, float], optional) – Rated
(V_min, V_max)voltage window of the cell. Used only whenvalidate_strict=True; enables the voltage-continuity check that detects time series rows that are out of chronological order.skip_checks (Iterable[str], optional) – Names of strict-mode checks to skip while keeping
validate_strict=Truefor everything else. Prefer this over disabling strict mode entirely when only a single check is a known false positive for the dataset. Seeionworks.validators.STRICT_CHECK_NAMESfor valid names.wait_for_processing (bool, optional) –
Block until the server has finished deriving the steps, raising if it could not. Defaults to True, because this call returning is otherwise no evidence the upload was usable: the record is created before the file is parsed, so a file the server cannot read still yields a successful response.
Pass False when uploading a batch. The server processes uploads concurrently, so submitting all of them and then waiting on every id at once with
wait_for_processing()takes about as long as the slowest single upload, where waiting inside each call would take the sum.
- Returns:
Response containing the created measurement, steps count, and file path.
steps_createdis always 0 — steps are derived after the call returns, so the count is not known yet.- Return type:
- Raises:
MeasurementProcessingError – If
wait_for_processingand the server could not process the upload, or did not finish in time.MeasurementValidationError – If data validation fails. Non-strict checks cover the sign convention, time axis, step-count monotonicity, and cumulative reset. Strict-only checks additionally cover time gaps, voltage continuity, and consecutive same-direction full steps.
IonworksError – When a
channel_idinmeasurementbreaks a channel rule:BAD_REQUEST(HTTP 400) if the channel is in another project, the measurement is nottime_series, orstart_timeis missing;CONFLICT(HTTP 409) if the channel is out of commission or the run’s time span overlaps another measurement already on that channel.
- create_or_get(cell_instance_id, measurement_detail, validate_strict=False, rated_capacity=None, voltage_window=None, skip_checks=None, wait_for_processing=True)[source]#
Create a new cell measurement or get existing.
Always returns a
CellMeasurementregardless of whether the measurement was newly created or already existed.- Parameters:
cell_instance_id (str) – The ID of the cell instance.
measurement_detail (dict[str, Any]) – Dictionary containing
measurementandtime_series(same ascreate()).validate_strict (bool, optional) – If False (default), skips strict validation. If True, runs strict validation including minimum points per step.
rated_capacity (float, optional) – Rated (nominal) cell capacity in A.h. Forwarded to
create()to enable the consecutive-full-step and per-step capacity checks.voltage_window (tuple[float, float], optional) – Rated
(V_min, V_max)voltage window. Forwarded tocreate()to enable the voltage-continuity check.skip_checks (Iterable[str], optional) – Names of strict-mode checks to skip. Forwarded to
create(). Prefer skipping a specific check over disabling strict mode entirely.wait_for_processing (bool, optional) – Forwarded to
create(). Defaults to True. Pass False when uploading a batch and wait on the ids together afterwards withwait_for_processing(). Note that a measurement returned because it already existed has processed long ago, so only the newly created ids are worth waiting on.
- Returns:
The measurement (newly created or existing).
- Return type:
- create_properties(cell_instance_id, name, properties, *, notes=None, protocol=None, start_time=None, end_time=None, test_setup=None)[source]#
Create a properties-type measurement (no file upload).
Use this for manual measurements like thickness, weight, or capacity that are stored as key-value pairs with units.
- Parameters:
cell_instance_id (str) – The ID of the parent cell instance.
name (str) – Name for the measurement.
properties (dict[str, Any]) – Key-value measurements using Quantity format for numerics. Example:
{"thickness": {"value": 0.52, "unit": "mm"}}.notes (str | None, optional) – Optional notes for the measurement.
protocol (dict[str, Any] | None, optional) – Protocol information.
start_time (str | None, optional) – ISO-formatted start time for the measurement.
end_time (str | None, optional) – ISO-formatted end time. Set once the test is complete; leave None while it is still running.
test_setup (dict[str, Any] | None, optional) – Test setup metadata.
- Returns:
The created measurement.
- Return type:
- ALLOWED_IMAGE_EXTENSIONS: frozenset[str] = frozenset({'bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'webp'})#
Allowed image file extensions for upload.
- create_file(cell_instance_id, name, filepaths, *, validate_images=False, notes=None, protocol=None, start_time=None, end_time=None, test_setup=None)[source]#
Create a file-type measurement by uploading files.
Uses a three-step signed URL flow: initiate (get signed URLs), upload each file, then confirm (create DB record). Supports any file type (PDFs, numpy arrays, images, etc.).
Set
validate_images=Trueto opt into client-side image validation when uploading image files specifically.- Parameters:
cell_instance_id (str) – The ID of the parent cell instance.
name (str) – Name for the measurement.
validate_images (bool, optional) – When True, validate that each file is a real image with an allowed extension before uploading. Defaults to False.
notes (str | None, optional) – Optional notes for the measurement.
protocol (dict[str, Any] | None, optional) – Protocol information.
start_time (str | None, optional) – ISO-formatted start time for the measurement.
end_time (str | None, optional) – ISO-formatted end time. Set once the test is complete; leave None while it is still running.
test_setup (dict[str, Any] | None, optional) – Test setup metadata.
- Returns:
Response containing the created measurement and steps_created (0).
- Return type:
- Raises:
IonworksError – If
validate_imagesis True and any file is not a valid image, or if upload fails.FileNotFoundError – If any file path does not exist.
- list_files(measurement_id)[source]#
List filenames in a file-type measurement.
- Parameters:
measurement_id (str) – The ID of a file-type cell measurement.
- Returns:
Filenames stored in the measurement.
- Return type:
- Raises:
IonworksError – If the measurement is not a file type or does not exist.
- download_files(measurement_id, use_cache=True, filenames=None)[source]#
Download files for a file-type measurement.
When
filenamesis provided thelist_filesround-trip is skipped, which avoids the slow storage-listing endpoint. Use this when you already know the filenames (e.g. from a previouslist_filescall or from the upload response).- Parameters:
measurement_id (str) – The ID of a file-type cell measurement.
use_cache (bool, optional) – If True (default), check the local file cache before downloading and store results for future use.
filenames (list[str] | None, optional) – Explicit list of filenames to download. When provided, the
GET /cell_measurements/{id}/fileslisting call is skipped.
- Returns:
Mapping of filename to file content bytes.
- Return type:
- Raises:
IonworksError – If the measurement is not a file type, does not exist, or a download fails.
- get_file(measurement_id, filename)[source]#
Download a single file from a file-type measurement.
This is a convenience wrapper that fetches one file directly without any listing call, making it the fastest way to retrieve a known file.
- Parameters:
- Returns:
Raw file content.
- Return type:
- Raises:
IonworksError – If the measurement or file does not exist.