Skip to content
cccskills
FreePublished on GitHub

plotly-interactive-visualization

Interactive visualization with Plotly. 40+ chart types (scatter, line, heatmap, 3D, geographic) with hover, zoom, pan. Two APIs: Plotly Express (DataFrame) and Graph Objects (fine control). For static publication figures use matplotlib; for statistical grammar use seaborn.

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md17.8 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Plotly — Interactive Scientific Visualization

Overview

Plotly is a Python graphing library for interactive, web-embeddable visualizations with 40+ chart types. It provides two APIs: Plotly Express (high-level, pandas-native) for quick plots and Graph Objects (low-level) for full customization. Output to interactive HTML, static PNG/PDF/SVG, or Dash web apps.

When to Use

  • Creating interactive charts with hover tooltips, zoom, and pan
  • Building multi-panel exploratory dashboards for data analysis
  • Visualizing 3D data (surfaces, scatter3d, mesh, volume)
  • Making geographic/map visualizations (choropleth, scatter_geo)
  • Presenting data in web-embeddable HTML format
  • Statistical distribution comparison (violin, box, histogram with marginals)
  • Time series with range sliders and animation frames
  • For static publication-quality figures (journal submissions), use matplotlib instead
  • For statistical grammar-of-graphics style, use seaborn instead

Prerequisites

  • Python packages: plotly, pandas, numpy
  • For static export: kaleido (PNG/PDF/SVG rendering)
  • For web apps: dash (optional)
pip install plotly kaleido

Quick Start

import plotly.express as px
import pandas as pd
import numpy as np

# Sample data
np.random.seed(42)
df = pd.DataFrame({
    "x": np.random.randn(200),
    "y": np.random.randn(200),
    "group": np.random.choice(["A", "B", "C"], 200),
    "size": np.random.uniform(5, 20, 200),
})

fig = px.scatter(df, x="x", y="y", color="group", size="size",
                 title="Interactive Scatter Plot", hover_data=["group"])
fig.write_html("scatter.html")
fig.write_image("scatter.png", width=800, height=500, scale=2)
print("Saved scatter.html and scatter.png")

Core API

1. Plotly Express (High-Level API)

Quick, one-line charts from pandas DataFrames. Returns go.Figure objects that can be further customized.

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    "temperature": np.linspace(20, 80, 50),
    "yield": 50 + 0.8 * np.linspace(20, 80, 50) + np.random.randn(50) * 5,
    "catalyst": np.random.choice(["Pd", "Pt", "Rh"], 50),
})

# Scatter with trendline
fig = px.scatter(df, x="temperature", y="yield", color="catalyst",
                 trendline="ols", title="Temperature vs Yield")
fig.write_image("scatter_trend.png", width=700, height=450)
print("Saved scatter_trend.png")

# Bar chart
summary = df.groupby("catalyst")["yield"].mean().reset_index()
fig = px.bar(summary, x="catalyst", y="yield", color="catalyst",
             title="Mean Yield by Catalyst")
fig.write_image("bar_catalyst.png", width=600, height=400)
print("Saved bar_catalyst.png")
# Heatmap from correlation matrix
import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(42)
data = pd.DataFrame(np.random.randn(100, 5), columns=["Gene_A", "Gene_B", "Gene_C", "Gene_D", "Gene_E"])
corr = data.corr()

fig = px.imshow(corr, text_auto=".2f", color_continuous_scale="RdBu_r",
                zmin=-1, zmax=1, title="Gene Expression Correlation")
fig.write_image("heatmap.png", width=600, height=500)
print("Saved heatmap.png")

2. Graph Objects (Low-Level API)

Full control over individual traces, layouts, and annotations.

import plotly.graph_objects as go
import numpy as np

# 3D surface plot
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))

fig = go.Figure(data=[go.Surface(z=Z, x=X[0], y=y, colorscale="Viridis")])
fig.update_layout(title="3D Surface Plot",
                  scene=dict(xaxis_title="X", yaxis_title="Y", zaxis_title="Z"))
