Skip to main content

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.

A cell measurement represents a single experiment or test performed on a cell instance. Every measurement has a measurement_type that determines what data it stores and how you create it.

Measurement types

TypeStoresTypical use
time_seriesHigh-resolution cycling data with voltage, current, and time columns. Includes auto-generated step and cycle summaries.Battery cycling tests, EIS measurements, charge/discharge experiments
propertiesKey-value pairs with optional units. No file upload.Manual measurements like thickness, weight, internal resistance
fileOne or more uploaded files (images, PDFs, numpy arrays, etc.) attached to the record.Microscopy images, SEM photos, post-mortem analysis documents

Common fields

Every measurement — regardless of type — accepts these optional metadata fields:
FieldDescription
nameName for the measurement
protocol.nameProtocol description
protocol.ambient_temperature_degcTest temperature
test_setupcycler, operator, lab, channel_number
start_timeISO 8601 start time, e.g. "2026-03-15T09:30:00Z"
notesFree-form notes about the test

Time series

Time series is the default measurement type. It carries high-resolution cycling data and auto-generates step and cycle summaries on upload. The time series DataFrame must follow the data format — recognized columns include Time [s], Voltage [V], Current [A], Step count, and Cycle count. See uploading data for the full upload workflow.
import pandas as pd

time_series = pd.DataFrame({
    "Time [s]": [0, 1, 2, 3, 4, 5],
    "Voltage [V]": [3.0, 3.2, 3.5, 3.8, 4.0, 4.2],
    "Current [A]": [0.002, 0.002, 0.002, 0.002, 0.002, 0.002],
    "Step count": [0, 0, 0, 1, 1, 1],
    "Cycle count": [0, 0, 0, 0, 0, 0],
    "Step from cycler": [1, 1, 1, 2, 2, 2],
    "Cycle from cycler": [0, 0, 0, 0, 0, 0],
})

bundle = client.cell_measurement.create(
    cell_instance.id,
    {
        "measurement": {
            "name": "Formation Cycle 1",
            "protocol": {
                "name": "CC-CV charge at C/10 to 4.2V",
                "ambient_temperature_degc": 25,
            },
        },
        "time_series": time_series,
    },
)

print(f"Steps created: {bundle.steps_created}")
create() returns a MeasurementBundle containing the measurement record plus metadata like steps_created. See reading data to fetch a measurement back with its full time series, steps, and cycles.

Properties

Properties measurements store key-value pairs directly in the record — no file upload. Use them for manual or one-off measurements like thickness, weight, or internal resistance. Properties-specific fields:
FieldDescription
propertiesKey-value pairs. Use the quantity format for numeric values. Plain strings and numbers are also allowed.
measurement = client.cell_measurement.create_properties(
    cell_instance.id,
    name="Post-formation properties",
    properties={
        "thickness": {"value": 0.52, "unit": "mm"},
        "weight": {"value": 45.3, "unit": "g"},
        "internal_resistance": {"value": 12.5, "unit": "mOhm"},
        "visual_condition": "No visible damage",
    },
    notes="Measured after formation cycling",
)
You can include any of the common metadata fields (protocol, test_setup, start_time, notes) alongside the properties.
create_properties returns a Measurement directly, not a MeasurementBundle. Properties measurements have no steps or file uploads, so the bundle wrapper isn’t needed.

File

File measurements attach files (images, PDFs, numpy arrays, or any other file type) to a measurement record. Useful for microscopy images, SEM photos, X-ray CT scans, or post-mortem analysis documents. File-specific fields:
FieldDescription
filepathsList of local file paths to upload
validate_imagesWhen True, validates file headers match the extension before upload
file_metadataPopulated automatically by the server after upload (MIME types, dimensions, etc.) — read-only
bundle = client.cell_measurement.create_file(
    cell_instance.id,
    name="Post-cycling SEM images",
    filepaths=[
        "images/anode_surface_1000x.png",
        "images/cathode_cross_section_500x.png",
    ],
    notes="SEM images taken after 500 cycles",
)
To enable client-side image validation:
bundle = client.cell_measurement.create_file(
    cell_instance.id,
    name="Electrode images",
    filepaths=["photo.png", "scan.tiff"],
    validate_images=True,
)
To access files from an existing file measurement:
# List filenames in the measurement
filenames = client.cell_measurement.list_files(measurement_id)

# Download file contents directly
files = client.cell_measurement.download_files(measurement_id)
for filename, content in files.items():
    print(f"{filename}: {len(content)} bytes")
File measurements use a signed URL upload flow internally. The client handles the multi-step process (initiate, upload, confirm) automatically.

Next steps

Uploading data

End-to-end upload workflow: specs, instances, and measurements.

Reading data

List, filter, and retrieve measurements with their full data.