braven 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- braven-0.1.0/.github/workflows/publish.yml +51 -0
- braven-0.1.0/.github/workflows/test.yml +26 -0
- braven-0.1.0/.gitignore +8 -0
- braven-0.1.0/LICENSE +21 -0
- braven-0.1.0/PKG-INFO +202 -0
- braven-0.1.0/README.md +183 -0
- braven-0.1.0/braven.py +1642 -0
- braven-0.1.0/examples/ring_resonator_direct.py +216 -0
- braven-0.1.0/pyproject.toml +30 -0
- braven-0.1.0/tests/test_braven.py +269 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Fires on a version tag push (vX.Y.Z). Uses PyPI's trusted-publisher (OIDC)
|
|
4
|
+
# flow — no long-lived API token stored as a repo secret. Before the first
|
|
5
|
+
# tag push, the `braven` project's trusted publisher must be registered on
|
|
6
|
+
# pypi.org via the "pending publisher" flow (the project doesn't exist on
|
|
7
|
+
# PyPI yet the first time this runs) — see .scratch/public-python-sdk/issues/06.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags:
|
|
12
|
+
- "v*.*.*"
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install build tooling
|
|
26
|
+
run: pip install build
|
|
27
|
+
|
|
28
|
+
- name: Build sdist and wheel
|
|
29
|
+
run: python -m build
|
|
30
|
+
|
|
31
|
+
- name: Upload build artifacts
|
|
32
|
+
uses: actions/upload-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: dist
|
|
35
|
+
path: dist/
|
|
36
|
+
|
|
37
|
+
publish:
|
|
38
|
+
needs: build
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
environment: pypi
|
|
41
|
+
permissions:
|
|
42
|
+
id-token: write # required for PyPI trusted-publisher OIDC
|
|
43
|
+
steps:
|
|
44
|
+
- name: Download build artifacts
|
|
45
|
+
uses: actions/download-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
|
|
50
|
+
- name: Publish to PyPI
|
|
51
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pytest:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Install package + dev dependencies
|
|
23
|
+
run: pip install -e ".[dataframe,plots]" pytest
|
|
24
|
+
|
|
25
|
+
- name: Run pytest
|
|
26
|
+
run: pytest -v
|
braven-0.1.0/.gitignore
ADDED
braven-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Braven
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
braven-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: braven
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the Braven experiment tracker
|
|
5
|
+
Project-URL: Homepage, https://github.com/bravenlab/braven-python
|
|
6
|
+
Project-URL: Issues, https://github.com/bravenlab/braven-python/issues
|
|
7
|
+
Project-URL: Documentation, https://docs.bravenlab.com
|
|
8
|
+
Author: Braven
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: requests>=2.28
|
|
13
|
+
Provides-Extra: dataframe
|
|
14
|
+
Requires-Dist: pandas>=1.5; extra == 'dataframe'
|
|
15
|
+
Provides-Extra: plots
|
|
16
|
+
Requires-Dist: matplotlib>=3.5; extra == 'plots'
|
|
17
|
+
Requires-Dist: pillow>=9.0; extra == 'plots'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# braven
|
|
21
|
+
|
|
22
|
+
Python SDK for [Braven](https://bravenlab.com), the experiment tracker for
|
|
23
|
+
hardware and photonics R&D teams.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install braven
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Install and login
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install braven
|
|
33
|
+
python -m braven login
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`login` asks for your backend URL and an SDK API key (`braven_...`, from
|
|
37
|
+
your Braven account's Settings → Watcher Keys) and saves them to
|
|
38
|
+
`~/.braven/config.json`. Every script on the machine picks the credentials
|
|
39
|
+
up automatically — no need to pass them around.
|
|
40
|
+
|
|
41
|
+
## Direct logging (wandb-style)
|
|
42
|
+
|
|
43
|
+
The common case: a script you run yourself, logging config, metrics, and
|
|
44
|
+
plots straight to Braven as it runs.
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import braven
|
|
48
|
+
|
|
49
|
+
run = braven.init(name="My Experiment", company="My Company", project="My Project")
|
|
50
|
+
|
|
51
|
+
braven.config("radius_um", 55.0)
|
|
52
|
+
braven.config("gap_nm", 200.0)
|
|
53
|
+
|
|
54
|
+
braven.summary("q_factor", 18_400)
|
|
55
|
+
braven.summary("extinction_ratio_dB", 22.1)
|
|
56
|
+
|
|
57
|
+
braven.upload("spectrum.png")
|
|
58
|
+
braven.finish()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`company`/`project` are only required if your API key can see more than one
|
|
62
|
+
project — pass them to disambiguate.
|
|
63
|
+
|
|
64
|
+
## Matplotlib figures
|
|
65
|
+
|
|
66
|
+
Pass a live `matplotlib.figure.Figure` to `upload()` instead of a file path
|
|
67
|
+
and the SDK saves the PNG for you (same as `fig.savefig()` would) *and*
|
|
68
|
+
extracts an interactive companion plot from the figure's line/scatter data,
|
|
69
|
+
so the experiment page shows a zoomable, hoverable chart alongside the
|
|
70
|
+
static image — no extra API to learn:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import matplotlib.pyplot as plt
|
|
74
|
+
|
|
75
|
+
fig, ax = plt.subplots()
|
|
76
|
+
ax.plot(wavelengths_nm, through_db, label="Through port")
|
|
77
|
+
ax.set_xlabel("Wavelength (nm)")
|
|
78
|
+
ax.set_ylabel("Transmission (dB)")
|
|
79
|
+
|
|
80
|
+
braven.upload(fig, name="spectrum.png")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This works the same way whether the figure came from a script you run
|
|
84
|
+
yourself or a script run through Braven's Pipelines tab — one code path, one
|
|
85
|
+
behavior, no separate API for "give me a nice list thumbnail."
|
|
86
|
+
|
|
87
|
+
Prefer to log a plain array without a matplotlib figure at all?
|
|
88
|
+
`plot_series()` does that directly:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
braven.plot_series("snr_vs_temp", y=snr_values, x=temperatures, x_label="Temp (C)", y_label="SNR (dB)")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Devices — multiple sensors/units in one experiment
|
|
95
|
+
|
|
96
|
+
Tag a value with a stable per-device key and the KPI name stays the same
|
|
97
|
+
across devices (no `SNR_dev1`, `SNR_dev2`) — the device becomes a separate
|
|
98
|
+
coordinate instead of a suffix:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
for sensor_id, snr in results.items():
|
|
102
|
+
braven.device(sensor_id).log_summary("SNR", snr)
|
|
103
|
+
|
|
104
|
+
braven.log_summary("max_device_mismatch", spread) # experiment-level, all devices
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
A device is auto-created on first sight and its history accumulates across
|
|
108
|
+
experiments — pass an optional type on first use
|
|
109
|
+
(`braven.device("SENSOR-4471", "Photodiode")`) to name what kind of device
|
|
110
|
+
it is; it's ignored once the device already exists.
|
|
111
|
+
|
|
112
|
+
## Pipeline scripts (run by the Braven worker)
|
|
113
|
+
|
|
114
|
+
If your script runs through Braven's Pipelines tab (server-side, executed by
|
|
115
|
+
the Braven worker against uploaded files) rather than on your own machine,
|
|
116
|
+
the SDK dispatches to the same functions automatically — no `braven.init()`
|
|
117
|
+
call needed, and no credentials to manage (the worker supplies the
|
|
118
|
+
experiment context):
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import braven
|
|
122
|
+
|
|
123
|
+
def process(braven=None):
|
|
124
|
+
braven.log_config("lr", "0.001")
|
|
125
|
+
braven.log_summary("acc", "0.94")
|
|
126
|
+
braven.log_artifact("plot.png")
|
|
127
|
+
|
|
128
|
+
# Devices and matplotlib figures work exactly as in direct logging:
|
|
129
|
+
braven.device("SENSOR-1").log_summary("SNR", 14.2)
|
|
130
|
+
braven.upload(fig, name="spectrum.png")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`braven.files` (uploaded file → local temp path) and `braven.params`
|
|
134
|
+
(extracted parameters) are populated by the worker before `process()` runs.
|
|
135
|
+
|
|
136
|
+
## Querying experiments
|
|
137
|
+
|
|
138
|
+
Read-only access to experiments already logged in Braven — no API key
|
|
139
|
+
required beyond what you already set up with `python -m braven login`, or
|
|
140
|
+
construct a client directly:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from braven import Braven
|
|
144
|
+
|
|
145
|
+
b = Braven("https://your-backend.example.com", api_key="braven_...")
|
|
146
|
+
exp = b.get("high temp run") # partial, case-insensitive name match
|
|
147
|
+
df = exp.file("data.csv").as_dataframe() # requires: pip install "braven[dataframe]"
|
|
148
|
+
|
|
149
|
+
print(exp.metadata) # {key: value} config/summary metadata
|
|
150
|
+
for f in exp.files:
|
|
151
|
+
print(f.filename)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`b.get()` also accepts a list of names and returns a list of `Experiment`
|
|
155
|
+
objects. `b.experiments()` returns lightweight summaries of everything
|
|
156
|
+
visible to the API key.
|
|
157
|
+
|
|
158
|
+
## Cross-experiment analysis
|
|
159
|
+
|
|
160
|
+
Pull an explicit, frozen set of experiments out of Braven for local work
|
|
161
|
+
(training a model, building a comparison plot — anything outside Braven),
|
|
162
|
+
then log results back onto the same object so the record of what was
|
|
163
|
+
analyzed can never drift from what was actually read:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
analysis = braven.collect(
|
|
167
|
+
experiment_ids=["exp_1", "exp_2", "exp_3"],
|
|
168
|
+
name="Cross-lot yield comparison",
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
for exp in analysis.experiments():
|
|
172
|
+
df = exp.file("data.csv").as_dataframe()
|
|
173
|
+
# ... do local analysis ...
|
|
174
|
+
|
|
175
|
+
analysis.log_summary("mean_yield", 0.94)
|
|
176
|
+
analysis.upload(fig, name="comparison.png")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`filter_token` (copied from Braven's webapp "Copy as code" action) works as
|
|
180
|
+
an alternative to an explicit `experiment_ids` list — it's re-resolved to
|
|
181
|
+
concrete experiment IDs at call time, never stored as a live query.
|
|
182
|
+
|
|
183
|
+
## Optional dependencies
|
|
184
|
+
|
|
185
|
+
`requests` is the only hard dependency. Everything else is optional and
|
|
186
|
+
imported lazily:
|
|
187
|
+
|
|
188
|
+
| Feature | Install |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `.as_dataframe()` on a downloaded file | `pip install "braven[dataframe]"` |
|
|
191
|
+
| Uploading a live matplotlib `Figure` (and its list thumbnail) | `pip install "braven[plots]"` |
|
|
192
|
+
|
|
193
|
+
## Contributing / issues
|
|
194
|
+
|
|
195
|
+
Source: [github.com/bravenlab/braven-python](https://github.com/bravenlab/braven-python).
|
|
196
|
+
Found a bug or have a feature request? File it on
|
|
197
|
+
[GitHub Issues](https://github.com/bravenlab/braven-python/issues) — that's
|
|
198
|
+
the right place for anything specific to the SDK itself.
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT — see [LICENSE](LICENSE).
|
braven-0.1.0/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# braven
|
|
2
|
+
|
|
3
|
+
Python SDK for [Braven](https://bravenlab.com), the experiment tracker for
|
|
4
|
+
hardware and photonics R&D teams.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pip install braven
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Install and login
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install braven
|
|
14
|
+
python -m braven login
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`login` asks for your backend URL and an SDK API key (`braven_...`, from
|
|
18
|
+
your Braven account's Settings → Watcher Keys) and saves them to
|
|
19
|
+
`~/.braven/config.json`. Every script on the machine picks the credentials
|
|
20
|
+
up automatically — no need to pass them around.
|
|
21
|
+
|
|
22
|
+
## Direct logging (wandb-style)
|
|
23
|
+
|
|
24
|
+
The common case: a script you run yourself, logging config, metrics, and
|
|
25
|
+
plots straight to Braven as it runs.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import braven
|
|
29
|
+
|
|
30
|
+
run = braven.init(name="My Experiment", company="My Company", project="My Project")
|
|
31
|
+
|
|
32
|
+
braven.config("radius_um", 55.0)
|
|
33
|
+
braven.config("gap_nm", 200.0)
|
|
34
|
+
|
|
35
|
+
braven.summary("q_factor", 18_400)
|
|
36
|
+
braven.summary("extinction_ratio_dB", 22.1)
|
|
37
|
+
|
|
38
|
+
braven.upload("spectrum.png")
|
|
39
|
+
braven.finish()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`company`/`project` are only required if your API key can see more than one
|
|
43
|
+
project — pass them to disambiguate.
|
|
44
|
+
|
|
45
|
+
## Matplotlib figures
|
|
46
|
+
|
|
47
|
+
Pass a live `matplotlib.figure.Figure` to `upload()` instead of a file path
|
|
48
|
+
and the SDK saves the PNG for you (same as `fig.savefig()` would) *and*
|
|
49
|
+
extracts an interactive companion plot from the figure's line/scatter data,
|
|
50
|
+
so the experiment page shows a zoomable, hoverable chart alongside the
|
|
51
|
+
static image — no extra API to learn:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import matplotlib.pyplot as plt
|
|
55
|
+
|
|
56
|
+
fig, ax = plt.subplots()
|
|
57
|
+
ax.plot(wavelengths_nm, through_db, label="Through port")
|
|
58
|
+
ax.set_xlabel("Wavelength (nm)")
|
|
59
|
+
ax.set_ylabel("Transmission (dB)")
|
|
60
|
+
|
|
61
|
+
braven.upload(fig, name="spectrum.png")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This works the same way whether the figure came from a script you run
|
|
65
|
+
yourself or a script run through Braven's Pipelines tab — one code path, one
|
|
66
|
+
behavior, no separate API for "give me a nice list thumbnail."
|
|
67
|
+
|
|
68
|
+
Prefer to log a plain array without a matplotlib figure at all?
|
|
69
|
+
`plot_series()` does that directly:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
braven.plot_series("snr_vs_temp", y=snr_values, x=temperatures, x_label="Temp (C)", y_label="SNR (dB)")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Devices — multiple sensors/units in one experiment
|
|
76
|
+
|
|
77
|
+
Tag a value with a stable per-device key and the KPI name stays the same
|
|
78
|
+
across devices (no `SNR_dev1`, `SNR_dev2`) — the device becomes a separate
|
|
79
|
+
coordinate instead of a suffix:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
for sensor_id, snr in results.items():
|
|
83
|
+
braven.device(sensor_id).log_summary("SNR", snr)
|
|
84
|
+
|
|
85
|
+
braven.log_summary("max_device_mismatch", spread) # experiment-level, all devices
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
A device is auto-created on first sight and its history accumulates across
|
|
89
|
+
experiments — pass an optional type on first use
|
|
90
|
+
(`braven.device("SENSOR-4471", "Photodiode")`) to name what kind of device
|
|
91
|
+
it is; it's ignored once the device already exists.
|
|
92
|
+
|
|
93
|
+
## Pipeline scripts (run by the Braven worker)
|
|
94
|
+
|
|
95
|
+
If your script runs through Braven's Pipelines tab (server-side, executed by
|
|
96
|
+
the Braven worker against uploaded files) rather than on your own machine,
|
|
97
|
+
the SDK dispatches to the same functions automatically — no `braven.init()`
|
|
98
|
+
call needed, and no credentials to manage (the worker supplies the
|
|
99
|
+
experiment context):
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import braven
|
|
103
|
+
|
|
104
|
+
def process(braven=None):
|
|
105
|
+
braven.log_config("lr", "0.001")
|
|
106
|
+
braven.log_summary("acc", "0.94")
|
|
107
|
+
braven.log_artifact("plot.png")
|
|
108
|
+
|
|
109
|
+
# Devices and matplotlib figures work exactly as in direct logging:
|
|
110
|
+
braven.device("SENSOR-1").log_summary("SNR", 14.2)
|
|
111
|
+
braven.upload(fig, name="spectrum.png")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`braven.files` (uploaded file → local temp path) and `braven.params`
|
|
115
|
+
(extracted parameters) are populated by the worker before `process()` runs.
|
|
116
|
+
|
|
117
|
+
## Querying experiments
|
|
118
|
+
|
|
119
|
+
Read-only access to experiments already logged in Braven — no API key
|
|
120
|
+
required beyond what you already set up with `python -m braven login`, or
|
|
121
|
+
construct a client directly:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from braven import Braven
|
|
125
|
+
|
|
126
|
+
b = Braven("https://your-backend.example.com", api_key="braven_...")
|
|
127
|
+
exp = b.get("high temp run") # partial, case-insensitive name match
|
|
128
|
+
df = exp.file("data.csv").as_dataframe() # requires: pip install "braven[dataframe]"
|
|
129
|
+
|
|
130
|
+
print(exp.metadata) # {key: value} config/summary metadata
|
|
131
|
+
for f in exp.files:
|
|
132
|
+
print(f.filename)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`b.get()` also accepts a list of names and returns a list of `Experiment`
|
|
136
|
+
objects. `b.experiments()` returns lightweight summaries of everything
|
|
137
|
+
visible to the API key.
|
|
138
|
+
|
|
139
|
+
## Cross-experiment analysis
|
|
140
|
+
|
|
141
|
+
Pull an explicit, frozen set of experiments out of Braven for local work
|
|
142
|
+
(training a model, building a comparison plot — anything outside Braven),
|
|
143
|
+
then log results back onto the same object so the record of what was
|
|
144
|
+
analyzed can never drift from what was actually read:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
analysis = braven.collect(
|
|
148
|
+
experiment_ids=["exp_1", "exp_2", "exp_3"],
|
|
149
|
+
name="Cross-lot yield comparison",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
for exp in analysis.experiments():
|
|
153
|
+
df = exp.file("data.csv").as_dataframe()
|
|
154
|
+
# ... do local analysis ...
|
|
155
|
+
|
|
156
|
+
analysis.log_summary("mean_yield", 0.94)
|
|
157
|
+
analysis.upload(fig, name="comparison.png")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`filter_token` (copied from Braven's webapp "Copy as code" action) works as
|
|
161
|
+
an alternative to an explicit `experiment_ids` list — it's re-resolved to
|
|
162
|
+
concrete experiment IDs at call time, never stored as a live query.
|
|
163
|
+
|
|
164
|
+
## Optional dependencies
|
|
165
|
+
|
|
166
|
+
`requests` is the only hard dependency. Everything else is optional and
|
|
167
|
+
imported lazily:
|
|
168
|
+
|
|
169
|
+
| Feature | Install |
|
|
170
|
+
|---|---|
|
|
171
|
+
| `.as_dataframe()` on a downloaded file | `pip install "braven[dataframe]"` |
|
|
172
|
+
| Uploading a live matplotlib `Figure` (and its list thumbnail) | `pip install "braven[plots]"` |
|
|
173
|
+
|
|
174
|
+
## Contributing / issues
|
|
175
|
+
|
|
176
|
+
Source: [github.com/bravenlab/braven-python](https://github.com/bravenlab/braven-python).
|
|
177
|
+
Found a bug or have a feature request? File it on
|
|
178
|
+
[GitHub Issues](https://github.com/bravenlab/braven-python/issues) — that's
|
|
179
|
+
the right place for anything specific to the SDK itself.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT — see [LICENSE](LICENSE).
|