Use this skill whenever creating, editing, running, or managing analyses within a LabDash analysis set. Triggers include: "create an analysis," "add a plot," "labdash build," "labdash serve," working with files in an analyses/ directory that has _lib/ and meta.yaml files, editing analysis.py scripts that follow the LabDash contract (run(output_dir) function), discussing the LabDash dashboard or viewer, exporting figures for publication, or any task involving the labdash CLI tool. Also triggers when the user asks to "add a visualization" or "make a figure" in the context of a project that uses LabDash. For scientific best practices during analysis, also load the analysis skill.
LabDash is an AI-agent-friendly analysis and visualization dashboard. Each analysis is a standalone Python script with metadata, producing a figure or table. A browser-based viewer displays results with descriptions, code, and user notes. A local server enables in-browser code editing and re-execution.
For scientific analysis best practices (statistical rigor, visualization philosophy, human-AI responsibilities), see the analysis skill. This skill covers LabDash tool mechanics only.
Every analysis script follows this exact structure:
"""Short title matching meta.yaml title."""
import sys
from pathlib import Path
# Find _lib by walking up from script location
_d = Path(__file__).resolve().parent
while not (_d / "_lib").is_dir():
_d = _d.parent
sys.path.insert(0, str(_d))
from _lib.style import apply_style, RELEVANT_COLORS # import before pyplot (sets agg backend)
import matplotlib.pyplot as plt
from _lib.data_loading import load_data_function
# ── Aesthetic variables ──────────────────────────────────
# (Convention: grouped at top for easy human tweaking)
FIGSIZE = (8, 5)
TITLE = "Title Here"
XLABEL = "X Label"
YLABEL = "Y Label"
# ─────────────────────────────────────────────────────────
def run(output_dir: Path) -> dict:
"""Main entry point. Returns stats dict."""
apply_style()
df = load_data_function()
# ── Analysis ──
stats = {}
# ── Figure ──
fig, ax = plt.subplots(figsize=FIGSIZE)
# ... plotting code ...
# ── Save ──
fig.savefig(output_dir / "output.png", dpi=150, bbox_inches="tight")
plt.close(fig)
return stats
if __name__ == "__main__":
run(Path(__file__).parent)
Aesthetic variables at the top in a clearly marked block between comment lines. Include: FIGSIZE, TITLE, labels, colors, ALPHA, marker sizes, line widths — anything the scientist might want to tweak visually. Always include:
SUPTITLE_Y, TOP_MARGIN, HSPACE, WSPACE, LEGEND_LOC, LABEL_PAD, TITLE_PAD — title/label overlap is the most common visual problem.XLIM = None and YLIM = None (or specific tuples like (0, 1.05)). When None, matplotlib auto-scales. The scientist can set explicit ranges without reading the plotting code.SHARE_Y_AXIS = False. When False, each subplot gets its own y-range (prevents ICL's high RTs from compressing IWL's scale).run(output_dir: Path) -> dict is the callable entry point. The runner imports and calls it. Returns a stats dict (saved as stats.json automatically).
if __name__ == "__main__": makes the script runnable standalone: python analyses/slug/analysis.py. Output goes to the script's own directory.
Import from _lib/ for data loading, preprocessing, and style. Never write custom data loading in an individual analysis.
One script = one output. Each script produces exactly one figure (output.png) or table (output.html). If an analysis naturally has two views, make two analysis directories.
Save the figure explicitly with fig.savefig(output_dir / "output.png", ...) and plt.close(fig).
analysis/ # Top-level analysis directory
├── _lib/ # Shared code across all collections
│ ├── __init__.py
│ ├── data_loading.py # Data loading functions
│ ├── preprocessing.py # Common transforms
│ └── style.py # Colors, fonts, apply_style()
├── my_collection/ # A "collection" — one set of analyses
│ ├── my_analysis/ # One directory per analysis
│ │ ├── analysis.py # The code
│ │ ├── meta.yaml # Metadata (title, group, description, etc.)
│ │ └── notes.md # Scientist's annotations (NEVER EDIT)
│ ├── another_analysis/
│ │ └── ...
├── simulation/ # Another collection (future)
│ └── ...
_output/ # Generated (gitignored)
├── index.html # Static dashboard for active collection
├── my_analysis/
│ ├── output.png # Generated figure
│ └── stats.json # Generated statistics
labdash.yaml # Project config (analyses_dir points to active collection)
Collections: A collection is a subdirectory of analysis/ containing a coherent set of analyses. The _lib/ directory is shared across all collections. labdash.yaml points analyses_dir to the active collection (e.g., analysis/my_collection). Switch collections by changing this path.