metacube (Python)
Interactive 3D cube visualization for tabular data. Provide a CSV and a config YAML — metacube transforms it and produces a self-contained HTML file or serves it locally.
Try it in the browser without installing →
Installation
pip install metacube
Quick Start
# Copy bundled example files
metacube examples --dest my_data/
# Explore interactively (no files written)
metacube dev my_data/census_tissue_general_counts.csv \
--config my_data/census_tissue_general.yaml
# Export a standalone HTML file
metacube export my_data/census_tissue_general_counts.csv \
--config my_data/census_tissue_general.yaml \
--output viz.html
CLI Reference
metacube dev — transform and serve in one step
metacube dev <CSV_FILE> --config <CONFIG_YAML> [--port 8000] [--no-browser]
Transforms the CSV in memory and serves a local visualization. Nothing is written to disk. Press Ctrl+C to stop.
metacube dev data.csv --config config.yaml
metacube dev data.csv --config config.yaml --port 9000 --no-browser
metacube export — transform and export in one step
metacube export <CSV_FILE> --config <CONFIG_YAML> [--output viz.html]
Produces a fully self-contained HTML file that works offline (no server needed). Default output name: <csv_stem>.html.
metacube export data.csv --config config.yaml
metacube export data.csv --config config.yaml --output my_viz.html
metacube transform — CSV → JSON
metacube transform <CSV_FILE> --config <CONFIG_YAML> [--output data.json]
Converts a CSV + config to an intermediate CubeData JSON. Use this when you want to cache the transformed data and serve or build from it later.
metacube transform data.csv --config config.yaml # writes data.json
metacube transform data.csv --config config.yaml -o out.json
metacube transform data.csv --config config.yaml | jq .config # pipe to jq
metacube build — JSON → HTML
metacube build <DATA_JSON> [--output cube.html]
Injects a pre-transformed CubeData JSON into the visualization template.
metacube build data.json
metacube build data.json --output my_viz.html
metacube serve — JSON → browser
metacube serve <DATA_JSON> [--port 8000] [--no-browser]
Serves a pre-transformed JSON locally.
metacube serve data.json
metacube serve data.json --port 9000
metacube examples — copy bundled example files
metacube examples [--dest ./] [--list]
Copies bundled example CSV and config YAML files to a local directory.
metacube examples # copy to current directory
metacube examples --dest my_data/ # copy to my_data/
metacube examples --list # print file names only
Python API
from metacube import csv_to_cube_data, build_html, serve
# Transform
data = csv_to_cube_data("data.csv", "config.yaml")
# Export standalone HTML
build_html(data, "viz.html")
# Serve locally
serve(data, port=8000, open_browser=True)
Step-by-step Workflow
# 1. Transform CSV → JSON (once, reuse for multiple outputs)
metacube transform dataset.csv --config config.yaml --output data.json
# 2a. Explore in browser
metacube serve data.json
# 2b. Or export for sharing
metacube build data.json --output shareable.html
Config YAML Reference
Full reference with all modes and examples: docs/config.md
The config YAML maps CSV columns to visualization axes and enables optional features.
Minimal config
title: "My Dataset"
axes:
x:
label: "Species"
column: "species"
y:
label: "Assay"
column: "assay"
z:
label: "Tissue"
column: "tissue"
size_colour: "cell_count"
Full config with all options
title: "My Dataset"
axes:
x:
label: "Organism"
column: "organism"
max_labels: 5 # keep only top N values by count (optional)
colors: # per-value hex colors (optional)
"Human": "#3b82f6"
"Mouse": "#10b981"
group_separator: " - " # group axis labels by prefix (optional)
y:
label: "Assay"
column: "assay"
max_labels: 20
z:
label: "Tissue"
column: "tissue"
max_labels: 30
size_colour: "cell_count" # numeric column for color gradient (omit for flat blue)
datasets_column: "dataset_id" # column of dataset IDs, shown in hover tooltip (optional)
# ── Drilldown: click a cell to see more detail ────────────────────────────────
drilldown:
# Option A: treemap popup (floating panel, stays alongside the cube)
type: "treemap"
category_column: "dataset_title" # outer grouping in the treemap
subcategory_column: "cell_type" # inner tiles in the treemap
count_column: "cell_count" # column to sum for tile size
# Option B: zoom into a finer-grained inner cube
# type: "zoom"
# axes:
# z: # redefine one or more axes
# label: "Organ"
# column: "organ"
# max_labels: 30
# size_colour: "cell_count"
# treemap: # optional: also show treemap panel in zoom view
# category_column: "dataset_title"
# subcategory_column: "cell_type"
# count_column: "cell_count"
# ── Slice: 2D matrix for the selected cell ───────────────────────────────────
slice:
fixed_axis: "x" # "x", "y", or "z" — the axis held fixed
count_column: "cell_count" # column to aggregate (optional)
# ── Info panel: structured text on click ─────────────────────────────────────
info:
columns:
title: "study_title"
author: "first_author"
year: "year"
doi: "doi"
url: "url"
# ── Axis ordering ─────────────────────────────────────────────────────────────
axis_order: "frequency" # "frequency" (default) or "cluster"
# frequency: labels ordered by descending total count
# (same rank as max_labels — most common first)
# cluster: after max_labels selection, labels are reordered
# by average-linkage cosine clustering on their
# co-occurrence profiles across the other two axes.
# Groups categories with similar occupancy patterns.
Config options summary
| Field | Required | Description |
|---|---|---|
title |
no | Visualization title shown in the header |
axes.{x,y,z}.column |
yes | CSV column name for each axis |
axes.{x,y,z}.label |
no | Display label (defaults to column name) |
axes.{x,y,z}.max_labels |
no | Keep only top N values by count |
axes.{x,y,z}.colors |
no | Map of value → hex color |
axes.{x,y,z}.group_separator |
no | String to split labels into groups |
size_colour |
no | Numeric column for colour gradient (omit for flat blue) |
datasets_column |
no | Column of dataset/study IDs, shown in hover tooltip |
drilldown |
no | Drilldown config (treemap or zoom) |
slice |
no | 2D matrix slice in the details panel |
info |
no | Structured entries shown as center modal on cell click |
info_box |
no | Structured entries shown inline in the side panel on cell click |
axis_order |
no | "frequency" (default) or "cluster" — see below |
axis_order: "frequency" (default): labels are presented in descending order of total count, matching the max_labels selection rank.
axis_order: "cluster": after max_labels selection, each axis is reordered by average-linkage hierarchical clustering on co-occurrence profiles. Each label becomes a row vector of its counts across all combinations of the other two axes (mode-k tensor unfolding); rows are L2-normalised and pairwise cosine distances feed scipy.cluster.hierarchy.linkage(method="average"). This groups categories with similar occupancy patterns together, making large-scale structure easier to read. This uses scipy, which is installed as a dependency of metacube. The R package uses stats::hclust and needs no additional dependencies.
Complete Example
Given a CSV data.csv:
organism,assay,tissue,study,cell_type,count
Human,scRNA-seq,blood,Study A,T cell,5000
Human,scRNA-seq,blood,Study A,B cell,2000
Human,scRNA-seq,liver,Study B,hepatocyte,8000
Mouse,scRNA-seq,blood,Study C,T cell,3000
And config.yaml:
title: "Single-cell Atlas"
axes:
x:
label: "Organism"
column: "organism"
y:
label: "Assay"
column: "assay"
z:
label: "Tissue"
column: "tissue"
size_colour: "count"
drilldown:
type: "treemap"
category_column: "study"
subcategory_column: "cell_type"
count_column: "count"
slice:
fixed_axis: "x"
count_column: "count"
metacube export data.csv --config config.yaml --output atlas.html
# Open atlas.html in any browser — no server needed
License
MIT — see LICENSE.
Metadata
Release files for metacube 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| metacube-0.1.0.tar.gz | 1.5 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| metacube-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.0 MB
Release files / metacube-0.1.0.tar.gz
| Download URL | metacube-0.1.0.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f76d55710436c57897e2317383281b996faf3f8baa855de681a1b7885911cf11
|
|
BLAKE2b-256 checksum How to use checksums |
c2c43fd5c6020e92b1fb15e7e3e3ede84dfae543b0dc909c877391ae5c72a408
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / metacube-0.1.0-py3-none-any.whl
| Download URL | metacube-0.1.0-py3-none-any.whl |
|---|---|
| Size | 1.5 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
29c5feaa35ffcfc18241f1397d4f0f219301d346163508769b8407baab3c3e21
|
|
BLAKE2b-256 checksum How to use checksums |
dc2f5dc61cccd6e88f56bde54bc42560f6f6cdb6633dac3e2a98ee9ab8d7e5c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|