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

# Series vs. Figures: the data model

> What actually gets stored per experiment, and why Series and Figures behave differently when you try to overlay them.

Every Experiment can carry four kinds of output. Config and Summary are simple; Series and Figures are where people get tripped up, because they look similar in the app but behave differently.

## Config and Summary — small key-value facts

<Frame>
  ```
  Config   temperature_c = 65        (an input the run was given)
  Summary  mean_slope    = -37.71    (an output the run produced)
  ```
</Frame>

Both are small, named scalar values. They show up as columns and filters in the Experiments list, and as fields on the experiment detail page. The only difference is direction: Config is what you fed in, Summary is what came out.

## Series — the plottable measurement data

A **Series** is a named set of numeric x/y traces. It comes from one of two places:

1. **Automatic classifier detection** — Braven recognizes plain numeric arrays in your data and offers them as plottable fields.
2. **`braven.plot_series(name, y, x=...)`** — an explicit call in your pipeline script or SDK code (see [Write a pipeline script](/guides/write-a-pipeline-script)).

Series are the source of truth for interactive plots: fully explorable, one trace at a time, overlayable with any other Series in [Analysis](/guides/analyze-and-compare).

## Figures — uploaded matplotlib plots

When your script calls `braven.upload(fig, name)` with a **live matplotlib Figure**, Braven does two things:

1. Saves the rendered image exactly as `fig.savefig()` would — this is what you see in the experiment's **Images** tab.
2. Best-effort extracts the line/scatter data from the figure and stores it as an interactive companion — this is what shows up as a **Figure** tile in Analysis.

<Warning>
  A Figure is addressed as **one object**, not per line. All of its subplots and traces travel together — you can't pick out a single line from inside a Figure and compare it against something else. If you need that level of control, promote that specific trace to a first-class Series with an explicit `plot_series()` call.
</Warning>

### Why the distinction exists

Early on, every line inside every matplotlib subplot was tracked as its own Series. In practice this flooded every picker with hundreds of entries per experiment (one real experiment produced 783), and nobody actually compared individual fit lines across figures — people compare whole figures, panel by panel. So Figures are intentionally opaque, and Series stays reserved for data you explicitly asked to be plottable.

### Overlay rules

| You have...     | You can overlay it with...                                                                                                       |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Series + Series | ✅ Freely, from any experiments                                                                                                   |
| Figure + Figure | ✅ Panel-by-panel — axes 1 onto axes 1, axes 2 onto axes 2. Figures with a different number/layout of subplots refuse to overlay. |
| Series + Figure | ❌ Never — they don't share one plot                                                                                              |

## Interactive plot

An "interactive plot" isn't a stored thing — it's what Analysis renders at view time from one or more Series, or one or more Figures. Nothing about opening or overlaying a plot changes what's stored.

<Card title="See it in action" icon="chart-line" href="/guides/analyze-and-compare">
  Continue to the Analysis guide to see how Series and Figures actually get combined on screen.
</Card>
