braven
Python SDK for Braven, the experiment tracker for hardware and photonics R&D teams.
pip install braven
Install and login
pip install braven
python -m braven login
login asks for your backend URL and an SDK API key (braven_..., from
your Braven account's Settings → Watcher Keys) and saves them to
~/.braven/config.json. Every script on the machine picks the credentials
up automatically — no need to pass them around.
Direct logging (wandb-style)
The common case: a script you run yourself, logging config, metrics, and plots straight to Braven as it runs.
import braven
run = braven.init(name="My Experiment", company="My Company", project="My Project")
braven.config("radius_um", 55.0)
braven.config("gap_nm", 200.0)
braven.summary("q_factor", 18_400)
braven.summary("extinction_ratio_dB", 22.1)
braven.upload("spectrum.png")
braven.finish()
company/project are only required if your API key can see more than one
project — pass them to disambiguate.
Matplotlib figures
Pass a live matplotlib.figure.Figure to upload() instead of a file path
and the SDK saves the PNG for you (same as fig.savefig() would) and
extracts an interactive companion plot from the figure's line/scatter data,
so the experiment page shows a zoomable, hoverable chart alongside the
static image — no extra API to learn:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(wavelengths_nm, through_db, label="Through port")
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("Transmission (dB)")
braven.upload(fig, name="spectrum.png")
This works the same way whether the figure came from a script you run yourself or a script run through Braven's Pipelines tab — one code path, one behavior, no separate API for "give me a nice list thumbnail."
Prefer to log a plain array without a matplotlib figure at all?
plot_series() does that directly:
braven.plot_series("snr_vs_temp", y=snr_values, x=temperatures, x_label="Temp (C)", y_label="SNR (dB)")
Devices — multiple sensors/units in one pipeline run
Tag a value with a stable per-device key and the KPI name stays the same
across devices (no SNR_dev1, SNR_dev2) — the device becomes a separate
coordinate instead of a suffix. In a pipeline script, each device also
gets its own single-device Experiment under the run's Experiment (the
"parent") — get_device() returns a handle scoped to it:
for sensor_id, snr in results.items():
braven.get_device(sensor_id).log_summary("SNR", snr)
braven.log_summary("max_device_mismatch", spread) # parent-level, across all devices
Logging several values for the same device without threading a handle
through every call? set_device() sets an ambient current device for
subsequent bare calls, the device-scoped equivalent of how braven.init()
sets the ambient current run:
braven.set_device("SENSOR-4471")
braven.log_config("gain_db", 12)
braven.log_summary("SNR", 14.2)
braven.upload(fig, name="spectrum.png") # this device's own figure
braven.set_device(None) # back to parent-level logging
A device is auto-created on first sight and its history accumulates across
experiments — pass an optional type on first use
(braven.get_device("SENSOR-4471", "Photodiode")) to name what kind of
device it is; it's ignored once the device already exists.
A direct-logging Run's device handle (run.get_device(key), not the
module-level get_device()) has no parent/child concept — it still tags
device-scoped values onto rows of that same Experiment; Device.upload()
is pipeline-only.
braven.device()was renamed toget_device()/set_device()in 0.2.0 — calling the old name now raises with migration guidance rather than silently keeping the old shared-row behavior, since it changed what a device-tagged value actually means (its own Experiment, not a tagged row).
Pipeline scripts (run by the Braven worker)
If your script runs through Braven's Pipelines tab (server-side, executed by
the Braven worker against uploaded files) rather than on your own machine,
the SDK dispatches to the same functions automatically — no braven.init()
call needed, and no credentials to manage (the worker supplies the
experiment context):
import braven
def process(braven=None):
braven.log_config("lr", "0.001")
braven.log_summary("acc", "0.94")
braven.log_artifact("plot.png")
# Devices and matplotlib figures work exactly as in direct logging:
braven.get_device("SENSOR-1").log_summary("SNR", 14.2)
braven.upload(fig, name="spectrum.png")
braven.files (uploaded file → local temp path) and braven.params
(extracted parameters) are populated by the worker before process() runs.
Querying experiments
Read-only access to experiments already logged in Braven — no API key
required beyond what you already set up with python -m braven login, or
construct a client directly:
from braven import Braven
b = Braven("https://your-backend.example.com", api_key="braven_...")
exp = b.get("high temp run") # partial, case-insensitive name match
df = exp.file("data.csv").as_dataframe() # requires: pip install "braven[dataframe]"
print(exp.metadata) # {key: value} config/summary metadata
for f in exp.files:
print(f.filename)
b.get() also accepts a list of names and returns a list of Experiment
objects. b.experiments() returns lightweight summaries of everything
visible to the API key.
Cross-experiment analysis
Pull an explicit, frozen set of experiments out of Braven for local work (training a model, building a comparison plot — anything outside Braven), then log results back onto the same object so the record of what was analyzed can never drift from what was actually read:
analysis = braven.collect(
experiment_ids=["exp_1", "exp_2", "exp_3"],
name="Cross-lot yield comparison",
)
for exp in analysis.experiments():
df = exp.file("data.csv").as_dataframe()
# ... do local analysis ...
analysis.log_summary("mean_yield", 0.94)
analysis.upload(fig, name="comparison.png")
filter_token (copied from Braven's webapp "Copy as code" action) works as
an alternative to an explicit experiment_ids list — it's re-resolved to
concrete experiment IDs at call time, never stored as a live query.
Optional dependencies
requests is the only hard dependency. Everything else is optional and
imported lazily:
| Feature | Install |
|---|---|
.as_dataframe() on a downloaded file |
pip install "braven[dataframe]" |
Uploading a live matplotlib Figure (and its list thumbnail) |
pip install "braven[plots]" |
Contributing / issues
Source: github.com/bravenlab/braven-python. Found a bug or have a feature request? File it on GitHub Issues — that's the right place for anything specific to the SDK itself.
License
MIT — see LICENSE.
Metadata
Release files for braven 0.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| braven-0.2.4.tar.gz | 37.8 kB | With provenance | Details for braven-0.2.4.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| braven-0.2.4-py3-none-any.whl | Python 3 | none | any | Details for braven-0.2.4-py3-none-any.whl |
Total release size: 67.0 kB
Release files / braven-0.2.4.tar.gz
| Download URL | braven-0.2.4.tar.gz |
|---|---|
| Size | 37.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
89f3515360ba2af5ab631b6a57c13cc1fa7de0ffc2cf30cf8a60b5591f598d22
|
|
BLAKE2b-256 checksum How to use checksums |
808d1451e51b7ea9af544c57364db3903dbbb42cc4e630defee179784beaf240
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.
Transparency logRelease files / braven-0.2.4-py3-none-any.whl
| Download URL | braven-0.2.4-py3-none-any.whl |
|---|---|
| Size | 29.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e3fb5454e2c67a6d6f99e0edc3552a43d176d4befbdd5508b7737dd7b97cf5bc
|
|
BLAKE2b-256 checksum How to use checksums |
2620a5340aee2e9f3ee69600b95d202bc7514da7831c766956c2ed84e3f14338
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.
Transparency logSecurity for braven 0.2.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for braven-0.2.4.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.