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

# Ingest data

> Get data into Braven with the desktop watcher, or push it directly from your own scripts with the SDK.

There are two live paths into Braven today. Pick based on whether your instrument/software already drops files into a folder, or you already have analysis code.

<Frame caption="Both paths produce a Run — the Watcher's Run comes from a Pipeline execution, the SDK's Run comes from braven.init() directly. From Run onward, the process is identical either way.">
  <img src="https://mintcdn.com/braven-27cb4d27/EcUXmzOYqDkxSWbz/images/ingestion-workflow.svg?fit=max&auto=format&n=EcUXmzOYqDkxSWbz&q=85&s=600331a06f995401263fc574b027048c" alt="Diagram of the two ingestion paths — Folder Watcher through an optional Pipeline, or the Python SDK directly — both merging at a Run, which then writes Config, Summary, Series and Figures onto the Experiment" width="1040" height="380" data-path="images/ingestion-workflow.svg" />
</Frame>

<Note>
  A third path — syncing a **OneDrive** folder without installing anything locally — is visible in the app under Pipelines → Watch Folders, but is marked **"coming soon"** and not yet connectable. Use the desktop watcher below for folder-based ingestion for now.
</Note>

## Path A — Desktop Watcher (no code)

Best when your instrument or software already writes files to a folder.

<Steps>
  <Step title="Install and connect">
    From **Settings**, download **Braven Watcher** and run it. Paste your Watcher Key when prompted (see [Quickstart](/quickstart) if you don't have one yet).
  </Step>

  <Step title="Add a folder to watch">
    Add a folder in the desktop agent, or from the app: **Pipelines → Watch Folders**. Each watcher (machine) can watch multiple folders; assign each one to a Project.
  </Step>

  <Step title="Drop files in">
    Each **direct subfolder** of a watched folder becomes one Experiment. Deeper nesting rolls up into that parent experiment:

    ```
    WatchedFolder/
      ├── run_25C_chipA/        →  Experiment "run_25C_chipA"
      │     ├── data.h5
      │     └── notes.txt
      └── run_65C_chipA/        →  Experiment "run_65C_chipA"
            └── data.h5
    ```

    The agent waits until **every file in a subfolder finishes uploading** before the experiment is considered ready — so a pipeline never runs against a half-copied dataset.
  </Step>

  <Step title="Attach a pipeline (optional but recommended)">
    From **Pipelines → Watch Folders**, find the folder and assign a pipeline (write one first — see [Write a pipeline script](/guides/write-a-pipeline-script)). Every new experiment in that folder then runs it automatically. Watch progress in the **Activity** tab.
  </Step>
</Steps>

<Warning>
  The watcher keys off **filename**. A duplicated source file (e.g. a Windows/OneDrive "*— Copy*" artifact) currently becomes a duplicate Experiment — there's no content-based dedup yet.
</Warning>

### Worked example — temperature characterization

```
TemperatureRuns/
  ├── 2026_07_09 Temperature characterization TCS3448/
  │     └── GLINT4_20260709.ffm
  └── 2026_07_09 Temperature characterization TCS3448 - Copy (3)/
        └── GLINT1_20260714.ffm
```

Pipeline assigned to `TemperatureRuns`:

```python theme={null}
import glob
import h5py
import numpy as np
import matplotlib.pyplot as plt
import braven

# Files are in the working directory — just read them.
for path in glob.glob("**/*.ffm", recursive=True):
    with h5py.File(path, "r") as f:
        temp = f["temperature"][:]      # adjust to your dataset keys
        signal = f["signal"][:]

    slope = float(np.polyfit(temp, signal, 1)[0])
    name = path.split("/")[-1].replace(".ffm", "")
    braven.log_summary(f"{name}_mean_slope", f"{slope:.4f}")
    braven.log_series(f"{name}_signal_vs_temp", signal.tolist())

    fig, ax = plt.subplots()
    ax.plot(temp, signal, ".")
    ax.set_xlabel("Temperature (°C)"); ax.set_ylabel("Signal")
    braven.upload(fig, f"{name}_fit.png")
```

Every run becomes an experiment with a `mean_slope` summary value, a plottable series, and a figure — no manual work per run.

## Path B — Python SDK (direct logging)

Best when you already have analysis code and want to push results directly with explicit logging calls — no folder or pipeline required.

```python theme={null}
import braven

braven.init(name="High-temp run 1", project="TCS3448")
braven.config("temperature_c", 65)
braven.summary("mean_slope", -37.71)
braven.plot_series("signal_vs_temp", y=signal, x=temp, y_label="chipA")
braven.upload("fit.png")
braven.finish()
```

Each `braven.init(...)` call creates a new experiment, visible immediately in the app. Full reference: [Direct logging](/sdk-reference/direct-logging).

## Either way, you land in the same place

Both paths produce ordinary Experiments — same tabs, same ability to attach devices, same eligibility for Analysis and Reports. Neither path is "more first-class" than the other.
