This release is a pre-release and may not be stable for production use.
Marple SDK
An SDK to interact with Marple DB & Insight
Installation and importing
Install the Marple SDK using your package manager:
poetry add marpledatauv add marpledatapip install marpledata
The SDK currently exposes:
from marple import DB # Marple DB
from marple import Insight # Marple Insight
For release notes, see CHANGELOG.md.
Marple DB
To get started:
- Create a stream in the Marple DB UI
- Create an API token (in user settings)
If you are using a VPC or self-hosted version, pass a custom api_url to DB(...) (it should end in /api/v1).
Examples
Import a file and wait for it to import
This is the typical flow for importing a new file into Marple DB:
from marple import DB
# Create a stream + API token in the Marple DB web application
STREAM = "Car data"
API_TOKEN = "<your api token>"
API_URL = "https://db.marpledata.com/api/v1" # optional if using the default SaaS
db = DB(API_TOKEN, API_URL)
db.check_connection()
stream = db.get_stream(STREAM)
dataset = stream.push_file("examples_race.csv", metadata={"driver": "Mbaerto"})
# Wait at most 10s for the dataset to completely import and get the new state of the dataset
dataset = dataset.wait_for_import(timeout=10)
Add signals to an imported dataset
Upload additional signals (for example derived channels) on an existing dataset.
Each signal is a DataFrame, Arrow table, or on-disk parquet matching LAKE_ARROW_SCHEMA:
columns time (int64 nanoseconds) plus value and/or value_text.
Times must overlap the dataset time range. Use overwrite=True to replace an existing signal name;
a conflict without overwrite raises SignalsAlreadyExistError.
import pandas as pd
from marple.db import LAKE_ARROW_SCHEMA # time + value and/or value_text
speed = dataset.get_signal("car.speed").get_data()
derived = pd.DataFrame({
"time": speed.index.asi8,
"value": speed["value"] * 3.6,
})
# Single signal: wait until available before reading
signal = dataset.add_signal(
"car.speed_kmh",
derived,
metadata={"unit": "km/h"},
).wait_until_available()
# Batch: returns IDs as soon as upload completes (no wait)
ids = dataset.add_signals([
{"name": "car.speed_kmh", "data": derived, "metadata": {"unit": "km/h"}},
], overwrite=True, concurrency=4)
signals = dataset.get_signals(signal_ids=ids)
Upload large files
stream.push_file(...) starts an ingestion and lets the Marple DB API choose the best upload mode. Depending on the deployment and file size, the SDK can upload through the API server, upload directly to Azure Blob Storage, use a single presigned URL, or split the file into multipart uploads.
The default upload_mode="auto" is recommended for most users. Increase concurrency when uploading large files over a fast connection:
dataset = stream.push_file(
"large_export.csv",
metadata={"source": "testbench"},
concurrency=8,
).wait_for_import(timeout=180)
If your network, proxy, or firewall blocks direct storage URLs, force the SDK to upload through the Marple DB API server:
dataset = stream.push_file(
"large_export.csv",
upload_mode="server",
).wait_for_import(timeout=180)
Filter datasets and get resampled data
# See previous example for setup
import re
from marple.db import Dataset
datasets = stream.get_datasets() # Get all datasets in a specific Data Stream
# OR
# datasets = db.get_datasets() # Get all datasets in the datapool
datasets = (
datasets
.where_metadata({"car_id": [1, 2], "track": "track_1"})
.wait_for_import()
.where_imported()
.where_signal("car.speed", "max", greater_than=75)
.where_signal("car.engine.temp", "mean", greater_than=30)
.where_dataset("n_datapoints", greater_than=100000)
)
def custom_filter_function(dataset: Dataset) -> bool:
return (
dataset.metadata.get("weather") == "sunny"
or dataset.get_signal("car.engine.NGear").stats.get("avg", 0) ** 2 > 16
)
# Pass any function to filter the datasets on more complex conditions
datasets = datasets.where(custom_filter_function)
# Create an overview of the datasets as a pandas.DataFrame to save it to a CSV.
datasets.to_pandas().to_csv("all_datasets.csv")
# Get a dataframe per dataset of the matching signals which is resampled at a period of 0.17s.
# The regex patterns will match with car.wheel.rear.left.speed, car.wheel.rear.front.speed, ...
for dataset, data in datasets.get_data(
signals=[
"car.speed",
"car.engine.temp",
re.compile("car.wheel.*.speed"),
re.compile("car.wheel.*.trq"),
],
resample_rule="0.17s",
):
machine_learning_model.train(data)
Delete a dataset that failed to import
datasets = stream.get_datasets()
datasets = datasets.where_dataset("import_status", equals="FAILED")
# datasets is of type DatasetList which is a subclass of list so you can do all normal list operations on it.
if len(datasets) > 0:
datasets[0].delete()
Common operations
- List streams:
db.get_streams() - List datasets in a stream:
stream.get_datasets() - Upload a file to a file-stream:
stream.push_file(file_path, metadata={...}, concurrency=4) - Add signals to a dataset:
dataset.add_signal(name, data, ...)/dataset.add_signals([...])— data matchesLAKE_ARROW_SCHEMA(time+valueand/orvalue_text) - Wait until a signal is available:
signal.wait_until_available(timeout=60) - Fetch signals by ID:
dataset.get_signals(signal_ids=[...], refresh=False) - Wait for a dataset to import:
dataset.wait_for_import(timeout=60) - Download original uploaded file:
dataset.download(destination_folder=".") - Download parquet for a signal:
dataset.get_signal(signal_name).download(destination_folder=".") - Get a resampled df of multiple signals:
dataset.get_data(signals=[...], resample_rule="1s") - Delete a stream:
stream.delete()ordb.delete_stream(stream_key) - Delete a dataset:
dataset.delete()ordb.delete_dataset(dataset_id, dataset_path)
For live/realtime streams (creating and appending data):
- Create an empty dataset:
stream.add_dataset(dataset_name, metadata=None) - Upsert signal definitions:
dataset.upsert_signals(signals=[...]) - Append timeseries data:
dataset.append(data=df, shape="long"|"wide"|None) - Cool a realtime dataset:
dataset.cool()thendataset.wait_for_import()to wait untilFINISHED
Calling endpoints directly
For advanced use cases, you can call API endpoints directly:
db.get("/health")
Notes on DB API changes
- Methods like
DB.push_file,DB.download_signal, andDB.update_metadataare deprecated compatibility paths. - Prefer stream/dataset methods instead:
stream.push_file,dataset.get_signal(...).download(), anddataset.update_metadata(...). - Use
DataStream.push_filefor new upload code because it exposes the current upload controls, includingconcurrencyandupload_mode.
Marple Insight
Common operations
- List datasets in the workspace:
insight.get_datasets() - Get a Marple DB dataset (by dataset id):
insight.get_dataset_mdb(dataset_id) - List signals in a dataset:
insight.get_signals(dataset_filter)/insight.get_signals_mdb(dataset_id)
Example: export a dataset (H5/MAT)
from marple import DB, Insight
INSIGHT_TOKEN = "<your api token>"
INSIGHT_URL = "https://insight.marpledata.com/api/v1" # optional if using the default SaaS
DB_TOKEN = "<your api token>"
DB_URL = "https://db.marpledata.com/api/v1" # optional if using the default SaaS
STREAM = "Car data"
insight = Insight(INSIGHT_TOKEN, INSIGHT_URL)
db = DB(DB_TOKEN, DB_URL)
dataset_id = db.get_datasets(STREAM)[0].id
insight_dataset = insight.get_dataset_mdb(dataset_id)
file_path = insight.export_data_mdb(
dataset_id,
format="h5",
signals=["car.speed"],
destination=".",
)
print("Wrote", file_path)
Calling endpoints directly
For advanced use cases, you can call API endpoints directly:
insight.get("/user/info")
insight.post("sources/search")
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 marpledata-3.4.0.dev1.tar.gz.
File metadata
- Download URL: marpledata-3.4.0.dev1.tar.gz
- Upload date:
- Size: 727.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f7340f495c7c058ddbdedc702393744dfe8bc8db22bb586dd884d58b84f7e8d
|
|
| MD5 |
debd350a2db35f7b902665137034f37e
|
|
| BLAKE2b-256 |
13839c37d6f5fc5255f81eb2dbe0df4f3d76dbc382f9b59591753a31050b0353
|
File details
Details for the file marpledata-3.4.0.dev1-py3-none-any.whl.
File metadata
- Download URL: marpledata-3.4.0.dev1-py3-none-any.whl
- Upload date:
- Size: 33.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5bd7e876c2a605de02587b6bf191826d188120c49e48a256d5d69cd50f7afa24
|
|
| MD5 |
5d0f54f296b3d0e5bf940fb460815c73
|
|
| BLAKE2b-256 |
d147fc63f624c6d68ce61a3a44d62a548e70470e0264bfa5fcfa1d1f49617629
|