> ## 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.

# Raw data

> Store original cycler files as-is, then link them to the measurements they produced for full provenance

Raw data records let you archive the **original files that came off your
cycler** — untouched — inside Ionworks Studio, then link them to the processed
[cell measurements](/data/measurements) they produced. This gives every
measurement a clear provenance trail back to its source.

Raw data records live under a [project](/core-concepts/projects-studies), not
under a specific cell instance. One raw file can feed many measurements, and
one measurement can be assembled from many raw files.

## When to use raw data

Use raw data records when you want to:

* Keep the untransformed cycler export (e.g. `.mpr`, `.res`, `.nda`, `.txt`,
  or a Neware / Maccor / Biologic file) alongside the processed
  [time series](/data/measurements#time-series) it was converted into.
* Trace a measurement back to the exact file — and file version — it came from.
* Store one source file that was split into several measurements (for example,
  a single test file containing formation + RPT + cycling that you uploaded
  as three separate measurements).
* Combine several source files into one measurement (for example, a run that
  was paused and resumed, producing two export files).

If you only care about the processed data, you do not need to create raw data
records — regular measurement upload is enough. Raw data is additive
provenance, not a replacement for [preparing data](/data/preparing-data) and
[uploading data](/data/uploading).

<Note>
  Raw data records store the file **as-is**. They are not processed into
  measurements automatically — you still convert your file with
  [`ionworksdata`](/data/preparing-data) and upload the resulting measurement
  separately, then attach the raw file for provenance.
</Note>

## Upload a raw file

Upload any file from a local path or an open binary handle. The client
derives the filename from the file path or handle:

```python theme={null}
raw = client.raw_data.upload(
    project_id=project.id,
    file="exports/cellA_formation.mpr",
    name="Cell A — formation export",
    metadata={"cycler": "Biologic VMP3", "operator": "Jane Smith"},
)

print(raw.id, raw.filename, raw.size_bytes)
```

**Arguments:**

| Argument     | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| `project_id` | Project the raw file belongs to. Required.                               |
| `file`       | Path (`str` or `os.PathLike`) or an open binary file-like object.        |
| `name`       | Human-readable label. Defaults to the file's basename.                   |
| `metadata`   | Free-form dict — cycler make/model, operator, channel, source path, etc. |

The returned `RawData` object has `id`, `project_id`, `name`, `filename`,
`content_type`, `size_bytes`, `metadata`, and timestamps.

## List, get, and download

```python theme={null}
# List a project's raw files, newest first
files = client.raw_data.list(project_id=project.id, limit=50)

for r in files.items:
    print(r.id, r.name, r.filename, r.size_bytes)

# Fetch one record
raw = client.raw_data.get(raw_data_id)

# Get a short-lived signed download URL
url = client.raw_data.download_url(raw_data_id)
```

`list` returns a paginated response with `items`, `count`, and `total`. The
`download_url` is signed and expires after a few minutes — request a fresh
one each time you need to download the file.

## Update and delete

`name` and `metadata` are patchable. The underlying file is immutable — to
replace the bytes, delete the record and upload again.

```python theme={null}
client.raw_data.update(
    raw_data_id,
    name="Cell A — formation export (re-labeled)",
    metadata={"cycler": "Biologic VMP3", "channel": 4},
)

client.raw_data.delete(raw_data_id)
```

Deleting a raw data record removes the stored file and clears any links to
measurements. The linked measurements themselves are **not** deleted.

## Link raw files to measurements

The provenance link is many-to-many and lives on the measurement side of the
SDK. Attaching is bulk and idempotent — re-attaching an already-linked file
is a no-op.

```python theme={null}
# Attach one or more raw files to a measurement
client.cell_measurement.attach_raw_data(
    cell_measurement_id=measurement.id,
    raw_data_ids=[raw.id],
)

# List the raw files behind a measurement
sources = client.cell_measurement.list_raw_data(measurement.id)
for r in sources.items:
    print(r.filename)

# Detach one link (does not delete the raw file)
client.cell_measurement.detach_raw_data(
    cell_measurement_id=measurement.id,
    raw_data_id=raw.id,
)
```

To go the other direction — find every measurement that was produced from a
given raw file — use `list_measurements` on the raw data client:

```python theme={null}
measurements = client.raw_data.list_measurements(raw_data_id)
for measurement_id in measurements.items:
    print(measurement_id)
```

<Note>
  Deleting a measurement removes only its provenance links, never the raw
  data record or its file. Raw files are independent, project-owned assets.
</Note>

## End-to-end example

Upload the processed measurement, then archive the original file and link
them:

```python theme={null}
import ionworksdata as iwd

source_path = "exports/cellA_formation.mpr"

# 1. Process the cycler file into the Ionworks format
data = iwd.read(source_path)

# 2. Upload the processed measurement
bundle = client.cell_measurement.create(
    cell_instance.id,
    {
        "measurement": {"name": "Cell A — formation"},
        "time_series": data,
    },
    validate_strict=True,
)

# 3. Archive the original file
raw = client.raw_data.upload(
    project_id=project.id,
    file=source_path,
    name="Cell A — formation export",
    metadata={"cycler": "Biologic VMP3"},
)

# 4. Link the raw file to the measurement it produced
client.cell_measurement.attach_raw_data(
    cell_measurement_id=bundle.id,
    raw_data_ids=[raw.id],
)
```

## Next steps

<CardGroup cols={2}>
  <Card title="Preparing data" icon="file-import" href="/data/preparing-data">
    Convert cycler files into the Ionworks format before uploading a measurement.
  </Card>

  <Card title="Uploading data" icon="upload" href="/data/uploading">
    Create cell specs, instances, and measurements via the Python API.
  </Card>

  <Card title="Measurements" icon="flask" href="/data/measurements">
    Time series, properties, and file measurement types.
  </Card>

  <Card title="Projects" icon="cubes" href="/core-concepts/projects-studies">
    Group raw data, studies, and simulations by research initiative.
  </Card>
</CardGroup>