fig.write_image("surface_3d.png", width=700, height=500)
print("Saved surface_3d.png")
# Multi-trace figure with custom styling
import plotly.graph_objects as go
import numpy as np

np.random.seed(42)
x = np.linspace(0, 10, 100)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=np.sin(x), mode="lines", name="sin(x)",
                         line=dict(color="blue", width=2)))
fig.add_trace(go.Scatter(x=x, y=np.cos(x), mode="lines", name="cos(x)",
                         line=dict(color="red", width=2, dash="dash")))
fig.add_hline(y=0, line_dash="dot", line_color="gray", opacity=0.5)
fig.add_annotation(x=np.pi/2, y=1, text="sin peak", showarrow=True, arrowhead=2)

fig.update_layout(template="plotly_white", title="Trigonometric Functions",
                  xaxis_title="x", yaxis_title="f(x)")
fig.write_image("multi_trace.png", width=700, height=400)
print("Saved multi_trace.png")

3. Subplots and Multi-Panel Layouts

Create figure grids with shared or independent axes.

from plotly.subplots import make_subplots
import plotly.graph_objects as go
import numpy as np

np.random.seed(42)
data = np.random.randn(500)

fig = make_subplots(
    rows=2, cols=2,
    subplot_titles=("Histogram", "Box Plot", "Scatter", "Violin"),
    specs=[[{"type": "histogram"}, {"type": "box"}],
           [{"type": "scatter"}, {"type": "violin"}]],
)

fig.add_trace(go.Histogram(x=data, nbinsx=30, name="Hist"), row=1, col=1)
fig.add_trace(go.Box(y=data, name="Box"), row=1, col=2)
fig.add_trace(go.Scatter(x=data[:100], y=data[100:200], mode="markers", name="Scatter"), row=2, col=1)
fig.add_trace(go.Violin(y=data, name="Violin", box_visible=True), row=2, col=2)

fig.update_layout(height=700, width=800, title_text="Multi-Panel Dashboard", showlegend=False)
fig.write_image("subplots.png", width=800, height=700)
print("Saved subplots.png")

4. Statistical Charts

Distribution comparison, error bars, and statistical annotations.

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    "value": np.concatenate([np.random.normal(0, 1, 100), np.random.normal(2, 1.5, 100)]),
    "group": ["Control"] * 100 + ["Treatment"] * 100,
})

# Histogram with marginal box plot
fig = px.histogram(df, x="value", color="group", marginal="box",
                   nbins=30, barmode="overlay", opacity=0.7,
                   title="Distribution Comparison")
fig.write_image("stat_hist.png", width=700, height=450)
print("Saved stat_hist.png")

# Violin plot with individual points
fig = px.violin(df, x="group", y="value", box=True, points="all",
                title="Treatment Effect (Violin + Points)")
fig.write_image("violin.png", width=500, height=450)
print("Saved violin.png")
# Error bars
import plotly.graph_objects as go
import numpy as np

conditions = ["Control", "Low Dose", "Med Dose", "High Dose"]
means = [5.2, 7.1, 9.8, 11.3]
sems = [0.4, 0.6, 0.5, 0.8]

fig = go.Figure(data=[go.Bar(
    x=conditions, y=means,
    error_y=dict(type="data", array=sems, visible=True),
    marker_color=["#636EFA", "#EF553B", "#00CC96", "#AB63FA"],
)])
fig.update_layout(title="Dose Response (mean ± SEM)", yaxis_title="Response",
                  template="plotly_white")
fig.write_image("error_bars.png", width=600, height=400)
print("Saved error_bars.png")

5. Export and Rendering

Save to interactive HTML, static images, or embed in notebooks.

import plotly.express as px
import pandas as pd

df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")

# Interactive HTML (full standalone)
fig.write_html("interactive.html")
# HTML with CDN (smaller file, needs internet)
fig.write_html("interactive_cdn.html", include_plotlyjs="cdn")

