Skip to content

Hello, Zelos

The five-minute tour. One connection, one catalog search, one query, one chart, one live read — the loop every other notebook builds on.

You'll use: connect() · signals() and match() · query() · plot() · latest() · params

Run it

zelos live demo --backfill 5m --duration 30m    # terminal 1: demo data

Copy the notebook below into hello-zelos.md, then:

zelos notebook run hello-zelos.md

Re-run with a different window — no edit needed:

zelos notebook run hello-zelos.md --param window=-10m

The notebook

---
description: Connect, browse the catalog, query a window, chart it, read live values.
requires-python: ">=3.10"
dependencies:
  - zelos-sdk[notebook]
params:
  window: "-3m"
---

This notebook is your first five minutes with Zelos: connect to the agent,
find out what data it has, pull a window of it, and chart it. Every cell
below runs against the demo generator — start it in another terminal if you
haven't:

```python {.norun}
# In a terminal, not here:
#   zelos live demo --backfill 5m
```

Connect once. Later cells reuse the handle — all cells share one Python
process, top to bottom. A bare object on the last line of a cell renders, so
`agent` shows you what you connected to.

```python
from zelos_sdk import connect

agent = connect()
agent
```

## What data is there?

The catalog lists every signal that produced data recently. Glob it to narrow
it — `*` matches any run of characters anywhere in the path, so
`bus0/BMS_message/*` is every signal on that message:

```python
catalog = agent.signals()
catalog.match("bus0/BMS_message/*")
```

A catalog is also a mapping, so you can ask about one path directly:

```python
"bus0/BMS_message/cells.cell_0" in catalog
```

## Pull a window of samples

`query()` takes paths — exact or globbed — and a time window. `start="-3m"`
means "three minutes ago"; the window comes from `params`, declared in the
front matter and overridable per run with `--param window=-10m`.

```python
frame = agent.query("bus0/BMS_message/cells.*", start=params.window)
frame
```

The frame tells you what it holds: rows, time range, and one line per column
with its unit, type, and how many samples are not null.

## Chart it

`plot()` renders the frame. `short_names()` first, so the legend reads
`cell_0` rather than the full path:

```python
frame.short_names().plot()
```

## Read the current values

`latest()` answers "what is it right now" without a window:

```python
agent.latest([
    "bus0/BMS_message/status.battery_level",
    "bus0/BMS_message/cells.cell_0",
    "bus0/BMS_message/status.pack_current",
])
```

One path instead of a list gives you the single value, unit and all:

```python
agent.latest("bus0/BMS_message/status.pack_current")
```

## What am I running with?

`params` renders every declared name and the value this run resolved it to:

```python
params
```

That's the loop: **catalog → query → compute → chart**. From here, try
changing `params.window` at run time, or move on to the other example
notebooks — finding a weak cell, building a pass/fail gate, or replaying the
seconds around a fault.

What to notice

  • Cells share one process. agent is created once and used by every cell below — a notebook is one Python session read top to bottom.
  • A bare object on the last line renders. agent, frame, catalog.match(...), agent.latest(...) and params all print themselves with their metadata. You never need .to_pandas() to see something; that call is for handing data to pandas.
  • params.window comes from the front matter and is overridden per run with --param. The same file is both the document and the tool. See Parameters.
  • The {.norun} fence at the top renders as documentation but never executes — the demo command belongs in a terminal, not the kernel.
  • plot() is the chart. It emits Vega-Lite, which the app renders inline and an HTML export renders offline. No plotting library in dependencies. See Chart a frame.