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¶
Copy the notebook below into hello-zelos.md, then:
Re-run with a different window — no edit needed:
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.
agentis 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(...)andparamsall print themselves with their metadata. You never need.to_pandas()to see something; that call is for handing data to pandas. params.windowcomes 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 independencies. See Chart a frame.