# Static images (requires kaleido)
fig.write_image("plot.png", width=800, height=500, scale=2)  # 2x resolution
fig.write_image("plot.pdf")  # Vector PDF
fig.write_image("plot.svg")  # Vector SVG

# Get image as bytes (for embedding)
img_bytes = fig.to_image(format="png", width=600, height=400)
print(f"PNG bytes: {len(img_bytes)}")

6. Interactivity Features

Customize hover, animations, buttons, and range sliders.

import plotly.express as px
import pandas as pd
import numpy as np

# Custom hover template
np.random.seed(42)
df = pd.DataFrame({
    "date": pd.date_range("2024-01-01", periods=100),
    "price": 100 + np.cumsum(np.random.randn(100) * 2),
    "volume": np.random.randint(1000, 5000, 100),
})

fig = px.line(df, x="date", y="price", title="Stock Price",
              hover_data={"volume": True, "price": ":.2f"})
fig.update_traces(hovertemplate="<b>%{x|%Y-%m-%d}</b><br>Price: $%{y:.2f}<br>Volume: %{customdata[0]:,}<extra></extra>")
fig.update_xaxes(rangeslider_visible=True)
fig.write_html("timeseries.html")
print("Saved timeseries.html with range slider")

Common Workflows

Workflow 1: Exploratory Data Analysis Dashboard

Goal: Create a multi-panel interactive dashboard for dataset exploration.

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np

# Sample dataset
np.random.seed(42)
n = 300
df = pd.DataFrame({
    "gene_expression": np.random.lognormal(2, 1, n),
    "protein_level": np.random.lognormal(1.5, 0.8, n),
    "cell_type": np.random.choice(["Neuron", "Astrocyte", "Microglia"], n),
    "treatment": np.random.choice(["Control", "Drug_A", "Drug_B"], n),
    "viability": np.random.uniform(0.3, 1.0, n),
})

fig = make_subplots(rows=2, cols=2,
                    subplot_titles=("Expression vs Protein", "Expression by Cell Type",
                                    "Viability by Treatment", "Expression Distribution"))

# Panel 1: Scatter
for ct in df["cell_type"].unique():
    sub = df[df["cell_type"] == ct]
    fig.add_trace(go.Scatter(x=sub["gene_expression"], y=sub["protein_level"],
                             mode="markers", name=ct, opacity=0.6), row=1, col=1)

# Panel 2: Box
for ct in df["cell_type"].unique():
    fig.add_trace(go.Box(y=df[df["cell_type"]==ct]["gene_expression"],
                         name=ct, showlegend=False), row=1, col=2)

# Panel 3: Violin
for tx in df["treatment"].unique():
    fig.add_trace(go.Violin(y=df[df["treatment"]==tx]["viability"],
                            name=tx, showlegend=False, box_visible=True), row=2, col=1)

# Panel 4: Histogram
fig.add_trace(go.Histogram(x=df["gene_expression"], nbinsx=30,
                           name="Expression", showlegend=False), row=2, col=2)

fig.update_layout(height=800, width=1000, title="Exploratory Data Analysis")
fig.write_html("eda_dashboard.html")
fig.write_image("eda_dashboard.png", width=1000, height=800)
print("Saved eda_dashboard.html and eda_dashboard.png")

Workflow 2: Publication Figure with Annotations

Goal: Create a polished, annotated figure suitable for supplementary materials or presentations.

import plotly.graph_objects as go
import numpy as np

np.random.seed(42)
x = np.linspace(0, 24, 100)
control = 50 + 10 * np.sin(x * np.pi / 12) + np.random.randn(100) * 3
treatment = 70 + 15 * np.sin(x * np.pi / 12 + 0.5) + np.random.randn(100) * 4

fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=control, mode="lines", name="Control",
                         line=dict(color="#636EFA", width=2)))
fig.add_trace(go.Scatter(x=x, y=treatment, mode="lines", name="Treatment",
                         line=dict(color="#EF553B", width=2)))

