agentsclimarketplace

Interactive visualization

Skill BioTender-max/awesome-bio-agent-skills/skills/bioskills/interactive-visualization

A curated collection of AI agent skills for biomedical research, covering genomics, proteomics, single-cell analysis, clinical AI, and protein design.

Install
npx -y skills add BioTender-max/awesome-bio-agent-skills --skill interactive-visualization

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.

What its author says it does

Copied from the file, not written here

Build interactive HTML/web visualizations with plotly (Python/R), bokeh (Python), and gganimate/plotly frames for animation, with awareness of current Kaleido static-export model (post-orca-EOL), HTML file-size bloat, and the limits of interactive-only output for journal submission. Use when producing zoomable/hoverable plots for notebook EDA, supplementary HTML, dashboards, or animated time-course / iteration visualizations.

SKILL.md

11.5 KB, as published. Nobody here has run it

Version Compatibility

Reference examples tested with: plotly 5.24+, plotly R 4.10+, bokeh 3.4+, kaleido 1.0+ (note: v1 dropped bundled Chrome), gganimate 1.0.9+, altair 5.4+, htmlwidgets 1.6+.

Before using code patterns, verify installed versions match. If versions differ:

  • Python: pip show <package> then help(module.function)
  • R: packageVersion('<pkg>') then ?function_name

If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.

Interactive Visualization

"Build an interactive plot" -> Render a zoomable, hoverable, panable HTML/web visualization, knowing that interactive output is a SUPPLEMENT to (not replacement for) the static figure needed for journal submission. Choose plotly for fastest onboarding and ggplot2 conversion (ggplotly); bokeh for streaming/server-side; altair for grammar-of-graphics; D3.js for full custom.

  • Python: plotly.graph_objects, plotly.express, bokeh, altair
  • R: plotly (via ggplotly), htmlwidgets ecosystem (leaflet, networkD3, DT)

The Single Most Important Modern Insight -- Kaleido v1 and the Static-Export Pipeline

