Lightweight Python client for Anthive REST API - query single-cell expression databases
Project description
Anthive Client
Lightweight Python client for the Anthive REST API - query single-cell expression databases with ease.
Features
- Lightweight: Only requires
requestslibrary - Optional pandas support: Install pandas for DataFrame output
- Pyodide-compatible: Runs in JupyterLite / browser environments
- Type hints: Full type annotations for IDE support
- Auto-detection: Works in standard Python, Pyodide, and Streamlit
- Comprehensive: Complete API coverage including gene statistics
Installation
From PyPI
# Basic installation
pip install antclient
# With pandas support for DataFrames
pip install antclient[pandas]
From Source
# Clone repository
git clone https://github.com/anthive/anthive4.git
cd anthive4
# Install
pip install -e .
# Or just copy the single file
cp antclient.py /path/to/your/project/
Quick Start
from antclient import AnthiveClient
from anthelper import find_database, find_metadata
# Connect to API (auto-detects URL in Pyodide/browser)
client = AnthiveClient()
# Browse available datasets
find_database(client, "brain") # search by keyword
find_metadata(client, "LC5/SPM") # list obs columns
# Get database info and detect best layer
info = client.get_database_info("LC5/SPM")
layer = 'data' if 'data' in info['layers'] else info['layers'][0]
# Search genes
genes = client.search_genes("LC5/SPM", q="Apoe", limit=10)
# Get per-gene statistics (fast — no full cell download)
stats = client.get_gene_stats("LC5/SPM", ["Apoe", "Actb"], format='dataframe')
print(stats[["gene", "pct_nonzero", "mean", "median_nonzero"]])
# Get cell data as DataFrame
df = client.get_cells(
"LC5/SPM",
genes=["Apoe", "Trem2"],
metadata=["genotype", "cell_type"],
layer=layer,
format='dataframe'
)
print(df.head())
Usage Examples
Database Discovery
# List all databases
databases = client.get_databases()
# Get as DataFrame
df = client.get_databases(format='dataframe')
# Force refresh from disk
databases = client.get_databases(refresh=True)
# Get specific database info
info = client.get_database_info("Voet2025/slide_st.counts")
print(f"Title: {info['title']}")
print(f"Layers: {info['layers']}")
print(f"Embeddings: {info['embeddings']}")
Gene Operations
# Search genes
genes = client.search_genes("mydb", q="CD", limit=20)
# Case-sensitive search
genes = client.search_genes("mydb", q="Cd4", case_sensitive=True)
# Get gene info
info = client.get_gene_info("mydb", "CD4")
# Get all genes (careful - may be large!)
all_genes = client.get_all_genes("mydb")
Gene Statistics (lightweight — no full cell download)
# Single gene
stats = client.get_gene_stats("mydb", "APOE")
# Returns list of dicts: gene, layer, n_cells, n_nonzero, pct_nonzero,
# mean, std (all cells), mean_nonzero, std_nonzero, median_nonzero,
# q10_nonzero, q90_nonzero, max
# Multiple genes as DataFrame
df = client.get_gene_stats("mydb", ["APOE", "CLU", "ACTB"],
layer="data", format='dataframe')
print(df[["gene", "pct_nonzero", "mean", "median_nonzero"]])
Cell Data Retrieval
# Get expression data for specific genes
result = client.get_cells(
"mydb",
genes=["CD4", "CD8"],
limit=100
)
# Get with metadata
result = client.get_cells(
"mydb",
genes=["CD4"],
metadata=["cell_type", "tissue"]
)
# Get all metadata
result = client.get_cells(
"mydb",
genes=["CD4"],
metadata="*" # or metadata=["*"]
)
# With filters
result = client.get_cells(
"mydb",
genes=["CD4"],
metadata=["cell_type", "n_counts"],
filters=[
"cell_type:T-cell",
"n_counts:1000,5000" # range filter
]
)
# Get as DataFrame
df = client.get_cells(
"mydb",
genes=["CD4", "CD8"],
metadata=["cell_type"],
format='dataframe'
)
# Export to CSV
csv_data = client.get_cells(
"mydb",
genes=["CD4"],
format='csv'
)
# Export to Parquet
parquet_bytes = client.get_cells(
"mydb",
genes=["CD4"],
format='parquet'
)
Embeddings
# List available embeddings
embeddings = client.get_embeddings("mydb")
# Get UMAP coordinates
umap = client.get_embedding_data("mydb", "Umap", n_dims=2, limit=1000)
# Get as DataFrame
df = client.get_embedding_data("mydb", "Umap", format='dataframe')
# Get all dimensions
pca = client.get_embedding_data("mydb", "Pca", n_dims=0) # 0 = all
Metadata Operations
# List metadata fields
fields = client.get_metadata_fields("mydb")
print(f"Numerical fields: {fields['numerical']}")
print(f"Categorical fields: {fields['categorical']}")
# List layers
layers = client.get_layers("mydb")
SQL Queries
# Execute raw SQL
result = client.execute_sql(
"mydb",
"SELECT cell_name, celltype FROM obscat LIMIT 10"
)
# Get as DataFrame
df = client.execute_sql(
"mydb",
"SELECT * FROM obsnum WHERE n_counts > 5000",
format='dataframe'
)
# With limit
result = client.execute_sql(
"mydb",
"SELECT * FROM cells",
limit=100
)
Server Monitoring (Phase 2)
# Check server health
health = client.get_health()
print(f"Status: {health['status']}")
# Get performance metrics
metrics = client.get_metrics()
print(f"Cache hit rate: {metrics['connection_pool']['hit_rate']:.2%}")
print(f"Uptime: {metrics['uptime_seconds']} seconds")
Admin Operations
# Rescan databases
result = client.rescan_databases()
print(f"Databases: {result['previous_count']} -> {result['current_count']}")
print(f"Added: {result['added']}")
print(f"Removed: {result['removed']}")
Advanced Usage
Environment Variables
# Set default API URL
export ANTHIVE_API_URL="http://myserver:8080"
# Client will auto-detect from environment
client = AnthiveClient() # Uses ANTHIVE_API_URL
Pyodide/Browser Integration
// In browser JavaScript, set global variable
window.ANTHIVE_API_URL = "https://api.example.com";
# In Pyodide Python
from antclient import AnthiveClient
# Auto-detects from window.location or ANTHIVE_API_URL global
client = AnthiveClient()
Streamlit Integration
The client automatically uses Streamlit's caching when available:
import streamlit as st
from antclient import AnthiveClient
# Cached automatically in Streamlit
client = AnthiveClient("http://localhost:8080")
databases = client.get_databases() # Cached for 60s
st.dataframe(databases)
Custom Timeout
# Set custom timeout
client = AnthiveClient("http://localhost:8080", timeout=60)
API Reference
AnthiveClient
Constructor:
AnthiveClient(base_url=None, timeout=30)
Info Methods:
get_root()- API root informationget_health()- Server health statusget_metrics()- Performance metrics (Phase 2)
Database Methods:
get_databases(refresh=False, format='list')- List databasesget_database_info(db_id)- Database detailslist_database_ids()- Get database IDs only
Gene Methods:
search_genes(db_id, q='', limit=100, case_sensitive=False)- Search genesget_gene_info(db_id, gene_id)- Gene detailsget_all_genes(db_id)- All genes (may be large!)get_gene_stats(db_id, genes, layer='X', format='json')- Per-gene statistics
Metadata Methods:
get_layers(db_id)- List layersget_metadata_fields(db_id)- List metadata fieldsget_embeddings(db_id)- List embeddings
Data Methods:
get_cells(db_id, genes=None, metadata=None, layer='X', filters=None, limit=None, format='json')- Get cell dataget_embedding_data(db_id, embedding_id, n_dims=2, limit=None, format='json')- Get embeddings
Query Methods:
execute_sql(db_id, query, limit=None, format='json')- Execute SQL
Admin Methods:
rescan_databases()- Force database rescan
Error Handling
import requests
try:
result = client.get_database_info("nonexistent")
except requests.HTTPError as e:
if e.response.status_code == 404:
print("Database not found")
elif e.response.status_code == 503:
print("Server unavailable")
else:
print(f"Error: {e}")
Development
Testing
# Install dev dependencies
pip install -e .[dev]
# Run tests (when test suite is created)
pytest tests/
# Check code style
black antclient.py
flake8 antclient.py
Building for PyPI
cd antclient
./build_pypi.sh # copies README, builds, checks
# Upload (requires PyPI credentials)
uvx twine upload --repository testpypi dist/* # test first
uvx twine upload dist/* # production
anthelper — Jupyter Notebook Helpers
The companion anthelper module ships with antclient and provides pretty-printing helpers for interactive use:
from anthelper import find_database, find_metadata
# Browse available datasets (sorted by year, up to 20)
find_database(client)
find_database(client, "alzheimer") # filter by keyword
# List obs columns for a dataset
find_metadata(client, "LC5/SPM")
find_metadata(client, "LC5/SPM", "cell") # filter column names
anthelper is designed for Jupyter / JupyterLite but works in any Python environment.
Requirements
Required:
- Python >= 3.9
- requests >= 2.25.0
Optional:
- pandas >= 1.3.0 (for
format='dataframe'support)
Compatibility
- Python: 3.9, 3.10, 3.11, 3.12
- Environments: Standard Python, Pyodide, Streamlit
- API: Anthive REST API v2.0 (Phase 2)
License
MIT License - see LICENSE file for details
Contributing
Contributions welcome! Please open an issue or pull request on GitHub.
Support
- Issues: https://github.com/anthive/anthive4/issues
- Documentation: https://github.com/anthive/anthive4
- API Documentation: http://your-server:8080/docs
Changelog
1.0.0 (2026-02-24)
- Initial release for Anthive REST API v2.0 (Phase 2)
- Single-file lightweight client
- Full API coverage
- Optional pandas support
- Pyodide compatible
- Streamlit caching support
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 antclient-1.1.3.tar.gz.
File metadata
- Download URL: antclient-1.1.3.tar.gz
- Upload date:
- Size: 18.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26c6733acf2143eb7d9102f514e4423895f445737882ddc853c7f90aeeac6355
|
|
| MD5 |
aed6baa8d6da9dfd6fcf404e4a0333fc
|
|
| BLAKE2b-256 |
8fe26736feaa2f3f4f4d9499f37d31734b8b82c7e144f7524ecc61af255f07a7
|
File details
Details for the file antclient-1.1.3-py3-none-any.whl.
File metadata
- Download URL: antclient-1.1.3-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4772cf4bffc99e766400b2627d2d4dd32dc72d221f3088048f01d56f7ba33647
|
|
| MD5 |
c493be891631ea90afc785e59c9042c6
|
|
| BLAKE2b-256 |
11eb688a24ed1e139afae1535046efbc0865baf8bbc63f11a8e98dfbef792edd
|