# Add shaded region for treatment window
fig.add_vrect(x0=6, x1=18, fillcolor="yellow", opacity=0.1, line_width=0,
              annotation_text="Treatment Window", annotation_position="top left")

# Add annotation at peak difference
fig.add_annotation(x=12, y=85, text="Peak difference<br>p < 0.001",
                   showarrow=True, arrowhead=2, font=dict(size=11))

fig.update_layout(
    template="plotly_white",
    title="Circadian Response to Treatment",
    xaxis_title="Time (hours)", yaxis_title="Response (AU)",
    font=dict(family="Arial", size=12),
    legend=dict(x=0.02, y=0.98),
    width=700, height=450,
)
fig.write_image("publication_figure.png", width=700, height=450, scale=3)
print("Saved publication_figure.png (3x resolution)")

Key Parameters

ParameterModuleDefaultRange / OptionsEffect
templateupdate_layout"plotly""plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white"Global figure styling theme
color_continuous_scalepx / govaries"Viridis", "Plasma", "RdBu", "RdBu_r", "Blues"Color scale for continuous data
barmodepx.histogram"relative""group", "overlay", "relative", "stack"How multiple histograms are arranged
trendlinepx.scatterNoneNone, "ols", "lowess", "expanding"Regression line overlay
marginalpx.scatter/histogramNoneNone, "rug", "box", "violin", "histogram"Marginal distribution display
scalewrite_image11–5Image resolution multiplier (2=retina, 3=print)
include_plotlyjswrite_htmlTrueTrue, "cdn", "directory", FalseHow Plotly.js is bundled in HTML
opacitymost trace types1.00.0–1.0Trace transparency for overlapping data

Best Practices

  1. Start with Plotly Express, customize with Graph Objects: px functions return go.Figure objects, so you can always add Graph Objects methods after. Don't start with go unless px genuinely cannot express what you need.

    fig = px.scatter(df, x="x", y="y", color="group")
    fig.update_layout(template="plotly_white")  # go method on px figure
    fig.add_hline(y=threshold)
    
  2. Use plotly_white template for publication figures: The default plotly template has a gray background that looks unprofessional in papers. plotly_white or simple_white gives a clean look.

  3. Always set explicit width/height for static export: Without dimensions, write_image uses the default viewport size which may not match your target (journal column width, slide dimensions).

  4. Use scale=2 or higher for print-quality images: Default scale=1 produces 72 DPI equivalent. For publications, use scale=3 (216 DPI effective).

  5. Prefer HTML export for interactive data sharing: HTML files are self-contained and can be opened in any browser without Python. Use include_plotlyjs="cdn" to reduce file size.

Common Recipes

Recipe: Correlation Matrix Heatmap

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame(np.random.randn(100, 6), columns=[f"Var_{i}" for i in range(6)])
corr = df.corr()

# Mask upper triangle
mask = np.triu(np.ones_like(corr, dtype=bool), k=1)
corr_masked = corr.where(~mask)

fig = px.imshow(corr_masked, text_auto=".2f", color_continuous_scale="RdBu_r",
                zmin=-1, zmax=1, title="Correlation Matrix")
fig.write_image("correlation.png", width=600, height=500, scale=2)
print("Saved correlation.png")

Recipe: Animated Scatter Plot

import plotly.express as px
import pandas as pd
import numpy as np

np.random.seed(42)
frames = []
for year in range(2010, 2025):
    n = 50
    frames.append(pd.DataFrame({
        "x": np.random.randn(n) * (year - 2009),
        "y": np.random.randn(n) * (year - 2009),
        "size": np.random.uniform(5, 20, n),
        "year": year,
    }))
df = pd.concat(frames)

fig = px.scatter(df, x="x", y="y", size="size", animation_frame="year",
                 range_x=[-30, 30], range_y=[-30, 30], title="Animated Scatter")
fig.write_html("animated.html")
print("Saved animated.html")