Interactive plots produce HTML, but journals need static PDF/PNG. The plotly static-export pipeline changed materially in 2025:

  • Orca is end-of-life (deprecated 2021, removed pipeline 2025)
  • fig.write_image(..., engine='orca') removed in plotly 6.2 (post-Sept 2025)
  • Kaleido v1+ is the current standard — pass no engine= argument
  • Kaleido v1 dropped bundled Chrome — requires installed Chrome / Chromium
  • EPS export removed in Kaleido v1 (was supported via orca's bundled Chromium)

For static export of plotly figures in 2026: pip install kaleido; verify Chrome installed; fig.write_image('out.pdf'). Test by writing to a known path and inspecting file size; silent failure on missing Chrome was a 2024-2025 pain point that v1 partially addresses with clearer errors.

Interactive vs Static — The Reproducibility Cost

Interactive HTML has hidden trade-offs:

  • File size: a 5000-point plotly HTML is 3-5 MB (embedded JS bundle). 50000 points crashes browsers without WebGL acceleration.
  • Non-citable: a paper figure must be static. Always export static alongside.
  • Browser version drift: HTML from 2020 plotly may not render in 2026 browsers.
  • Cannot be alt-text described: accessibility weaker than static.

Use interactive for notebooks (exploration), supplementary HTML (online journal supplement), dashboards (Streamlit/Dash/Shiny). For the journal figure, always also produce static.

plotly (Python) — Standard Interactive

Goal: Build an interactive HTML plot with zoom, pan, and hover-tooltip behavior; export both interactive HTML for supplements and static PDF for the journal figure.

Approach: Use plotly.express for declarative high-level plots OR graph_objects for fine control; enable WebGL via render_mode='webgl' or Scattergl for >5000 points; export HTML with write_html() and static with write_image() after installing Kaleido v1+ and Chrome.

import plotly.express as px
import plotly.graph_objects as go

# Express: high-level, declarative
fig = px.scatter(df, x='PC1', y='PC2', color='cluster',
                  hover_data=['gene_count', 'sample_id'],
                  color_discrete_sequence=['#0072B2', '#D55E00', '#009E73'],
                  title='PCA')
fig.update_layout(template='plotly_white', width=600, height=500)

# WebGL acceleration for >5000 points
fig = px.scatter(df, x='PC1', y='PC2', color='cluster', render_mode='webgl')

# Save
fig.write_html('pca.html')
fig.write_image('pca.pdf')                   # requires kaleido + Chrome

# Graph_objects: low-level
fig = go.Figure(go.Scattergl(                 # Scattergl == WebGL scatter
    x=df['PC1'], y=df['PC2'],
    mode='markers',
    marker=dict(color=df['cluster_code'], colorscale='Tab10', size=4),
    text=df['sample_id'], hoverinfo='text'))

plotly (R) — ggplotly Conversion

library(plotly)
library(ggplot2)

p <- ggplot(df, aes(x = PC1, y = PC2, color = cluster, text = sample_id)) +
    geom_point() + theme_classic()

# Convert ggplot to interactive plotly
p_int <- ggplotly(p, tooltip = c('text', 'x', 'y', 'colour'))

# Save
htmlwidgets::saveWidget(p_int, 'pca.html', selfcontained = TRUE)

ggplotly is the lowest-friction R interactive path — write ggplot, get plotly.

bokeh (Python) — Server-Side / Streaming

from bokeh.plotting import figure, output_file, save
from bokeh.models import ColumnDataSource, HoverTool

output_file('pca_bokeh.html')

source = ColumnDataSource(df)
p = figure(title='PCA', x_axis_label='PC1', y_axis_label='PC2',
           tools='pan,wheel_zoom,box_zoom,reset,hover,save')
p.scatter('PC1', 'PC2', source=source, size=8, alpha=0.7,
          color={'field': 'cluster', 'transform': cluster_cmap})
p.add_tools(HoverTool(tooltips=[('Sample', '@sample_id'), ('Cluster', '@cluster')]))
save(p)

bokeh is stronger than plotly for streaming dashboards and server-side aggregation. Static export via bokeh.io.export_png requires selenium + Chrome.

Animation — gganimate (R) and plotly frames (Python)

library(gganimate)
p <- ggplot(df, aes(x, y, color = condition)) +
    geom_point(size = 3) +
    theme_classic() +
    transition_time(time) +                  # animate over time
    labs(title = 'Time: {frame_time}')

anim <- animate(p, nframes = 100, fps = 20, width = 600, height = 400,
                 renderer = gifski_renderer())
anim_save('time_course.gif', anim)
import plotly.express as px
fig = px.scatter(df, x='x', y='y', color='condition',
                  animation_frame='time',
                  animation_group='entity_id',
                  range_x=[xmin, xmax], range_y=[ymin, ymax])
fig.write_html('time_course.html')

Animation suits time-course data, iterative algorithm visualization, before-after comparisons. Limit to ≤100 frames; longer animations bloat file size and tax viewer attention.

htmlwidgets Ecosystem (R)

library(DT)                                 # interactive tables
datatable(df, filter = 'top', extensions = 'Buttons',
          options = list(dom = 'Bfrtip', buttons = c('csv', 'excel')))

library(leaflet)                            # interactive maps
leaflet(spatial_df) %>% addTiles() %>% addCircles()

library(networkD3)                          # interactive networks
sankeyNetwork(...) %>% saveWidget('sankey.html')

htmlwidgets is the R answer to plotly's JavaScript wrapping — many specialized packages for tables, maps, networks, all producing standalone HTML.

Per-Method Failure Modes

plotly static export silently fails

Trigger: fig.write_image('out.pdf') without kaleido installed.

Mechanism: plotly previously fell back to orca (now removed); current versions raise ValueError but older versions silently skipped.

Symptom: No file written; OR file written with default settings.

Fix: pip install kaleido; verify Chrome is installed (kaleido v1+ requires it); test with fig.write_image('test.pdf') after install.

orca dependency in older code

Trigger: Following 2020-2022 plotly tutorials with engine='orca'.

Mechanism: orca is EOL; engine= parameter deprecated in plotly 6.2 (post-Sep 2025).

Symptom: ValueError or DeprecationWarning.

Fix: Remove engine= argument; use Kaleido v1 (default).

EPS export needed but Kaleido v1 dropped it

Trigger: Journal requires EPS; Kaleido v1 only supports PDF/PNG/SVG/JPG/WebP.

Mechanism: Bundled Chromium in v0 supported EPS; v1 unbundled and dropped it.

Symptom: kaleido error on EPS export.

Fix: Export PDF, then convert via pdf2ps (ghostscript). For complex figures may produce raster EPS — verify acceptability with journal.

HTML file > 10 MB

Trigger: Plotly scatter of 50000 points exported as HTML.

Mechanism: Each point + hover data embedded; JS bundle ~3 MB; data scales linearly.

Symptom: Browser hangs opening; reviewer's network throttles upload.

Fix: Use Scattergl (WebGL); OR Datashader pre-aggregation; OR ship static + small HTML supplement.

gganimate slow on large frames

Trigger: transition_time with 100+ frames and 10000+ points per frame.

Mechanism: Each frame rendered independently.

Symptom: Animation takes hours.

Fix: Downsample frames; pre-aggregate per-frame data; OR use plotly animation (in-browser interpolation faster).

Interactive plot shown as figure in paper

Trigger: Manuscript references interactive HTML as Figure 2.

Mechanism: Journals require static; interactive HTML is supplement.

Symptom: Submission requires figure resubmission as static.

Fix: Always produce both static (figure) + interactive (supplement) versions.

Reconciliation

PatternCauseAction
Kaleido / orca confusion in plotlyPipeline changed 2024-2025Use Kaleido v1+; no engine=
ggplotly drops some custom themeConversion loses non-translatable ggplot elementsManually re-add via plotly::layout()
bokeh static export failsselenium not installedpip install selenium; Chrome required
htmlwidgets self-contained doesn't work offlineCDN-linked resources by defaultsaveWidget(..., selfcontained = TRUE)

Quantitative Thresholds

ThresholdValueSource
HTML file size warning>10 MBPractical
Scattergl trigger>5000 pointsplotly performance
Animation max frames~100Viewer attention + file size
Selfcontained HTML onalways for portabilityhtmlwidgets best practice

Common Errors

Error / symptomCauseSolution
Static export silent failurekaleido / Chrome missingInstall both
HTML bloatedLarge N pointsScattergl or Datashader
orca DeprecationWarningFollowing old tutorialRemove engine=, use Kaleido v1
EPS export failsKaleido v1 dropped EPSPDF + pdf2ps
ggplotly tooltips show wrong fieldsDefault tooltip argumentSpecify tooltip = c(...)
Animation file too largeToo many framesDownsample / pre-aggregate
Interactive cited as paper figureJournal requires staticProduce both

References

  • Sievert C. 2020. Interactive Web-Based Data Visualization with R, plotly, and shiny. Chapman and Hall/CRC.
  • Plotly Python — Static Image Generation Changes (2024-2025). https://plotly.com/python/static-image-generation-changes/
  • Bostock M, Ogievetsky V, Heer J. 2011. D³ Data-Driven Documents. IEEE TVCG 17(12):2301-2309.
  • Wickham H, Pedersen TL, Seidel D. 2022. gganimate (CRAN). https://gganimate.com

Related Skills

  • reporting/quarto-reports - Embed interactive HTML in scientific reports
  • reporting/rmarkdown-reports - htmlwidgets in Rmd
  • data-visualization/ggplot2-fundamentals - ggplot input for ggplotly
  • data-visualization/dimensionality-reduction-plots - Interactive UMAP/PCA exploration
  • data-visualization/network-visualization - PyVis interactive networks

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.