Python WebSocket client for the Loom Genome Browser
Project description
loom-client
Python WebSocket client for the Loom Genome Browser. Provides a fully async, typed interface for programmatically controlling a running Loom instance -- navigating loci, managing tracks and regions of interest, exporting views, and subscribing to browser events.
Installation
pip install loom-client
Or install from source:
git clone https://github.com/riyavsinha/loom-client.git
cd loom-client
pip install -e .
Requires Python >= 3.11.
Quick start
import asyncio
from loom_client import LoomClient
async def main():
client = LoomClient("ws://localhost:8080")
await client.connect()
# Get current browser state
state = await client.get_browser_state()
print(state.locus_string) # e.g. "chr1:1,000-2,000"
print(state.zoom_level) # e.g. ZoomLevel.GENE
# Navigate to a locus
await client.navigate(locus="chr17:7565097-7590856") # TP53
# Zoom out 2x
await client.navigate(zoom="out", factor=2.0)
await client.close()
asyncio.run(main())
API reference
Connection
client = LoomClient(url) # Create client
await client.connect() # Open WebSocket + start listener
await client.close() # Tear down
Commands
All command methods are async and return typed Pydantic models.
get_browser_state(record=None) -> ProjectedState
Returns the current viewport state including locus, zoom level, loaded tracks, and ROIs.
state = await client.get_browser_state()
for track in state.tracks:
print(f"{track.name} ({track.type})")
navigate(locus=None, zoom=None, factor=None) -> bool
Move the viewport to a genomic locus or zoom in/out.
await client.navigate(locus="chr1:1000-2000")
await client.navigate(zoom="in", factor=3.0)
modify_tracks(actions) -> ModifyTracksResult
Add, remove, find, or update tracks in a single batch.
from loom_client import AddTrackAction, RemoveTrackAction, TrackSessionConfig, DataSourceConfig, WireTrackSelector
# Add a BigWig track
result = await client.modify_tracks([
AddTrackAction(config=TrackSessionConfig(
type="wig",
name="H3K27ac",
data_source=DataSourceConfig(
type="bigwig",
url="https://example.com/h3k27ac.bw",
),
))
])
# Remove by name pattern
result = await client.modify_tracks([
RemoveTrackAction(selector=WireTrackSelector(name_regex="H3K.*"))
])
query_features(track_id, summarize=None) -> QueryFeaturesResult
Query features for a loaded track.
result = await client.query_features("track-id-123", summarize=True)
print(result.feature_count)
set_layout(tracks, locus=None) -> SetLayoutResult
Replace the entire track layout at once.
result = await client.set_layout(
tracks=[
TrackSessionConfig(type="ruler"),
TrackSessionConfig(type="sequence"),
TrackSessionConfig(
type="annotation",
name="GENCODE",
data_source=DataSourceConfig(type="gencode", genome="hg38"),
),
],
locus="chr1:1000-5000",
)
export_view(format, width=None) -> str | SessionConfig
Export the current view as SVG, PNG (returned as strings), or a session config object.
svg = await client.export_view("svg", width=1200)
session = await client.export_view("session") # returns SessionConfig
manage_rois(action) -> ROI result
Manage regions of interest. The action type determines the operation.
from loom_client import AddROIAction, ROI, ListROIAction, FindROIAtLocusAction
# Add a region of interest
result = await client.manage_rois(AddROIAction(
roi=ROI(id="roi-1", chr="chr17", start=7565097, end=7590856,
name="TP53", color="rgba(255,0,0,0.3)"),
set_name="Genes of interest",
))
# List all ROIs
result = await client.manage_rois(ListROIAction())
# Find ROIs overlapping a locus
result = await client.manage_rois(
FindROIAtLocusAction(chr="chr17", start=7500000, end=7600000)
)
subscribe_events(events) -> SubscribeEventsResult
Subscribe to server-pushed events. Use ["*"] for all events or [] to unsubscribe.
await client.subscribe_events(["locuschange", "trackadded", "dataloaded"])
Event handling
Register callbacks for browser events:
def on_locus_change(data):
locus = data["locus"]
print(f"Moved to {locus['chr']}:{locus['start']}-{locus['end']}")
client.on("locuschange", on_locus_change)
# Wildcard handler receives (event_name, data)
client.on("*", lambda name, data: print(f"Event: {name}"))
# Unregister
client.off("locuschange", on_locus_change)
Available events: locuschange, trackadded, trackremoved, dataloaded, dataerror, rendererror, trackclick, trackhover, trackcontextmenu, trackorderchanged, roiadded, roiremoved, roichanged, roiclick, roicontextmenu
Error handling
Server errors raise CommandException:
from loom_client import CommandException
try:
await client.navigate(locus="invalid")
except CommandException as e:
print(e.code, e.message)
Development
pip install -e ".[dev]"
pytest
License
MIT
Project details
Release history Release notifications | RSS feed
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 loom_client-0.0.1.tar.gz.
File metadata
- Download URL: loom_client-0.0.1.tar.gz
- Upload date:
- Size: 15.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27d9239c34d406feebba7d91951a25be80b5949372a1ee73e12b784421e26ef2
|
|
| MD5 |
5d7939dd3146adc8bfd558c3505d7ffb
|
|
| BLAKE2b-256 |
0018fe63d11cbb61b0438f7ad6631a6b91db60212fad9ca19cb76c00d62b2a90
|
File details
Details for the file loom_client-0.0.1-py3-none-any.whl.
File metadata
- Download URL: loom_client-0.0.1-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1f20ce62b427cf337541f5c4b6982e9d20b316a614120844adf18dd4e6a7637
|
|
| MD5 |
8a42f3db0d2ec0d500a9a6f66e5234ce
|
|
| BLAKE2b-256 |
fa96293ae1065f829fe716c024dc9eebf0ce65be288c6265af159196c455c639
|