Recipe: Geographic Choropleth Map

import plotly.express as px

# Built-in gapminder dataset
df = px.data.gapminder().query("year == 2007")
fig = px.choropleth(df, locations="iso_alpha", color="gdpPercap",
                    hover_name="country", color_continuous_scale="Plasma",
                    title="GDP per Capita (2007)")
fig.write_image("choropleth.png", width=900, height=500, scale=2)
print("Saved choropleth.png")

Troubleshooting

ProblemCauseSolution
write_image fails with ValueErrorkaleido not installedpip install kaleido
Blank/white image from write_imagePlotly version mismatch with kaleidoUpdate both: pip install --upgrade plotly kaleido
HTML file very large (>10 MB)Full Plotly.js bundledUse fig.write_html(path, include_plotlyjs="cdn")
Hover data not showingColumn not in DataFrame or wrong nameCheck hover_data parameter matches DataFrame columns exactly
Subplot traces appear in wrong panelIncorrect row/col in add_traceVerify row= and col= match your make_subplots grid (1-indexed)
Colors don't match between px and goDifferent default color sequencesSet explicitly: fig.update_layout(colorway=px.colors.qualitative.Plotly)
Animation slow/choppyToo many points per frameReduce data points or use px.scatter with render_mode="webgl" for large datasets

Related Skills

  • matplotlib — static, publication-quality figures for journal submissions (more control over typography and layout)
  • seaborn — statistical visualization with grammar-of-graphics approach (built on matplotlib)
  • scientific-visualization — general principles of scientific figure design and color theory

References

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

API + Python SDK for ordering cell-free protein expression and binding assays. Submit sequences for expression (10–100 µg), measure binding affinity (KD) against targets, track status, and retrieve results programmatically — no wet-lab setup. Built for ML-guided directed evolution and antibody/nanobody optimization. Requires Adaptyv account and API key.

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

aeon

Free

scikit-learn compatible Python toolkit for time series ML: classify, cluster, regress, segment, transform with 30+ algorithms (ROCKET, InceptionTime, KNN-DTW, HIVE-COTE, WEASEL). Handles panel, multivariate, and unequal-length series. Maintained successor to sktime. Alternatives: sktime (larger ecosystem), tslearn (fewer algorithms), catch22 (features only).

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

AiZynthFinder retrosynthetic route planning (CASP) from AstraZeneca Molecular AI. Monte Carlo tree search guided by a template-based neural expansion policy recursively disconnects a target SMILES until precursors are found in a purchasable stock. Covers config.yml (v4 format), aizynthcli batch screening, the AiZynthFinder/AiZynthExpander Python API, one-step disconnections, custom stocks via smiles2stock, scorers, Retro*/breadth-first/DFPN search alternatives, and reading output.json.gz / trees.json. Use for synthesis route planning, synthesizability screening, and building-block/precursor search. For reaction barriers use neb-irc-activation-energy; for 2D reaction scheme drawing use rdkit-chemdraw-cdxml.

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

Access AlphaFold DB's 200M+ predicted structures by UniProt ID. Download PDB/mmCIF, analyze pLDDT/PAE, bulk-fetch proteomes via Google Cloud. For experimental structures use PDB; for prediction use ColabFold or ESMFold.

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

Annotated matrices for single-cell genomics. Stores X with obs/var metadata, layers, embeddings (obsm/varm), graphs (obsp/varp), uns. Use for .h5ad/.zarr I/O, concatenation, scverse integration. For analysis use scanpy; for probabilistic models use scvi-tools.

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

GRN inference from expression via GRNBoost2 (gradient boosting) or GENIE3 (Random Forest). Load matrix, filter by TFs, infer TF-target-importance links, save network. Dask-parallelized to single-cell scale. Core SCENIC component.

The English summary is being prepared. Showing the original description.

jaechang-hits/SciAgent-Skills381Updated Oct 16, 2026

See all skills by jaechang-hits

Report a problem with this skill