Official Python SDK for the Waveium API
Project description
Waveium Python SDK
Official Python client library for the Waveium API. Build and run RF propagation simulations on top of a real environment model, stream progress via Server-Sent Events, and read the parquet results straight into a pandas DataFrame.
New here? Start with the step-by-step walkthrough at
docs/getting_started.md.
Features
- Full coverage of the Environment -> Scene -> Execution workflow.
- Synchronous (
waveium.Client) and asynchronous (waveium.AsyncClient) clients. - Built-in SSE progress streaming with blocking
wait()helpers and acreate_and_run()convenience for the common case. read_parquet()streams result files straight into pandas without writing to disk;structured=Truemerges xyz triplets and complex re/im pairs for immediate analysis.- Pydantic v2 models throughout for type safety.
.envauto-loaded viapython-dotenv.- Typed exception hierarchy for precise error handling.
Installation
pip install "waveium[parquet]"
The [parquet] extra pulls in pandas and pyarrow, which
client.executions.read_parquet() requires. Drop it if you only need
to drive simulations without reading results in-process.
Python 3.9 or newer. Tested up to 3.13.
Quick start
import waveium
client = waveium.init() # reads WAVEIUM_API_KEY from env / .env
# 1. Create an environment (outdoor, route-based).
env_resp = client.environments.create(
name="Stockholm Route",
environment_type="outdoor",
route={
"start": "Stockholm Central Station",
"end": "Gamla Stan",
"area": "Stockholm, Sweden",
},
stations={"BS1": [59.3293, 18.0686, 25.0]},
)
env = client.environments.wait(
env_resp.environment.environment_id, timeout=900
)
# 2. Create and generate a scene.
scene = client.scenes.create(
environment_id=env.environment_id,
name="Default Scene",
parameters={
"stations": {"BS1": [59.3293, 18.0686, 25.0]},
"station_radio_config": {
"BS1": {"tx_power_dbm": 20.0, "noise_floor_dbm": -100.0}
},
},
)
client.scenes.generate(scene.scene_id)
client.scenes.wait(scene.scene_id, timeout=3600)
# 3. Run an execution and stream progress.
execution = client.scenes.create_and_run(
scene.scene_id,
execution_name="Quick Start",
timeout=3600,
)
# 4. Read the parquet results into a DataFrame.
df = client.executions.read_parquet(
execution.execution_id, structured=True
)
print(df.columns)
client.close()
For a guided walkthrough -- including how to plot RSSI, SNR, and
channel gain -- see docs/getting_started.md.
Resource handles
Responses for the workflow chain (environments, scenes, executions) come back as bound handles: the same pydantic models as before, but carrying a reference to the client, so follow-up calls need no id threading. The quick-start workflow becomes:
env = client.environments.create(
name="Stockholm Route",
environment_type="outdoor",
route={
"start": "Stockholm Central Station",
"end": "Gamla Stan",
"area": "Stockholm, Sweden",
},
).environment
env = env.wait(timeout=900)
env.upload("map.zip")
scene = env.scenes.create(name="Default Scene", parameters={...})
scene = scene.generate().wait(timeout=3600)
execution = scene.create_and_run(
execution_name="Quick Start", timeout=3600
)
df = execution.read_parquet(structured=True)
The flat id-first API remains fully supported -- handles are plain
EnvironmentResponse / SceneResponse / ExecutionResponse
subclasses (waveium.Environment, waveium.Scene,
waveium.Execution, plus async twins), so both styles mix freely:
client.environments.upload(env.environment_id, ...) and
env.upload(...) are equivalent. Handles rebuilt via
model_validate() or unpickling are unbound; re-fetch through the
client to get a bound one. See
examples/handles_workflow.py.
Authentication
The SDK reads the API key from the WAVEIUM_API_KEY (or
WAVEIUM_SDK_TOKEN) environment variable. Create keys at
https://app.waveium.io.
Using a .env file (recommended)
WAVEIUM_API_KEY=wvx_paste_your_key_here
import waveium
client = waveium.init() # .env auto-loaded
Passing the key explicitly
client = waveium.init(api_key="wvx_...")
Firebase JWT exchange
If you already have a signed-in Firebase user, exchange the JWT for a long-lived API key in one call:
client = waveium.auth(
firebase_token="eyJ...", # or set FIREBASE_TOKEN
token_name="My Python App",
expires_days=30,
)
Under the hood this POSTs the Firebase JWT to /auth/tokens with
Authorization: Bearer <jwt> and returns a Client bound to the new
wvx_ key.
Async usage
The AsyncClient mirrors the sync client one-for-one and works as an
async context manager:
import asyncio
import waveium
async def main() -> None:
async with waveium.AsyncClient() as client:
execution = await client.scenes.create_and_run(
"scn_xxx",
execution_name="Async run",
timeout=3600,
)
df = await client.executions.read_parquet(
execution.execution_id, structured=True
)
print(df.head())
asyncio.run(main())
See examples/async_streaming_usage.py for the full set of async
streaming patterns.
Available resources
Environments, scenes, and executions return bound handles (see Resource handles); the id-first methods listed below accept explicit ids and remain fully supported.
| Resource | Purpose |
|---|---|
client.environments |
Create / list / get / wait on environments. |
client.scenes |
Scene lifecycle, generate(), wait(), create_execution(), create_and_run(), file upload. |
client.executions |
Execution lifecycle, SSE streaming, wait(), get(), progress(), read_parquet(), download_parquet(), download_archive(), post-processing. |
client.antenna_patterns |
List, upload, and manage antenna patterns. |
client.auth |
Create, list, and revoke API tokens (Firebase exchange lives here). |
client.users |
me() and admin user management. |
client.organizations |
Organization admin. |
client.teams |
Team membership management. |
client.projects |
Project scoping for shared work. |
client.roles |
RBAC role and permission queries. |
Error handling
All SDK errors inherit from waveium.WaveiumError:
from waveium import (
WaveiumError, # Base class
AuthenticationError, # 401
AuthorizationError, # 403
NotFoundError, # 404
ConflictError, # 409 (e.g. scene not completed yet)
ValidationError, # 400
RateLimitError, # 429
APIError, # 5xx
NetworkError, # connection / DNS / timeout
FileUploadError,
FileDownloadError,
ConfigurationError,
StreamError,
StreamTimeoutError,
StreamReconnectError,
ExecutionFailedError, # terminal "failed" SSE event
)
try:
client.scenes.create_and_run(scene_id, timeout=3600)
except ExecutionFailedError as e:
print(f"Execution {e.execution_id} failed: {e.error_message}")
except ConflictError:
print("Scene is not in completed state yet")
except WaveiumError as e:
print(f"SDK error: {e}")
Configuration
| Variable | Meaning | Default |
|---|---|---|
WAVEIUM_API_KEY |
API key (starts with wvx_) |
-- |
WAVEIUM_SDK_TOKEN |
Alias for WAVEIUM_API_KEY |
-- |
FIREBASE_TOKEN |
Firebase JWT for waveium.auth() |
-- |
WAVEIUM_BASE_URL |
API base URL | https://api.waveium.io |
WAVEIUM_TIMEOUT |
HTTP timeout in seconds | 60 |
WAVEIUM_MAX_RETRIES |
Retry budget for idempotent requests | 3 |
Override programmatically:
client = waveium.init(
api_key="wvx_...",
base_url="https://api.waveium.io",
timeout=120.0,
max_retries=5,
)
Examples
See the examples/ directory for runnable scripts. Each reads
WAVEIUM_API_KEY from the environment (or a .env file).
| Script | What it shows |
|---|---|
basic_usage.py |
Full Env -> Scene -> Execution pipeline, synchronous. |
streaming_usage.py |
Four tiers of SSE streaming (raw stream, blocking wait, create-and-run, environment wait). |
async_usage.py |
Async environment creation. |
async_streaming_usage.py |
Async counterparts of the streaming tiers. |
load_and_plot.py |
Minimal results-only script: point it at an execution_id to plot channel power and CIR. |
helsinki_usage.py |
Full outdoor Helsinki route: run the sim, download the parquet, and plot a 2D PDP. |
helsinki_track_usage.py |
Outdoor bbox variant: generate/upload a GPX track with timestamps as the UE trajectory, run the sim, download the parquet, and plot a 2D PDP. |
upload_download.py |
Scene file upload and execution result download. |
underground_workflow.py |
Complex underground scenario driven by JSON tunnel graph and CSV stations/UE, using polling. |
underground_workflow_sse.py |
Same scenario using SSE streaming instead of polling. |
verify_sdk.py |
Quick smoke test: init, users.me(), list environments. |
Development
cd python313
pip install -e ".[dev,parquet]"
Code quality gates (match the project's pyproject.toml and
setup.cfg):
black src/ examples/ tests/
flake8 src/ examples/ tests/
mypy --strict src/
pytest
License
MIT -- see LICENSE.
Support
- Dashboard: https://app.waveium.io
- Documentation: https://docs.waveium.io
- Issues: https://github.com/waveium/waveium-sdk/issues
- Email: support@waveium.io
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file waveium-0.6.0.tar.gz.
File metadata
- Download URL: waveium-0.6.0.tar.gz
- Upload date:
- Size: 98.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
595f38b1ee509f13a9a0c2df5b7444667934b00d8e97ae28c6397f5f63690bb6
|
|
| MD5 |
3c404134031f7dbac885859b5753c953
|
|
| BLAKE2b-256 |
6bbe01410ba59da4894df59076b2f56dab7cee35509078642246eb3b4a0f3291
|
File details
Details for the file waveium-0.6.0-py3-none-any.whl.
File metadata
- Download URL: waveium-0.6.0-py3-none-any.whl
- Upload date:
- Size: 84.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
433c8777b32fa53c4467e2b496c5c1c11e2e822b76864eda948df5beabab2e39
|
|
| MD5 |
7a35018a32a7ec1c2e12adc08efe3716
|
|
| BLAKE2b-256 |
0071ff261d872ef52df84503ede9755583325bf4a9f18338917e66d4a8231855
|