| name | marsilea-visualization |
| description | Marsilea 可视化 Agent Skill:根据数据分析、真实数据案例或作图需求,生成可运行的 Python / Jupyter 示例, 覆盖注释热图、分组热图、聚类树、SizedHeatmap、CatHeatmap、layered heatmap、 ClusterBoard 布局、UpSet 图、Kaggle 数据集选型,并包含 uv/Jupyter 环境管理、中文字体处理、可复现实例和导出校验。 Marsilea visualization Agent Skill: turn data-analysis, real-world dataset, or plotting requests into runnable Python / Jupyter examples for annotated heatmaps, grouped heatmaps, dendrograms, SizedHeatmap, CatHeatmap, layered heatmaps, ClusterBoard layouts, UpSet plots, and Kaggle dataset selection, with uv/Jupyter setup, Chinese font handling, reproducible examples, and export checks.
|
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["marsilea","visualization","matplotlib","heatmap","upset","jupyter","uv","python"],"category":"data-science"}} |
Marsilea Visualization Skill
Use this skill when the user asks to create, debug, explain, or package examples for
Marsilea, a Python library for declarative,
composable visualizations built on top of Matplotlib.
Prefer Marsilea when the visualization needs multiple coordinated components:
- heatmap + row/column annotations
- heatmap + dendrogram + labels + bars
- grouped matrix visualization
- sized heatmap / Hinton-like diagram
- categorical heatmap
- layered heatmap with markers/shapes
- UpSet plot for multi-set intersections
- real-world dataset selection (Kaggle / UCI / local CSV)
- publication-quality composite figure assembled incrementally
Core mental model
Marsilea is declarative and composable:
- Create a main board or high-level visualization.
- Add plotters to the main layer or to sides.
- Optionally group/cut rows or columns.
- Add dendrograms, titles, legends, and margin.
- Render and save.
Common imports:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import marsilea as ma
import marsilea.plotter as mp
from marsilea.upset import UpsetData, Upset
Environment setup with uv
For a fresh example project:
uv init --bare --name marsilea-demo --python 3.11
uv add marsilea jupyter ipykernel matplotlib numpy pandas seaborn scipy
uv run jupyter lab
For command-line verification of a notebook:
uv run jupyter nbconvert --to notebook --execute notebook.ipynb --output executed.ipynb
For a standalone script:
uv run python script.py
Chinese font handling
When the notebook or figure contains Chinese labels, add this setup cell before plotting:
from matplotlib import pyplot as plt, font_manager
import warnings
preferred_fonts = [
"PingFang SC", "Hiragino Sans GB", "Heiti TC", "Songti SC",
"Arial Unicode MS", "Noto Sans CJK SC", "Microsoft YaHei", "SimHei",
]
available_fonts = {f.name for f in font_manager.fontManager.ttflist}
for font in preferred_fonts:
if font in available_fonts:
plt.rcParams["font.sans-serif"] = [font]
break
else:
warnings.warn("未找到常见中文字体;图中的中文可能显示为方框。")
plt.rcParams["axes.unicode_minus"] = False
Basic annotated heatmap template
Use this when the user wants a practical Marsilea demo or a scientific heatmap with
side annotations.
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import marsilea as ma
import marsilea.plotter as mp
rng = np.random.default_rng(2026)
out = Path("outputs")
out.mkdir(exist_ok=True)
genes = [f"Gene {i:02d}" for i in range(1, 13)]
samples = [f"S{i:02d}" for i in range(1, 11)]
row_groups = np.array(["Inflammation"] * 4 + ["Metabolism"] * 4 + ["Repair"] * 4)
col_groups = np.array(["Before"] * 3 + ["During"] * 4 + ["After"] * 3)
data = rng.normal(0, 1, size=(12, 10))
data[:4, 3:7] += 1.2
data[4:8, :3] -= 0.8
data[8:, 7:] += 1.0
expr = pd.DataFrame(data, index=genes, columns=samples)
row_palette = {"Inflammation": "#E64B35", "Metabolism": "#4DBBD5", "Repair": "#00A087"}
col_palette = {"Before": "#3C5488", "During": "#F39B7F", "After": "#8491B4"}
h = ma.Heatmap(
expr.values,
cmap="coolwarm",
linewidth=0.5,
linecolor="white",
height=4.5,
width=5.5,
label="Z-score",
)
h.group_rows(row_groups, order=["Inflammation", "Metabolism", "Repair"], spacing=0.04)
h.group_cols(col_groups, order=["Before", "During", "After"], spacing=0.04)
h.add_left(mp.Colors(row_groups, palette=row_palette, label="Gene module"), size=0.18, pad=0.05)
h.add_top(mp.Colors(col_groups, palette=col_palette, label="Stage"), size=0.18, pad=0.05)
h.add_dendrogram("left")
h.add_dendrogram("top")
h.add_layer(mp.MarkerMesh(expr.values > 1.5, color="black", marker="*", size=45, label="> 1.5"), zorder=10)
h.add_right(mp.Labels(genes, align="center"), pad=0.05)
h.add_bottom(mp.Bar(expr.mean(axis=0).values, color="#5F9EA0", label="Sample mean"), size=0.7, pad=0.1)
h.add_title(top="Annotated Marsilea heatmap")
h.add_legends()
h.render()
h.save(out / "annotated_heatmap.png", dpi=180)
plt.close("all")
SizedHeatmap template
Use when each cell has both magnitude and color/effect information.
size_data = np.abs(rng.normal(size=(8, 8)))
color_data = rng.normal(size=(8, 8))
s = ma.SizedHeatmap(
size=size_data,
color=color_data,
cmap="PiYG",
marker="s",
height=4,
width=4,
label="Effect",
)
s.add_title(top="SizedHeatmap: size + color")
s.add_legends()
s.render()
s.save("outputs/sized_heatmap.png", dpi=180)
CatHeatmap template
Use for categorical matrices such as states, mutation classes, QC labels, or user-feature status.
status_levels = ["Normal", "Low", "High", "Missing"]
palette = {
"Normal": "#7CAE00",
"Low": "#00BFC4",
"High": "#F8766D",
"Missing": "#BDBDBD",
}
status = rng.choice(status_levels, size=(10, 12), p=[0.55, 0.18, 0.18, 0.09])
row_batch = np.array(["Batch A"] * 5 + ["Batch B"] * 5)
c = ma.CatHeatmap(status, palette=palette, linewidth=0.5, linecolor="white", height=4, width=5.5, label="Status")
c.group_rows(row_batch, order=["Batch A", "Batch B"], spacing=0.05)
c.add_left(mp.Colors(row_batch, palette={"Batch A": "#8DA0CB", "Batch B": "#FC8D62"}, label="Batch"), size=0.18, pad=0.05)
c.add_title(top="Categorical heatmap")
c.add_legends()
c.render()
c.save("outputs/categorical_heatmap.png", dpi=180)
UpSet template
Use when there are more than 3 sets or when Venn diagrams become unreadable.
from marsilea.upset import UpsetData, Upset
sets = [
{"Alice", "Bob", "Carol", "David"},
{"Carol", "David", "Eve", "Frank"},
{"Alice", "David", "Eve", "Grace"},
{"Bob", "Carol", "Frank", "Grace"},
]
set_names = ["Python", "R", "SQL", "Visualization"]
upset_data = UpsetData.from_sets(sets, sets_names=set_names)
us = Upset(upset_data, min_cardinality=1, add_labels="left", add_sets_size="right", height=4.5, width=6)
us.highlight_subsets(facecolor="#E64B35", label="Intersection size >= 2", min_cardinality=2)
us.add_legends()
us.add_title(top="UpSet plot")
us.render()
us.save("outputs/upset.png", dpi=180)
Declarative API cheat sheet
add_layer(plotter): add a plotter to the main canvas.
add_left(plotter, size=..., pad=...): add a plotter to the left side.
add_right(plotter, size=..., pad=...): add a plotter to the right side.
add_top(plotter, size=..., pad=...): add a plotter above the main plot.
add_bottom(plotter, size=..., pad=...): add a plotter below the main plot.
group_rows(labels, order=..., spacing=...): split rows by labels.
group_cols(labels, order=..., spacing=...): split columns by labels.
cut_rows([positions]): split rows by numeric cut positions.
cut_cols([positions]): split columns by numeric cut positions.
add_dendrogram("left" | "right" | "top" | "bottom"): add hierarchical clustering.
add_title(top=..., bottom=..., left=..., right=...): add figure titles.
add_legends(): collect and draw legends from plotters.
render(): draw the figure.
save(path, dpi=300): save the result.
board.figure: access the underlying Matplotlib figure.
Plotter selection guide
- Continuous matrix:
ma.Heatmap or mp.ColorMesh
- Categorical annotation/color strip:
mp.Colors
- Cell marker overlay:
mp.MarkerMesh
- Text labels:
mp.Labels, mp.TextMesh
- Bar annotation:
mp.Bar, mp.Numbers, mp.StackBar
- Distribution annotation:
mp.Box, mp.Violin, mp.Strip, mp.Swarm, mp.Point
- Group labels:
mp.Chunk, mp.FixedChunk
- Sized elements:
ma.SizedHeatmap, mp.SizedMesh
- Categorical matrix:
ma.CatHeatmap
- Set intersections:
UpsetData, Upset
Workflow for creating a Marsilea notebook
- Clarify the data shape and semantic mapping:
- rows/columns meaning
- continuous vs categorical values
- row/column metadata
- desired side annotations
- output file type and size
- Create a uv-managed project if one does not exist.
- Add a first cell for imports, deterministic RNG, output directory, and Chinese fonts if needed.
- Build examples from simple to complex:
- basic plot
- grouping
- side annotations
- dendrograms
- overlays
- legends/titles
- save outputs
- Verify top-to-bottom execution with nbconvert.
- Keep generated outputs out of git unless the user explicitly wants committed images.
Verification checklist
Before finalizing:
uv run python - <<'PY'
import marsilea as ma
import marsilea.plotter as mp
from marsilea.upset import UpsetData, Upset
print('marsilea', getattr(ma, '__version__', 'unknown'))
PY
For notebooks:
uv run jupyter nbconvert --to notebook --execute notebook.ipynb --output executed.ipynb
For scripts:
uv run python script.py
Confirm that expected output files exist and are non-empty.
Common pitfalls
group_rows() labels length must match the number of rows; group_cols() labels length must match the number of columns.
- Use
order=[...] when group display order matters.
size and pad are in inches for side plots.
- Call
render() before displaying or saving if the figure has not been rendered.
- Call
add_legends() after adding plotters that have labels.
- For Chinese labels, configure a CJK font before rendering.
- Close figures in batch scripts with
plt.close("all") to avoid memory growth.
- If labels are clipped, increase
margin, use set_margin(), or save via board.figure.savefig(..., bbox_inches="tight").
- Marsilea examples may depend on API version; verify signatures with
inspect.signature(...) when debugging.
References